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