Mesa (staging/21.3): radeonsi: fix fast clear / depth decompression corruption

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Dec 17 19:44:18 UTC 2021


Module: Mesa
Branch: staging/21.3
Commit: e71b82818af9e5c9a46b296f26ca2897aa491252
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=e71b82818af9e5c9a46b296f26ca2897aa491252

Author: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Date:   Thu Dec  2 11:56:41 2021 +0100

radeonsi: fix fast clear / depth decompression corruption

Insert a flush after a depth decompression pass if the texture
was fast cleared.
This fixes a corruption which seems to only affect gfx10.3 chips.

Ideally we should also clear tex->need_flush_after_depth_decompression
after a flush but there's no easy way for this so this commit will
introduce extra flushes.

Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14089>
(cherry picked from commit 573d6451335a0b3c947aa2823619e31017d0362c)

---

 .pick_status.json                       |  2 +-
 src/gallium/drivers/radeonsi/si_blit.c  | 23 +++++++++++++++++++++--
 src/gallium/drivers/radeonsi/si_clear.c |  4 ++++
 src/gallium/drivers/radeonsi/si_pipe.h  |  1 +
 4 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/.pick_status.json b/.pick_status.json
index b9dcf9126b4..9ef1aae6133 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -1588,7 +1588,7 @@
         "description": "radeonsi: fix fast clear / depth decompression corruption",
         "nominated": true,
         "nomination_type": 0,
-        "resolution": 0,
+        "resolution": 1,
         "main_sha": null,
         "because_sha": null
     },
diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c
index bf5ccb1cc9a..5653ff233ab 100644
--- a/src/gallium/drivers/radeonsi/si_blit.c
+++ b/src/gallium/drivers/radeonsi/si_blit.c
@@ -395,11 +395,12 @@ static void si_decompress_depth(struct si_context *sctx, struct si_texture *tex,
       si_make_CB_shader_coherent(sctx, tex->buffer.b.b.nr_samples, false, true /* no DCC */);
 }
 
-static void si_decompress_sampler_depth_textures(struct si_context *sctx,
+static bool si_decompress_sampler_depth_textures(struct si_context *sctx,
                                                  struct si_samplers *textures)
 {
    unsigned i;
    unsigned mask = textures->needs_depth_decompress_mask;
+   bool need_flush = false;
 
    while (mask) {
       struct pipe_sampler_view *view;
@@ -418,7 +419,14 @@ static void si_decompress_sampler_depth_textures(struct si_context *sctx,
       si_decompress_depth(sctx, tex, sview->is_stencil_sampler ? PIPE_MASK_S : PIPE_MASK_Z,
                           view->u.tex.first_level, view->u.tex.last_level, 0,
                           util_max_layer(&tex->buffer.b.b, view->u.tex.first_level));
+
+      if (tex->need_flush_after_depth_decompression) {
+         need_flush = true;
+         tex->need_flush_after_depth_decompression = false;
+      }
    }
+
+   return need_flush;
 }
 
 static void si_blit_decompress_color(struct si_context *sctx, struct si_texture *tex,
@@ -757,6 +765,7 @@ static void si_decompress_resident_images(struct si_context *sctx)
 void si_decompress_textures(struct si_context *sctx, unsigned shader_mask)
 {
    unsigned compressed_colortex_counter, mask;
+   bool need_flush = false;
 
    if (sctx->blitter_running)
       return;
@@ -774,7 +783,7 @@ void si_decompress_textures(struct si_context *sctx, unsigned shader_mask)
       unsigned i = u_bit_scan(&mask);
 
       if (sctx->samplers[i].needs_depth_decompress_mask) {
-         si_decompress_sampler_depth_textures(sctx, &sctx->samplers[i]);
+         need_flush |= si_decompress_sampler_depth_textures(sctx, &sctx->samplers[i]);
       }
       if (sctx->samplers[i].needs_color_decompress_mask) {
          si_decompress_sampler_color_textures(sctx, &sctx->samplers[i]);
@@ -784,6 +793,16 @@ void si_decompress_textures(struct si_context *sctx, unsigned shader_mask)
       }
    }
 
+   if (sctx->chip_class == GFX10_3 && need_flush) {
+      /* This fixes a corruption with the following sequence:
+       *   - fast clear depth
+       *   - decompress depth
+       *   - draw
+       * (see https://gitlab.freedesktop.org/drm/amd/-/issues/1810#note_1170171)
+       */
+      sctx->b.flush(&sctx->b, NULL, RADEON_FLUSH_ASYNC_START_NEXT_GFX_IB_NOW);
+   }
+
    if (shader_mask & u_bit_consecutive(0, SI_NUM_GRAPHICS_SHADERS)) {
       if (sctx->uses_bindless_samplers)
          si_decompress_resident_textures(sctx);
diff --git a/src/gallium/drivers/radeonsi/si_clear.c b/src/gallium/drivers/radeonsi/si_clear.c
index aa73131bb24..63ff2c893c2 100644
--- a/src/gallium/drivers/radeonsi/si_clear.c
+++ b/src/gallium/drivers/radeonsi/si_clear.c
@@ -829,6 +829,8 @@ static void si_fast_clear(struct si_context *sctx, unsigned *buffers,
                clear_value = !zstex->htile_stencil_disabled ? 0xfffff30f : 0xfffc000f;
             }
 
+            zstex->need_flush_after_depth_decompression = sctx->chip_class == GFX10_3;
+
             assert(num_clears < ARRAY_SIZE(info));
             si_init_buffer_clear(&info[num_clears++], &zstex->buffer.b.b,
                                  zstex->surface.meta_offset, zstex->surface.meta_size, clear_value);
@@ -934,6 +936,8 @@ static void si_fast_clear(struct si_context *sctx, unsigned *buffers,
             }
          }
 
+         zstex->need_flush_after_depth_decompression = update_db_depth_clear && sctx->chip_class == GFX10_3;
+
          /* Update DB_DEPTH_CLEAR. */
          if (update_db_depth_clear &&
              zstex->depth_clear_value[level] != (float)depth) {
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index d9a6abec609..2408346c31b 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -374,6 +374,7 @@ struct si_texture {
    bool db_compatible : 1;
    bool can_sample_z : 1;
    bool can_sample_s : 1;
+   bool need_flush_after_depth_decompression: 1;
 
    /* We need to track DCC dirtiness, because st/dri usually calls
     * flush_resource twice per frame (not a bug) and we don't wanna



More information about the mesa-commit mailing list