summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/radeonsi
diff options
context:
space:
mode:
authorBas Nieuwenhuizen <[email protected]>2016-05-31 14:11:49 +0200
committerBas Nieuwenhuizen <[email protected]>2016-05-31 21:43:04 +0200
commit35818129a676502415a5f502ccd2759646066921 (patch)
tree6ddf2b5c345cca3827bfae9bdb8bf4f73bf629d9 /src/gallium/drivers/radeonsi
parentcbe3421f05b1a99df6df0fc93d7ce7d5071af02f (diff)
radeonsi: Decompress DCC textures in a render feedback loop.
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 <[email protected]> Reviewed-by: Marek Olšák <[email protected]>
Diffstat (limited to 'src/gallium/drivers/radeonsi')
-rw-r--r--src/gallium/drivers/radeonsi/si_blit.c100
-rw-r--r--src/gallium/drivers/radeonsi/si_descriptors.c8
-rw-r--r--src/gallium/drivers/radeonsi/si_pipe.h3
-rw-r--r--src/gallium/drivers/radeonsi/si_state.c2
4 files changed, 113 insertions, 0 deletions
diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c
index 6f3199ce3ff..3748a591779 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 855b79e9f99..ec174742353 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 e5b88c71dfd..b48b1bba4ad 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 ed62710611f..5bf87a8961a 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)