From c378829a0df904c907d7070801fd89749053680f Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 18 Jun 2019 12:30:55 -0700 Subject: [PATCH] panfrost: Skip shading unaffected tiles Looking at the scissor, we can discard some tiles. We specifially don't care about the scissor on the wallpaper, since that's a no-op if the entire tile is culled. v2: Clarify clear comment (not reviewed but trivial). Signed-off-by: Alyssa Rosenzweig Reviewed-by: Tomeu Vizoso --- src/gallium/drivers/panfrost/pan_context.c | 9 +++++++ src/gallium/drivers/panfrost/pan_context.h | 1 + src/gallium/drivers/panfrost/pan_fragment.c | 6 +++-- src/gallium/drivers/panfrost/pan_job.c | 26 +++++++++++++++++++++ src/gallium/drivers/panfrost/pan_job.h | 11 +++++++++ 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index 0b888fe3c64..41656236b5b 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -1373,6 +1373,13 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data) miny = MIN2(ctx->pipe_framebuffer.height, miny); maxy = MIN2(ctx->pipe_framebuffer.height, maxy); + /* Update the job, unless we're doing wallpapering (whose lack of + * scissor we can ignore, since if we "miss" a tile of wallpaper, it'll + * just... be faster :) */ + + if (!ctx->in_wallpaper) + panfrost_job_union_scissor(job, minx, miny, maxx, maxy); + /* Upload */ view.viewport0[0] = minx; @@ -1467,7 +1474,9 @@ panfrost_draw_wallpaper(struct pipe_context *pipe) return; /* Blit the wallpaper in */ + ctx->in_wallpaper = true; panfrost_blit_wallpaper(ctx); + ctx->in_wallpaper = false; /* We are flushing all queued draws and we know that no more jobs will * be added until the next frame. diff --git a/src/gallium/drivers/panfrost/pan_context.h b/src/gallium/drivers/panfrost/pan_context.h index d0365310223..deba4668767 100644 --- a/src/gallium/drivers/panfrost/pan_context.h +++ b/src/gallium/drivers/panfrost/pan_context.h @@ -201,6 +201,7 @@ struct panfrost_context { struct primconvert_context *primconvert; struct blitter_context *blitter; + bool in_wallpaper; struct panfrost_blend_state *blend; diff --git a/src/gallium/drivers/panfrost/pan_fragment.c b/src/gallium/drivers/panfrost/pan_fragment.c index ea0bd6cebdf..70358fec3f3 100644 --- a/src/gallium/drivers/panfrost/pan_fragment.c +++ b/src/gallium/drivers/panfrost/pan_fragment.c @@ -46,9 +46,11 @@ panfrost_fragment_job(struct panfrost_context *ctx, bool has_draws) #endif }; + struct panfrost_job *job = panfrost_get_job_for_fbo(ctx); + struct mali_payload_fragment payload = { - .min_tile_coord = MALI_COORDINATE_TO_TILE_MIN(0, 0), - .max_tile_coord = MALI_COORDINATE_TO_TILE_MAX(ctx->pipe_framebuffer.width, ctx->pipe_framebuffer.height), + .min_tile_coord = MALI_COORDINATE_TO_TILE_MIN(job->minx, job->miny), + .max_tile_coord = MALI_COORDINATE_TO_TILE_MAX(job->maxx, job->maxy), .framebuffer = framebuffer, }; diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c index 9c5d385e2ef..37bd70cb9a9 100644 --- a/src/gallium/drivers/panfrost/pan_job.c +++ b/src/gallium/drivers/panfrost/pan_job.c @@ -38,6 +38,9 @@ panfrost_create_job(struct panfrost_context *ctx) job->bos = _mesa_set_create(job, _mesa_hash_pointer, _mesa_key_pointer_equal); + + job->minx = job->miny = ~0; + job->maxx = job->maxy = 0; return job; } @@ -232,6 +235,15 @@ panfrost_job_clear(struct panfrost_context *ctx, } job->clear |= buffers; + + /* Clearing affects the entire framebuffer (by definition -- this is + * the Gallium clear callback, which clears the whole framebuffer. If + * the scissor test were enabled from the GL side, the state tracker + * would emit a quad instead and we wouldn't go down this code path) */ + + panfrost_job_union_scissor(job, 0, 0, + ctx->pipe_framebuffer.width, + ctx->pipe_framebuffer.height); } void @@ -265,6 +277,20 @@ panfrost_job_hash(const void *key) return _mesa_hash_data(key, sizeof(struct panfrost_job_key)); } +/* Given a new bounding rectangle (scissor), let the job cover the union of the + * new and old bounding rectangles */ + +void +panfrost_job_union_scissor(struct panfrost_job *job, + unsigned minx, unsigned miny, + unsigned maxx, unsigned maxy) +{ + job->minx = MIN2(job->minx, minx); + job->miny = MIN2(job->miny, miny); + job->maxx = MAX2(job->maxx, maxx); + job->maxy = MAX2(job->maxy, maxy); +} + void panfrost_job_init(struct panfrost_context *ctx) { diff --git a/src/gallium/drivers/panfrost/pan_job.h b/src/gallium/drivers/panfrost/pan_job.h index 2e7c0532341..ed8b084246a 100644 --- a/src/gallium/drivers/panfrost/pan_job.h +++ b/src/gallium/drivers/panfrost/pan_job.h @@ -55,6 +55,12 @@ struct panfrost_job { * bitmask) */ unsigned requirements; + /* The bounding box covered by this job, taking scissors into account. + * Basically, the bounding box we have to run fragment shaders for */ + + unsigned minx, miny; + unsigned maxx, maxy; + /* BOs referenced -- will be used for flushing logic */ struct set *bos; }; @@ -102,4 +108,9 @@ panfrost_job_clear(struct panfrost_context *ctx, const union pipe_color_union *color, double depth, unsigned stencil); +void +panfrost_job_union_scissor(struct panfrost_job *job, + unsigned minx, unsigned miny, + unsigned maxx, unsigned maxy); + #endif -- 2.30.2