summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2016-07-01 12:38:16 -0400
committerRob Clark <[email protected]>2016-07-30 09:23:42 -0400
commitba3009688892713b711ca6e9420d813f0bdce43f (patch)
treea9acb89c8f3996de84c1808d171fcdd314284e74
parent7105774babc4d23623c3547cd19122a55c1090db (diff)
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 <[email protected]>
-rw-r--r--src/gallium/drivers/freedreno/freedreno_context.h6
-rw-r--r--src/gallium/drivers/freedreno/freedreno_draw.c10
-rw-r--r--src/gallium/drivers/freedreno/freedreno_resource.c21
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