Uses the DCC buffer instead of the CMASK buffer. The ELIMINATE_FAST_CLEAR still works. Furthermore, with DCC compression we can directly clear to a limited set of colors such that we do not need a postprocessing step.
Signed-off-by: Bas Nieuwenhuizen <b...@basnieuwenhuizen.nl> --- src/gallium/drivers/radeon/r600_texture.c | 78 +++++++++++++++++++++++---- src/gallium/drivers/radeonsi/si_blit.c | 4 +- src/gallium/drivers/radeonsi/si_cp_dma.c | 3 +- src/gallium/drivers/radeonsi/si_descriptors.c | 2 +- 4 files changed, 72 insertions(+), 15 deletions(-) diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c index 0314049..90e47ba 100644 --- a/src/gallium/drivers/radeon/r600_texture.c +++ b/src/gallium/drivers/radeon/r600_texture.c @@ -1239,6 +1239,52 @@ static void evergreen_set_clear_color(struct r600_texture *rtex, memcpy(rtex->color_clear_value, &uc, 2 * sizeof(uint32_t)); } +static void vi_get_fast_clear_parameters(enum pipe_format surface_format, + const union pipe_color_union *color, + uint32_t* reset_value, + bool* clear_words_needed) +{ + bool values[4] = {}; + int i; + const struct util_format_description *desc = util_format_description(surface_format); + + *clear_words_needed = true; + *reset_value = 0x20202020U; + + for (i = 0; i < 4; ++i) { + int index = desc->swizzle[i] - UTIL_FORMAT_SWIZZLE_X; + + if (desc->swizzle[i] < UTIL_FORMAT_SWIZZLE_X || desc->swizzle[i] > UTIL_FORMAT_SWIZZLE_W) + continue; + + /* All values have to be either zero or the positive maximum. */ + if (desc->channel[index].pure_integer && desc->channel[index].type == UTIL_FORMAT_TYPE_SIGNED) { + values[i] = color->i[i] != 0; + if(color->i[i] != 0 && color->i[i] != (1ULL << (desc->channel[index].size - 1)) - 1) + return; + } else if (desc->channel[index].pure_integer && desc->channel[index].type == UTIL_FORMAT_TYPE_UNSIGNED) { + values[i] = color->ui[i] != 0U; + if(color->ui[i] != 0U && color->ui[i] != (1ULL << desc->channel[index].size) - 1) + return; + } else { + values[i] = color->f[i] != 0.0F; + if(color->f[i] != 0.0F && color->f[i] != 1.0F) + return; + } + + /* All channels except alpha have to have the same value. */ + if (i < 3 && values[i] != values[0]) + return; + } + + *clear_words_needed = false; + if (values[0]) + *reset_value |= 0x80808080U; + + if (values[3]) + *reset_value |= 0x40404040U; +} + void evergreen_do_fast_color_clear(struct r600_common_context *rctx, struct pipe_framebuffer_state *fb, struct r600_atom *fb_state, @@ -1292,23 +1338,33 @@ void evergreen_do_fast_color_clear(struct r600_common_context *rctx, continue; } - /* CMASK clear does not work for DCC compressed textures */ if (tex->surface.dcc_enabled) { - continue; - } + uint32_t reset_value; + bool clear_words_needed; - /* ensure CMASK is enabled */ - r600_texture_alloc_cmask_separate(rctx->screen, tex); - if (tex->cmask.size == 0) { - continue; + vi_get_fast_clear_parameters(fb->cbufs[i]->format, color, &reset_value, &clear_words_needed); + + rctx->clear_buffer(&rctx->b, &tex->dcc_buffer->b.b, + 0, tex->surface.dcc_size, reset_value, true); + + if (clear_words_needed) + tex->dirty_level_mask |= 1 << fb->cbufs[i]->u.tex.level; + } else { + /* ensure CMASK is enabled */ + r600_texture_alloc_cmask_separate(rctx->screen, tex); + if (tex->cmask.size == 0) { + continue; + } + + /* Do the fast clear. */ + rctx->clear_buffer(&rctx->b, &tex->cmask_buffer->b.b, + tex->cmask.offset, tex->cmask.size, 0, true); + + tex->dirty_level_mask |= 1 << fb->cbufs[i]->u.tex.level; } - /* Do the fast clear. */ evergreen_set_clear_color(tex, fb->cbufs[i]->format, color); - rctx->clear_buffer(&rctx->b, &tex->cmask_buffer->b.b, - tex->cmask.offset, tex->cmask.size, 0, true); - tex->dirty_level_mask |= 1 << fb->cbufs[i]->u.tex.level; if (dirty_cbufs) *dirty_cbufs |= 1 << i; rctx->set_atom_dirty(rctx, fb_state, true); diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c index 120ec7f..f63ea5a 100644 --- a/src/gallium/drivers/radeonsi/si_blit.c +++ b/src/gallium/drivers/radeonsi/si_blit.c @@ -326,7 +326,7 @@ void si_decompress_color_textures(struct si_context *sctx, assert(view); tex = (struct r600_texture *)view->texture; - assert(tex->cmask.size || tex->fmask.size); + assert(tex->cmask.size || tex->fmask.size || tex->surface.dcc_enabled); si_blit_decompress_color(&sctx->b.b, tex, view->u.tex.first_level, view->u.tex.last_level, @@ -455,7 +455,7 @@ static void si_decompress_subresource(struct pipe_context *ctx, si_blit_decompress_depth_in_place(sctx, rtex, true, level, level, first_layer, last_layer); - } else if (rtex->fmask.size || rtex->cmask.size) { + } else if (rtex->fmask.size || rtex->cmask.size || rtex->surface.dcc_enabled) { si_blit_decompress_color(ctx, rtex, level, level, first_layer, last_layer); } diff --git a/src/gallium/drivers/radeonsi/si_cp_dma.c b/src/gallium/drivers/radeonsi/si_cp_dma.c index d4bd7b2..7441f26 100644 --- a/src/gallium/drivers/radeonsi/si_cp_dma.c +++ b/src/gallium/drivers/radeonsi/si_cp_dma.c @@ -139,7 +139,8 @@ static void si_clear_buffer(struct pipe_context *ctx, struct pipe_resource *dst, /* Flush the caches where the resource is bound. */ if (is_framebuffer) { - flush_flags = SI_CONTEXT_FLUSH_AND_INV_FRAMEBUFFER; + flush_flags = SI_CONTEXT_FLUSH_AND_INV_FRAMEBUFFER | + (sctx->b.chip_class >= VI ? SI_CONTEXT_FLUSH : 0); tc_l2_flag = 0; } else { flush_flags = SI_CONTEXT_INV_TC_L1 | diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c index 664a1a2..b486edc 100644 --- a/src/gallium/drivers/radeonsi/si_descriptors.c +++ b/src/gallium/drivers/radeonsi/si_descriptors.c @@ -234,7 +234,7 @@ static void si_set_sampler_views(struct pipe_context *ctx, } else { samplers->depth_texture_mask &= ~(1 << slot); } - if (rtex->cmask.size || rtex->fmask.size) { + if (rtex->cmask.size || rtex->fmask.size || rtex->surface.dcc_enabled) { samplers->compressed_colortex_mask |= 1 << slot; } else { samplers->compressed_colortex_mask &= ~(1 << slot); -- 2.5.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev