From 0e1c5cc78fe24fb9620cac7bdcf7e927ab042ff8 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Wed, 29 May 2019 11:25:20 +0200 Subject: [PATCH] panfrost: Remove link stage for jobs And instead, link them as they are added. Makes things a bit clearer and prepares future work such as FB reload jobs. Signed-off-by: Tomeu Vizoso Reviewed-by: Alyssa Rosenzweig --- src/gallium/drivers/panfrost/pan_context.c | 120 +++++++++++++---------------- src/gallium/drivers/panfrost/pan_context.h | 2 +- 2 files changed, 54 insertions(+), 68 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index b3f89ea..6dab13d 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -384,6 +384,11 @@ panfrost_invalidate_frame(struct panfrost_context *ctx) /* XXX */ ctx->dirty |= PAN_DIRTY_SAMPLERS | PAN_DIRTY_TEXTURES; + + /* Reset job counters */ + ctx->draw_count = 0; + ctx->vertex_job_count = 0; + ctx->tiler_job_count = 0; } /* In practice, every field of these payloads should be configurable @@ -610,6 +615,15 @@ panfrost_default_shader_backend(struct panfrost_context *ctx) memcpy(&ctx->fragment_shader_core, &shader, sizeof(shader)); } +static void +panfrost_link_job_pair(struct mali_job_descriptor_header *first, mali_ptr next) +{ + if (first->job_descriptor_size) + first->next_job_64 = (u64) (uintptr_t) next; + else + first->next_job_32 = (u32) (uintptr_t) next; +} + /* Generates a vertex/tiler job. This is, in some sense, the heart of the * graphics command stream. It should be called once per draw, accordding to * presentations. Set is_tiler for "tiler" jobs (fragment shader jobs, but in @@ -617,10 +631,10 @@ panfrost_default_shader_backend(struct panfrost_context *ctx) * vertex jobs. */ struct panfrost_transfer -panfrost_vertex_tiler_job(struct panfrost_context *ctx, bool is_tiler, bool is_elided_tiler) +panfrost_vertex_tiler_job(struct panfrost_context *ctx, bool is_tiler) { - /* Each draw call corresponds to two jobs, and we want to offset to leave room for the set-value job */ - int draw_job_index = 1 + (2 * ctx->draw_count); + /* Each draw call corresponds to two jobs, and the set-value job is first */ + int draw_job_index = 1 + (2 * ctx->draw_count) + 1; struct mali_job_descriptor_header job = { .job_type = is_tiler ? JOB_TYPE_TILER : JOB_TYPE_VERTEX, @@ -630,19 +644,6 @@ panfrost_vertex_tiler_job(struct panfrost_context *ctx, bool is_tiler, bool is_e #endif }; - /* Only non-elided tiler jobs have dependencies which are known at this point */ - - if (is_tiler && !is_elided_tiler) { - /* Tiler jobs depend on vertex jobs */ - - job.job_dependency_index_1 = draw_job_index; - - /* Tiler jobs also depend on the previous tiler job */ - - if (ctx->draw_count) - job.job_dependency_index_2 = draw_job_index - 1; - } - struct midgard_payload_vertex_tiler *payload = is_tiler ? &ctx->payload_tiler : &ctx->payload_vertex; /* There's some padding hacks on 32-bit */ @@ -653,6 +654,36 @@ panfrost_vertex_tiler_job(struct panfrost_context *ctx, bool is_tiler, bool is_e int offset = 4; #endif struct panfrost_transfer transfer = panfrost_allocate_transient(ctx, sizeof(job) + sizeof(*payload)); + + if (is_tiler) { + /* Tiler jobs depend on vertex jobs */ + + job.job_dependency_index_1 = draw_job_index; + + /* Tiler jobs also depend on the previous tiler job */ + + if (ctx->draw_count) { + job.job_dependency_index_2 = draw_job_index - 1; + /* Previous tiler job points to this tiler job */ + panfrost_link_job_pair(ctx->u_tiler_jobs[ctx->draw_count - 1], transfer.gpu); + } else { + /* The only vertex job so far points to first tiler job */ + panfrost_link_job_pair(ctx->u_vertex_jobs[0], transfer.gpu); + } + } else { + if (ctx->draw_count) { + /* Previous vertex job points to this vertex job */ + panfrost_link_job_pair(ctx->u_vertex_jobs[ctx->draw_count - 1], transfer.gpu); + + /* Last vertex job points to first tiler job */ + panfrost_link_job_pair(&job, ctx->tiler_jobs[0]); + } else { + /* Have the first vertex job depend on the set value job */ + job.job_dependency_index_1 = ctx->u_set_value_job->job_index; + panfrost_link_job_pair(ctx->u_set_value_job, transfer.gpu); + } + } + memcpy(transfer.cpu, &job, sizeof(job)); memcpy(transfer.cpu + sizeof(job) - offset, payload, sizeof(*payload)); return transfer; @@ -667,7 +698,7 @@ panfrost_set_value_job(struct panfrost_context *ctx) struct mali_job_descriptor_header job = { .job_type = JOB_TYPE_SET_VALUE, .job_descriptor_size = 1, - .job_index = 1 + (2 * ctx->draw_count), + .job_index = 1, }; struct mali_payload_set_value payload = { @@ -1285,59 +1316,21 @@ panfrost_queue_draw(struct panfrost_context *ctx) /* Handle dirty flags now */ panfrost_emit_for_draw(ctx, true); - struct panfrost_transfer vertex = panfrost_vertex_tiler_job(ctx, false, false); - struct panfrost_transfer tiler = panfrost_vertex_tiler_job(ctx, true, false); + /* We need a set_value job before any other draw jobs */ + if (ctx->draw_count == 0) + panfrost_set_value_job(ctx); + struct panfrost_transfer vertex = panfrost_vertex_tiler_job(ctx, false); ctx->u_vertex_jobs[ctx->vertex_job_count] = (struct mali_job_descriptor_header *) vertex.cpu; ctx->vertex_jobs[ctx->vertex_job_count++] = vertex.gpu; + struct panfrost_transfer tiler = panfrost_vertex_tiler_job(ctx, true); ctx->u_tiler_jobs[ctx->tiler_job_count] = (struct mali_job_descriptor_header *) tiler.cpu; ctx->tiler_jobs[ctx->tiler_job_count++] = tiler.gpu; ctx->draw_count++; } -/* At the end of the frame, the vertex and tiler jobs are linked together and - * then the fragment job is plonked at the end. Set value job is first for - * unknown reasons. */ - -static void -panfrost_link_job_pair(struct mali_job_descriptor_header *first, mali_ptr next) -{ - if (first->job_descriptor_size) - first->next_job_64 = (u64) (uintptr_t) next; - else - first->next_job_32 = (u32) (uintptr_t) next; -} - -static void -panfrost_link_jobs(struct panfrost_context *ctx) -{ - if (ctx->draw_count) { - /* Generate the set_value_job */ - panfrost_set_value_job(ctx); - - /* Have the first vertex job depend on the set value job */ - ctx->u_vertex_jobs[0]->job_dependency_index_1 = ctx->u_set_value_job->job_index; - - /* SV -> V */ - panfrost_link_job_pair(ctx->u_set_value_job, ctx->vertex_jobs[0]); - } - - /* V -> V/T ; T -> T/null */ - for (int i = 0; i < ctx->vertex_job_count; ++i) { - bool isLast = (i + 1) == ctx->vertex_job_count; - - panfrost_link_job_pair(ctx->u_vertex_jobs[i], isLast ? ctx->tiler_jobs[0] : ctx->vertex_jobs[i + 1]); - } - - /* T -> T/null */ - for (int i = 0; i < ctx->tiler_job_count; ++i) { - bool isLast = (i + 1) == ctx->tiler_job_count; - panfrost_link_job_pair(ctx->u_tiler_jobs[i], isLast ? 0 : ctx->tiler_jobs[i + 1]); - } -} - /* The entire frame is in memory -- send it off to the kernel! */ static void @@ -1355,13 +1348,6 @@ panfrost_submit_frame(struct panfrost_context *ctx, bool flush_immediate, if (!has_draws) flush_immediate = true; - /* A number of jobs are batched -- this must be linked and cleared */ - panfrost_link_jobs(ctx); - - ctx->draw_count = 0; - ctx->vertex_job_count = 0; - ctx->tiler_job_count = 0; - #ifndef DRY_RUN bool is_scanout = panfrost_is_scanout(ctx); diff --git a/src/gallium/drivers/panfrost/pan_context.h b/src/gallium/drivers/panfrost/pan_context.h index 7f08d47..e3dc070 100644 --- a/src/gallium/drivers/panfrost/pan_context.h +++ b/src/gallium/drivers/panfrost/pan_context.h @@ -326,7 +326,7 @@ void panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data); struct panfrost_transfer -panfrost_vertex_tiler_job(struct panfrost_context *ctx, bool is_tiler, bool is_elided_tiler); +panfrost_vertex_tiler_job(struct panfrost_context *ctx, bool is_tiler); unsigned panfrost_get_default_swizzle(unsigned components); -- 2.7.4