radeonsi: use current context for DCC feedback-loop decompress, fixes Elemental
authorMarek Olšák <marek.olsak@amd.com>
Thu, 11 Aug 2016 15:56:44 +0000 (17:56 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Wed, 17 Aug 2016 10:24:35 +0000 (12:24 +0200)
This is just a workaround. The problem is described in the code.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96541

v2: say that it's only between the current context and aux_context

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com> (v1)
src/gallium/drivers/radeon/r600_pipe_common.h
src/gallium/drivers/radeon/r600_texture.c
src/gallium/drivers/radeonsi/si_blit.c
src/gallium/drivers/radeonsi/si_descriptors.c

index e4002f944cd2020c02d487a35abaa51f45dd25c9..53750440ef8330c342dfd20b8771982d573aed52 100644 (file)
@@ -771,7 +771,7 @@ void evergreen_do_fast_color_clear(struct r600_common_context *rctx,
                                   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);
index ddfa13503a6036e1f20be37334b98e7d4bd07e68..8c7bfa328d95408b8aeebb75f32cd3cbdc897d10 100644 (file)
@@ -400,20 +400,44 @@ static bool r600_texture_discard_dcc(struct r600_common_screen *rscreen,
        return true;
 }
 
-bool r600_texture_disable_dcc(struct r600_common_screen *rscreen,
+/**
+ * Disable DCC for the texture. (first decompress, then discard metadata).
+ *
+ * There is unresolved multi-context synchronization issue between
+ * screen::aux_context and the current context. If applications do this with
+ * multiple contexts, it's already undefined behavior for them and we don't
+ * have to worry about that. The scenario is:
+ *
+ * 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);
 }
@@ -492,6 +516,8 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen,
                                        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;
@@ -510,7 +536,7 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen,
                 * 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;
                }
 
index f4bff6b5bb11fc56b2d181a616f9ece965a67dc2..3cfd0114d517750cf97b34d2ced37a07e6cc8007 100644 (file)
@@ -557,10 +557,8 @@ static void si_check_render_feedback_textures(struct si_context *sctx,
                                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);
        }
 }
 
@@ -599,10 +597,8 @@ static void si_check_render_feedback_images(struct si_context *sctx,
                                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);
        }
 }
 
index 7600671d07e31ed1414f55c9cd1f0d4f7d349cba..1d04a9c6e4d50956dd7ab004d1fee72acd4fc672 100644 (file)
@@ -663,7 +663,7 @@ static void si_set_shader_image(struct si_context *ctx,
                         * 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);