Mesa (main): freedreno: Handle full blit discards by invalidating the resource.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Jun 21 21:22:47 UTC 2021


Module: Mesa
Branch: main
Commit: 58f5605124a74eeac6a6156b093c9f098bb99c78
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=58f5605124a74eeac6a6156b093c9f098bb99c78

Author: Emma Anholt <emma at anholt.net>
Date:   Thu Jun 17 09:50:15 2021 -0700

freedreno: Handle full blit discards by invalidating the resource.

The previous implementation had several issues:

- It wasn't checking all the conditions necessary for "this blit updates
  the whole surface", like PIPE_MASK_Z but not S on a depth/stencil
  buffer.
- It would reset the previous batchbuffer, even if that batch had side
  effects on other buffers.
- The layering was painful to follow and made any recursion extra
  dangerous.

Now, we use a more conservative test (enough for the resource shadowing
case) and just invalidate the buffer up front, which should have the right
logic for discarding drawing to that resource.

I found I had to add fd_bc_flush_writer() to the end of fd_blitter_blit()
-- a flush was happening at fb state restore time when the discard flag
was set, and losing that flush breaks
dEQP-GLES31.functional.stencil_texturing.format.stencil_index8_cube.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11455>

---

 src/freedreno/ci/deqp-freedreno-a530-fails.txt     |  6 ----
 src/gallium/drivers/freedreno/freedreno_autotune.c |  2 +-
 src/gallium/drivers/freedreno/freedreno_batch.h    |  2 --
 src/gallium/drivers/freedreno/freedreno_blitter.c  | 36 ++++++++++++----------
 src/gallium/drivers/freedreno/freedreno_context.h  |  6 ----
 src/gallium/drivers/freedreno/freedreno_draw.c     | 14 ---------
 src/gallium/drivers/freedreno/freedreno_state.c    |  9 ------
 7 files changed, 20 insertions(+), 55 deletions(-)

diff --git a/src/freedreno/ci/deqp-freedreno-a530-fails.txt b/src/freedreno/ci/deqp-freedreno-a530-fails.txt
index 0c6ca6e857c..d901ff78d0e 100644
--- a/src/freedreno/ci/deqp-freedreno-a530-fails.txt
+++ b/src/freedreno/ci/deqp-freedreno-a530-fails.txt
@@ -3,10 +3,6 @@ dEQP-GLES2.functional.clipping.line.wide_line_clip_viewport_corner,Fail
 dEQP-GLES2.functional.clipping.point.wide_point_clip,Fail
 dEQP-GLES2.functional.clipping.point.wide_point_clip_viewport_center,Fail
 dEQP-GLES2.functional.clipping.point.wide_point_clip_viewport_corner,Fail
-dEQP-GLES2.functional.texture.specification.basic_copytexsubimage2d.2d_alpha,Fail
-dEQP-GLES2.functional.texture.specification.basic_copytexsubimage2d.2d_luminance,Fail
-dEQP-GLES2.functional.texture.specification.basic_copytexsubimage2d.2d_rgba,Fail
-dEQP-GLES2.functional.texture.specification.basic_copytexsubimage2d.2d_rgb,Fail
 dEQP-GLES31.functional.image_load_store.early_fragment_tests.early_fragment_tests_stencil,Crash
 dEQP-GLES31.functional.image_load_store.early_fragment_tests.early_fragment_tests_stencil_fbo,Crash
 dEQP-GLES31.functional.image_load_store.early_fragment_tests.early_fragment_tests_stencil_fbo_with_no_stencil,Crash
@@ -141,8 +137,6 @@ dEQP-GLES3.functional.shaders.texture_functions.textureprojgradoffset.sampler2ds
 dEQP-GLES3.functional.shaders.texture_functions.textureprojgradoffset.sampler3d_fixed_vertex,Fail
 dEQP-GLES3.functional.shaders.texture_functions.textureprojgradoffset.sampler3d_float_vertex,Fail
 dEQP-GLES3.functional.shaders.texture_functions.textureprojgrad.sampler2dshadow_vertex,Fail
-dEQP-GLES3.functional.texture.specification.basic_copytexsubimage2d.2d_alpha,Fail
-dEQP-GLES3.functional.texture.specification.basic_copytexsubimage2d.2d_rgba,Fail
 dEQP-GLES3.functional.transform_feedback.array_element.interleaved.lines.highp_float,Fail
 dEQP-GLES3.functional.transform_feedback.array_element.interleaved.lines.highp_ivec2,Fail
 dEQP-GLES3.functional.transform_feedback.array_element.interleaved.lines.highp_ivec4,Fail
