radeonsi: Decompress DCC textures in a render feedback loop.
authorBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Tue, 31 May 2016 12:11:49 +0000 (14:11 +0200)
committerBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Tue, 31 May 2016 19:43:04 +0000 (21:43 +0200)
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 <bas@basnieuwenhuizen.nl>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/drivers/radeonsi/si_blit.c
src/gallium/drivers/radeonsi/si_descriptors.c
src/gallium/drivers/radeonsi/si_pipe.h
src/gallium/drivers/radeonsi/si_state.c

index 6f3199ce3ff0d3b35af5994bf7fbd56d4030c6a7..3748a59177973443b92da056441f70860f4fe9ab 100644 (file)
@@ -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)
index 855b79e9f9922294c85b118432bc0d23042c37c4..ec1747423537a51d9f7e639ef827548579f56aab 100644 (file)
@@ -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
index e5b88c71dfdd4be940ce3290a7de743fcaefa281..b48b1bba4ad5661f3564a044c5a1609b50c553ee 100644 (file)
@@ -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 */
index ed62710611f096d821c62bb6d82c54d8556a62fb..5bf87a8961a7f65a59202484d9403723e1bbbaaa 100644 (file)
@@ -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)