From: Marek Olšák <marek.ol...@amd.com>

This is just a workaround. The problem is described in the code.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96541
---
 src/gallium/drivers/radeon/r600_pipe_common.h |  2 +-
 src/gallium/drivers/radeon/r600_texture.c     | 35 ++++++++++++++++++++++-----
 src/gallium/drivers/radeonsi/si_blit.c        | 12 +++------
 src/gallium/drivers/radeonsi/si_descriptors.c |  2 +-
 4 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h 
b/src/gallium/drivers/radeon/r600_pipe_common.h
index e4002f9..5375044 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -764,21 +764,21 @@ void vi_separate_dcc_stop_query(struct pipe_context *ctx,
 void vi_separate_dcc_process_and_reset_stats(struct pipe_context *ctx,
                                             struct r600_texture *tex);
 void vi_dcc_clear_level(struct r600_common_context *rctx,
                        struct r600_texture *rtex,
                        unsigned level, unsigned clear_value);
 void evergreen_do_fast_color_clear(struct r600_common_context *rctx,
                                   struct pipe_framebuffer_state *fb,
                                   struct r600_atom *fb_state,
                                   unsigned *buffers, unsigned *dirty_cbufs,
                                   const union pipe_color_union *color);
-bool r600_texture_disable_dcc(struct r600_common_screen *rscreen,
+bool r600_texture_disable_dcc(struct r600_common_context *rctx,
                              struct r600_texture *rtex);
 void r600_init_screen_texture_functions(struct r600_common_screen *rscreen);
 void r600_init_context_texture_functions(struct r600_common_context *rctx);
 
 /* r600_viewport.c */
 void evergreen_apply_scissor_bug_workaround(struct r600_common_context *rctx,
                                            struct pipe_scissor_state *scissor);
 void r600_set_scissor_enable(struct r600_common_context *rctx, bool enable);
 void r600_update_vs_writes_viewport_index(struct r600_common_context *rctx,
                                          struct tgsi_shader_info *info);
diff --git a/src/gallium/drivers/radeon/r600_texture.c 
b/src/gallium/drivers/radeon/r600_texture.c
index ddfa135..78dd177 100644
--- a/src/gallium/drivers/radeon/r600_texture.c
+++ b/src/gallium/drivers/radeon/r600_texture.c
@@ -393,34 +393,55 @@ static bool r600_texture_discard_dcc(struct 
r600_common_screen *rscreen,
        assert(rtex->dcc_separate_buffer == NULL);
 
        /* Disable DCC. */
        rtex->dcc_offset = 0;
 
        /* Notify all contexts about the change. */
        r600_dirty_all_framebuffer_states(rscreen);
        return true;
 }
 
-bool r600_texture_disable_dcc(struct r600_common_screen *rscreen,
+/**
+ * Disable DCC for the texture. (first decompress, then discard metadata).
+ *
+ * Unresolved multi-context synchronization issue:
+ *
+ * If context 1 disables DCC and context 2 has queued commands that write
+ * to the texture via CB with DCC enabled, and the order of operations is
+ * as follows:
+ *   context 2 queues draw calls rendering to the texture, but doesn't flush
+ *   context 1 disables DCC and flushes
+ *   context 1 & 2 reset descriptors and FB state
+ *   context 2 flushes (new compressed tiles written by the draw calls)
+ *   context 1 & 2 read garbage, because DCC is disabled, yet there are
+ *   compressed tiled
+ *
+ * \param rctx  the current context if you have one, or rscreen->aux_context
+ *              if you don't.
+ */
+bool r600_texture_disable_dcc(struct r600_common_context *rctx,
                              struct r600_texture *rtex)
 {
-       struct r600_common_context *rctx =
-               (struct r600_common_context *)rscreen->aux_context;
+       struct r600_common_screen *rscreen = rctx->screen;
 
        if (!r600_can_disable_dcc(rtex))
                return false;
 
+       if (&rctx->b == rscreen->aux_context)
+               pipe_mutex_lock(rscreen->aux_context_lock);
+
        /* Decompress DCC. */
-       pipe_mutex_lock(rscreen->aux_context_lock);
        rctx->decompress_dcc(&rctx->b, rtex);
        rctx->b.flush(&rctx->b, NULL, 0);
-       pipe_mutex_unlock(rscreen->aux_context_lock);
+
+       if (&rctx->b == rscreen->aux_context)
+               pipe_mutex_unlock(rscreen->aux_context_lock);
 
        return r600_texture_discard_dcc(rscreen, rtex);
 }
 
 static void r600_degrade_tile_mode_to_linear(struct r600_common_context *rctx,
                                             struct r600_texture *rtex,
                                             bool invalidate_storage)
 {
        struct pipe_screen *screen = rctx->b.screen;
        struct r600_texture *new_tex;
@@ -485,39 +506,41 @@ static void r600_degrade_tile_mode_to_linear(struct 
r600_common_context *rctx,
        r600_dirty_all_framebuffer_states(rctx->screen);
        p_atomic_inc(&rctx->screen->dirty_tex_descriptor_counter);
 }
 
 static boolean r600_texture_get_handle(struct pipe_screen* screen,
                                       struct pipe_resource *resource,
                                       struct winsys_handle *whandle,
                                        unsigned usage)
 {
        struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
+       struct r600_common_context *aux_context =
+               (struct r600_common_context*)rscreen->aux_context;
        struct r600_resource *res = (struct r600_resource*)resource;
        struct r600_texture *rtex = (struct r600_texture*)resource;
        struct radeon_bo_metadata metadata;
        bool update_metadata = false;
 
        /* This is not supported now, but it might be required for OpenCL
         * interop in the future.
         */
        if (resource->target != PIPE_BUFFER &&
            (resource->nr_samples > 1 || rtex->is_depth))
                return false;
 
        if (resource->target != PIPE_BUFFER) {
                /* Since shader image stores don't support DCC on VI,
                 * disable it for external clients that want write
                 * access.
                 */
                if (usage & PIPE_HANDLE_USAGE_WRITE && rtex->dcc_offset) {
-                       if (r600_texture_disable_dcc(rscreen, rtex))
+                       if (r600_texture_disable_dcc(aux_context, rtex))
                                update_metadata = true;
                }
 
                if (!(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH) &&
                    rtex->cmask.size) {
                        /* Eliminate fast clear (both CMASK and DCC) */
                        r600_eliminate_fast_color_clear(rscreen, rtex);
 
                        /* Disable CMASK if flush_resource isn't going
                         * to be called.
diff --git a/src/gallium/drivers/radeonsi/si_blit.c 
b/src/gallium/drivers/radeonsi/si_blit.c
index f4bff6b..3cfd011 100644
--- a/src/gallium/drivers/radeonsi/si_blit.c
+++ b/src/gallium/drivers/radeonsi/si_blit.c
@@ -550,24 +550,22 @@ static void si_check_render_feedback_textures(struct 
si_context *sctx,
                        surf = (struct 
r600_surface*)sctx->framebuffer.state.cbufs[j];
 
                        if (tex == (struct r600_texture*)surf->base.texture &&
                            surf->base.u.tex.level >= view->u.tex.first_level &&
                            surf->base.u.tex.level <= view->u.tex.last_level &&
                            surf->base.u.tex.first_layer <= 
view->u.tex.last_layer &&
                            surf->base.u.tex.last_layer >= 
view->u.tex.first_layer)
                                render_feedback = true;
                }
 
-               if (render_feedback) {
-                       struct si_screen *screen = sctx->screen;
-                       r600_texture_disable_dcc(&screen->b, tex);
-               }
+               if (render_feedback)
+                       r600_texture_disable_dcc(&sctx->b, tex);
        }
 }
 
 static void si_check_render_feedback_images(struct si_context *sctx,
                                             struct si_images_info *images)
 {
        uint32_t mask = images->enabled_mask;
 
        while (mask) {
                const struct pipe_image_view *view;
@@ -592,24 +590,22 @@ static void si_check_render_feedback_images(struct 
si_context *sctx,
 
                        surf = (struct 
r600_surface*)sctx->framebuffer.state.cbufs[j];
 
                        if (tex == (struct r600_texture*)surf->base.texture &&
                            surf->base.u.tex.level == view->u.tex.level &&
                            surf->base.u.tex.first_layer <= 
view->u.tex.last_layer &&
                            surf->base.u.tex.last_layer >= 
view->u.tex.first_layer)
                                render_feedback = true;
                }
 
-               if (render_feedback) {
-                       struct si_screen *screen = sctx->screen;
-                       r600_texture_disable_dcc(&screen->b, tex);
-               }
+               if (render_feedback)
+                       r600_texture_disable_dcc(&sctx->b, tex);
        }
 }
 
 static void si_check_render_feedback(struct si_context *sctx)
 {
 
        if (!sctx->need_check_render_feedback)
                return;
 
        for (int i = 0; i < SI_NUM_SHADERS; ++i) {
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c 
b/src/gallium/drivers/radeonsi/si_descriptors.c
index 7600671..1d04a9c 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -656,21 +656,21 @@ static void si_set_shader_image(struct si_context *ctx,
 
                assert(!tex->is_depth);
                assert(tex->fmask.size == 0);
 
                if (uses_dcc &&
                    view->access & PIPE_IMAGE_ACCESS_WRITE) {
                        /* If DCC can't be disabled, at least decompress it.
                         * The decompression is relatively cheap if the surface
                         * has been decompressed already.
                         */
-                       if (r600_texture_disable_dcc(&screen->b, tex))
+                       if (r600_texture_disable_dcc(&ctx->b, tex))
                                uses_dcc = false;
                        else
                                ctx->b.decompress_dcc(&ctx->b.b, tex);
                }
 
                if (is_compressed_colortex(tex)) {
                        images->compressed_colortex_mask |= 1 << slot;
                } else {
                        images->compressed_colortex_mask &= ~(1 << slot);
                }
-- 
2.7.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to