diff --git a/src/gallium/drivers/freedreno/freedreno_autotune.c b/src/gallium/drivers/freedreno/freedreno_autotune.c
index 9f25307f768..d4ab28bcd8a 100644
--- a/src/gallium/drivers/freedreno/freedreno_autotune.c
+++ b/src/gallium/drivers/freedreno/freedreno_autotune.c
@@ -157,7 +157,7 @@ fallback_use_bypass(struct fd_batch *batch)
 
    /* Fallback logic if we have no historical data about the rendertarget: */
    if (batch->cleared || batch->gmem_reason ||
-       ((batch->num_draws > 5) && !batch->blit) || (pfb->samples > 1)) {
+       (batch->num_draws > 5) || (pfb->samples > 1)) {
       return false;
    }
 
diff --git a/src/gallium/drivers/freedreno/freedreno_batch.h b/src/gallium/drivers/freedreno/freedreno_batch.h
index 8f69a9d4e25..842537f8c47 100644
--- a/src/gallium/drivers/freedreno/freedreno_batch.h
+++ b/src/gallium/drivers/freedreno/freedreno_batch.h
@@ -94,8 +94,6 @@ struct fd_batch {
    bool nondraw : 1;
    bool needs_flush : 1;
    bool flushed : 1;
-   bool blit : 1;
-   bool back_blit : 1;    /* only blit so far is resource shadowing back-blit */
    bool tessellation : 1; /* tessellation used in batch */
 
    /* Keep track if WAIT_FOR_IDLE is needed for registers we need
diff --git a/src/gallium/drivers/freedreno/freedreno_blitter.c b/src/gallium/drivers/freedreno/freedreno_blitter.c
index 15bf9e315d8..8a4b0a1dc96 100644
--- a/src/gallium/drivers/freedreno/freedreno_blitter.c
+++ b/src/gallium/drivers/freedreno/freedreno_blitter.c
@@ -77,8 +77,7 @@ default_src_texture(struct pipe_sampler_view *src_templ,
 }
 
 static void
-fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond,
-                      bool discard) assert_dt
+fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond) assert_dt
 {
    util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vtx.vertexbuf.vb);
    util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx.vtx);
@@ -109,25 +108,29 @@ fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond,
 
    if (ctx->batch)
       fd_batch_update_queries(ctx->batch);
-
-   ctx->in_discard_blit = discard;
 }
 
 static void
 fd_blitter_pipe_end(struct fd_context *ctx) assert_dt
 {
-   ctx->in_discard_blit = false;
 }
 
 bool
 fd_blitter_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
 {
+   struct pipe_context *pctx = &ctx->base;
    struct pipe_resource *dst = info->dst.resource;
    struct pipe_resource *src = info->src.resource;
    struct pipe_context *pipe = &ctx->base;
    struct pipe_surface *dst_view, dst_templ;
    struct pipe_sampler_view src_templ, *src_view;
-   bool discard = false;
+
+   /* If the blit is updating the whole contents of the resource,
+    * invalidate it so we don't trigger any unnecessary tile loads in the 3D
+    * path.
+    */
+   if (util_blit_covers_whole_resource(info))
+      pctx->invalidate_resource(pctx, info->dst.resource);
 
    /* The blit format may not match the resource format in this path, so
     * we need to validate that we can use the src/dst resource with the
@@ -145,16 +148,9 @@ fd_blitter_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
    if (src == dst)
       pipe->flush(pipe, NULL, 0);
 
-   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);
-   }
-
    DBG_BLIT(info, NULL);
 
-   fd_blitter_pipe_begin(ctx, info->render_condition_enable, discard);
+   fd_blitter_pipe_begin(ctx, info->render_condition_enable);
 
    /* Initialize the surface. */
    default_dst_texture(&dst_templ, dst, info->dst.level, info->dst.box.z);
@@ -177,6 +173,12 @@ fd_blitter_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
 
    fd_blitter_pipe_end(ctx);
 
+   /* While this shouldn't technically be necessary, it is required for
+    * dEQP-GLES31.functional.stencil_texturing.format.stencil_index8_cube and
+    * 2d_array to pass.
+    */
+   fd_bc_flush_writer(ctx, fd_resource(info->dst.resource));
+
    /* The fallback blitter must never fail: */
    return true;
 }
