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 <bas@basnieuwenhuizen.nl> Reviewed-by: Marek Olšák <marek.olsak@amd.com>
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user