From a6b5845a0d7547198037a2e5ea5c7d3f6f5f9f26 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Thu, 11 Aug 2016 17:56:44 +0200 Subject: [PATCH] radeonsi: use current context for DCC feedback-loop decompress, fixes Elemental MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 (v1) --- src/gallium/drivers/radeon/r600_pipe_common.h | 2 +- src/gallium/drivers/radeon/r600_texture.c | 38 ++++++++++++++++--- src/gallium/drivers/radeonsi/si_blit.c | 12 ++---- src/gallium/drivers/radeonsi/si_descriptors.c | 2 +- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h index e4002f944cd..53750440ef8 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -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); diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c index ddfa13503a6..8c7bfa328d9 100644 --- a/src/gallium/drivers/radeon/r600_texture.c +++ b/src/gallium/drivers/radeon/r600_texture.c @@ -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; } diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c index f4bff6b5bb1..3cfd0114d51 100644 --- a/src/gallium/drivers/radeonsi/si_blit.c +++ b/src/gallium/drivers/radeonsi/si_blit.c @@ -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); } } diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c index 7600671d07e..1d04a9c6e4d 100644 --- a/src/gallium/drivers/radeonsi/si_descriptors.c +++ b/src/gallium/drivers/radeonsi/si_descriptors.c @@ -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); -- 2.30.2