From 35818129a676502415a5f502ccd2759646066921 Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Tue, 31 May 2016 14:11:49 +0200 Subject: [PATCH] radeonsi: Decompress DCC textures in a render feedback loop. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit By using a counter to quickly reject textures that are not bound to a framebuffer, the performance impact when binding sampler_views/images is not too large. Signed-off-by: Bas Nieuwenhuizen Reviewed-by: Marek Olšák --- src/gallium/drivers/radeonsi/si_blit.c | 100 ++++++++++++++++++++++++++ src/gallium/drivers/radeonsi/si_descriptors.c | 8 +++ src/gallium/drivers/radeonsi/si_pipe.h | 3 + src/gallium/drivers/radeonsi/si_state.c | 2 + 4 files changed, 113 insertions(+) diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c index 6f3199c..3748a59 100644 --- a/src/gallium/drivers/radeonsi/si_blit.c +++ b/src/gallium/drivers/radeonsi/si_blit.c @@ -412,6 +412,104 @@ si_decompress_image_color_textures(struct si_context *sctx, } } +static void si_check_render_feedback_textures(struct si_context *sctx, + struct si_textures_info *textures) +{ + uint32_t mask = textures->views.desc.enabled_mask; + + while (mask) { + const struct pipe_sampler_view *view; + struct r600_texture *tex; + bool render_feedback = false; + + unsigned i = u_bit_scan(&mask); + + view = textures->views.views[i]; + if(view->texture->target == PIPE_BUFFER) + continue; + + tex = (struct r600_texture *)view->texture; + if (!tex->dcc_offset) + continue; + + for (unsigned j = 0; j < sctx->framebuffer.state.nr_cbufs; ++j) { + struct r600_surface * surf; + + if (!sctx->framebuffer.state.cbufs[j]) + continue; + + 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); + } + } +} + +static void si_check_render_feedback_images(struct si_context *sctx, + struct si_images_info *images) +{ + uint32_t mask = images->desc.enabled_mask; + + while (mask) { + const struct pipe_image_view *view; + struct r600_texture *tex; + bool render_feedback = false; + + unsigned i = u_bit_scan(&mask); + + view = &images->views[i]; + if (view->resource->target == PIPE_BUFFER) + continue; + + tex = (struct r600_texture *)view->resource; + if (!tex->dcc_offset) + continue; + + for (unsigned j = 0; j < sctx->framebuffer.state.nr_cbufs; ++j) { + struct r600_surface * surf; + + if (!sctx->framebuffer.state.cbufs[j]) + continue; + + 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); + } + } +} + +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) { + si_check_render_feedback_images(sctx, &sctx->images[i]); + si_check_render_feedback_textures(sctx, &sctx->samplers[i]); + } + sctx->need_check_render_feedback = false; +} + static void si_decompress_textures(struct si_context *sctx, int shader_start, int shader_end) { @@ -439,6 +537,8 @@ static void si_decompress_textures(struct si_context *sctx, int shader_start, si_decompress_image_color_textures(sctx, &sctx->images[i]); } } + + si_check_render_feedback(sctx); } void si_decompress_graphics_textures(struct si_context *sctx) diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c index 855b79e..ec17474 100644 --- a/src/gallium/drivers/radeonsi/si_descriptors.c +++ b/src/gallium/drivers/radeonsi/si_descriptors.c @@ -387,6 +387,10 @@ static void si_set_sampler_views(struct pipe_context *ctx, } else { samplers->compressed_colortex_mask &= ~(1u << slot); } + + if (rtex->dcc_offset && + p_atomic_read(&rtex->framebuffers_bound)) + sctx->need_check_render_feedback = true; } else { samplers->depth_texture_mask &= ~(1u << slot); samplers->compressed_colortex_mask &= ~(1u << slot); @@ -527,6 +531,10 @@ si_set_shader_images(struct pipe_context *pipe, unsigned shader, images->compressed_colortex_mask &= ~(1 << slot); } + if (tex->dcc_offset && + p_atomic_read(&tex->framebuffers_bound)) + ctx->need_check_render_feedback = true; + /* Always force the base level to the selected level. * * This is required for 3D textures, where otherwise diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h index e5b88c7..b48b1bb 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.h +++ b/src/gallium/drivers/radeonsi/si_pipe.h @@ -323,6 +323,9 @@ struct si_context { uint64_t dmesg_timestamp; unsigned last_bo_count; struct radeon_bo_list_item *last_bo_list; + + /* Other state */ + bool need_check_render_feedback; }; /* cik_sdma.c */ diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index ed62710..5bf87a8 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -2429,6 +2429,8 @@ static void si_set_framebuffer_state(struct pipe_context *ctx, old_nr_samples != 1)) si_mark_atom_dirty(sctx, &sctx->msaa_sample_locs); } + + sctx->need_check_render_feedback = true; } static void si_emit_framebuffer_state(struct si_context *sctx, struct r600_atom *atom) -- 2.7.4