freedreno: support discarding previous rendering in special cases
authorRob Clark <robdclark@gmail.com>
Fri, 1 Jul 2016 16:38:16 +0000 (12:38 -0400)
committerRob Clark <robdclark@gmail.com>
Sat, 30 Jul 2016 13:23:42 +0000 (09:23 -0400)
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 <robdclark@gmail.com>
src/gallium/drivers/freedreno/freedreno_context.h
src/gallium/drivers/freedreno/freedreno_draw.c
src/gallium/drivers/freedreno/freedreno_resource.c

index c0004fabeaaadbfcf140d35c61c432a935a860b6..6fafa3940421884f8966ae98f001fbc5bd2684a9 100644 (file)
@@ -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: */
index b8ba4545b942badb720dad9d5dd10df93395e926..112bf5cb6244d122c58c6f7ba98c83249910b28e 100644 (file)
@@ -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
index dce953f74c1f5a4c80c5bd28740243a794db60db..a9b94610e46be69bda9b8d7f15175d3448c9ab87 100644 (file)
@@ -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