From ba3009688892713b711ca6e9420d813f0bdce43f Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 1 Jul 2016 12:38:16 -0400 Subject: [PATCH] freedreno: support discarding previous rendering in special cases Basically, to "DCE" blits triggered by resource shadowing, in cases where the levels are immediately completely overwritten. For example, mid-frame texture upload to level zero triggers shadowing and back-blits to the remaining levels, which are immediately overwritten by glGenerateMipmap(). Signed-off-by: Rob Clark --- .../drivers/freedreno/freedreno_context.h | 6 ++++++ .../drivers/freedreno/freedreno_draw.c | 10 +++++++++ .../drivers/freedreno/freedreno_resource.c | 21 ++++++++++++++----- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index c0004fabeaa..6fafa394042 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -304,6 +304,12 @@ struct fd_context { */ bool in_shadow; + /* Ie. in blit situation where we no longer care about previous framebuffer + * contents. Main point is to eliminate blits from fd_try_shadow_resource(). + * For example, in case of texture upload + gen-mipmaps. + */ + bool discard; + struct pipe_debug_callback debug; /* GMEM/tile handling fxns: */ diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c index b8ba4545b94..112bf5cb624 100644 --- a/src/gallium/drivers/freedreno/freedreno_draw.c +++ b/src/gallium/drivers/freedreno/freedreno_draw.c @@ -84,6 +84,11 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) return; } + if (ctx->discard) { + fd_batch_reset(ctx->batch); + ctx->discard = false; + } + /* * Figure out the buffers/features we need: */ @@ -209,6 +214,11 @@ fd_clear(struct pipe_context *pctx, unsigned buffers, if (!fd_render_condition_check(pctx)) return; + if (ctx->discard) { + fd_batch_reset(ctx->batch); + ctx->discard = false; + } + /* for bookkeeping about which buffers have been cleared (and thus * can fully or partially skip mem2gmem) we need to ignore buffers * that have already had a draw, in case apps do silly things like diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index dce953f74c1..a9b94610e46 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -124,7 +124,7 @@ realloc_bo(struct fd_resource *rsc, uint32_t size) fd_bc_invalidate_resource(rsc, true); } -static void fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond); +static void fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond, bool discard); static void fd_blitter_pipe_end(struct fd_context *ctx); static void @@ -133,7 +133,7 @@ do_blit(struct fd_context *ctx, const struct pipe_blit_info *blit, bool fallback /* TODO size threshold too?? */ if ((blit->src.resource->target != PIPE_BUFFER) && !fallback) { /* do blit on gpu: */ - fd_blitter_pipe_begin(ctx, false); + fd_blitter_pipe_begin(ctx, false, true); util_blitter_blit(ctx->blitter, blit); fd_blitter_pipe_end(ctx); } else { @@ -909,7 +909,8 @@ fd_blitter_pipe_copy_region(struct fd_context *ctx, if (!util_blitter_is_copy_supported(ctx->blitter, dst, src)) return false; - fd_blitter_pipe_begin(ctx, false); + /* TODO we could discard if dst box covers dst level fully.. */ + fd_blitter_pipe_begin(ctx, false, false); util_blitter_copy_texture(ctx->blitter, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); @@ -979,6 +980,7 @@ fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) { struct fd_context *ctx = fd_context(pctx); struct pipe_blit_info info = *blit_info; + bool discard = false; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && @@ -991,6 +993,13 @@ fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) if (info.render_condition_enable && !fd_render_condition_check(pctx)) return; + if (!info.scissor_enable && !info.alpha_blend) { + discard = util_texrange_covers_whole_level(info.dst.resource, + info.dst.level, info.dst.box.x, info.dst.box.y, + info.dst.box.z, info.dst.box.width, + info.dst.box.height, info.dst.box.depth); + } + if (util_try_blit_via_copy_region(pctx, &info)) { return; /* done */ } @@ -1007,13 +1016,13 @@ fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) return; } - fd_blitter_pipe_begin(ctx, info.render_condition_enable); + fd_blitter_pipe_begin(ctx, info.render_condition_enable, discard); util_blitter_blit(ctx->blitter, &info); fd_blitter_pipe_end(ctx); } static void -fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond) +fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond, bool discard) { util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vtx.vertexbuf.vb); util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx.vtx); @@ -1040,6 +1049,8 @@ fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond) ctx->cond_query, ctx->cond_cond, ctx->cond_mode); fd_hw_query_set_stage(ctx, ctx->batch->draw, FD_STAGE_BLIT); + + ctx->discard = discard; } static void -- 2.30.2