@@ -194,7 +196,7 @@ fd_blitter_clear(struct pipe_context *pctx, unsigned buffers,
    /* Note: don't use discard=true, if there was something to
     * discard, that would have been already handled in fd_clear().
     */
-   fd_blitter_pipe_begin(ctx, false, false);
+   fd_blitter_pipe_begin(ctx, false);
 
    util_blitter_save_fragment_constant_buffer_slot(
       ctx->blitter, ctx->constbuf[PIPE_SHADER_FRAGMENT].cb);
@@ -330,8 +332,8 @@ fd_blitter_pipe_copy_region(struct fd_context *ctx, struct pipe_resource *dst,
       pctx->flush(pctx, NULL, 0);
    }
 
-   /* TODO we could discard if dst box covers dst level fully.. */
-   fd_blitter_pipe_begin(ctx, false, false);
+   /* TODO we could invalidate if dst box covers dst level fully. */
+   fd_blitter_pipe_begin(ctx, false);
    util_blitter_copy_texture(ctx->blitter, dst, dst_level, dstx, dsty, dstz,
                              src, src_level, src_box);
    fd_blitter_pipe_end(ctx);
diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h
index 5438da48589..ac0fce4429b 100644
--- a/src/gallium/drivers/freedreno/freedreno_context.h
+++ b/src/gallium/drivers/freedreno/freedreno_context.h
@@ -344,12 +344,6 @@ struct fd_context {
     */
    bool in_shadow : 1 dt;
 
-   /* 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 in_discard_blit : 1 dt;
-
    /* For catching recursion problems with blit fallback: */
    bool in_blit : 1 dt;
 
diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c
index 9065b032082..e22da55caa4 100644
--- a/src/gallium/drivers/freedreno/freedreno_draw.c
+++ b/src/gallium/drivers/freedreno/freedreno_draw.c
@@ -325,11 +325,6 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
 
    struct fd_batch *batch = fd_context_batch(ctx);
 
-   if (ctx->in_discard_blit) {
-      fd_batch_reset(batch);
-      fd_context_all_dirty(ctx);
-   }
-
    batch_draw_tracking(batch, info, indirect);
 
    while (unlikely(!fd_batch_lock_submit(batch))) {
@@ -343,12 +338,8 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
       assert(ctx->batch == batch);
    }
 
-   batch->blit = ctx->in_discard_blit;
-   batch->back_blit = ctx->in_shadow;
    batch->num_draws++;
 
-   ctx->in_discard_blit = false;
-
    /* Marking the batch as needing flush must come after the batch
     * dependency tracking (resource_read()/resource_write()), as that
     * can trigger a flush
@@ -452,11 +443,6 @@ fd_clear(struct pipe_context *pctx, unsigned buffers,
 
    struct fd_batch *batch = fd_context_batch(ctx);
 
-   if (ctx->in_discard_blit) {
-      fd_batch_reset(batch);
-      fd_context_all_dirty(ctx);
-   }
-
    batch_clear_tracking(batch, buffers);
 
    while (unlikely(!fd_batch_lock_submit(batch))) {
diff --git a/src/gallium/drivers/freedreno/freedreno_state.c b/src/gallium/drivers/freedreno/freedreno_state.c
index 92a4827149e..46e8a7cbed8 100644
--- a/src/gallium/drivers/freedreno/freedreno_state.c
+++ b/src/gallium/drivers/freedreno/freedreno_state.c
@@ -287,15 +287,6 @@ fd_set_framebuffer_state(struct pipe_context *pctx,
       fd_context_all_dirty(ctx);
       ctx->update_active_queries = true;
 
-      if (old_batch && old_batch->blit && !old_batch->back_blit) {
-         /* for blits, there is not really much point in hanging on
-          * to the uncommitted batch (ie. you probably don't blit
-          * multiple times to the same surface), so we might as
-          * well go ahead and flush this one:
-          */
-         fd_batch_flush(old_batch);
-      }
-
       fd_batch_reference(&old_batch, NULL);
    } else if (ctx->batch) {
       DBG("%d: cbufs[0]=%p, zsbuf=%p", ctx->batch->needs_flush,



More information about the mesa-commit mailing list