[Mesa-dev] [PATCH 2/4] radeonsi: enable DCC fast clear for 128-bit formats

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Wed Sep 7 12:11:06 UTC 2016


On Wed, Sep 7, 2016 at 1:46 PM, Marek Olšák <maraeo at gmail.com> wrote:
> From: Marek Olšák <marek.olsak at amd.com>
>
> ---
>  src/gallium/drivers/radeon/r600_texture.c | 45 ++++++++++++++++++++++---------
>  1 file changed, 32 insertions(+), 13 deletions(-)
>
> diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c
> index aee768f..074fed8 100644
> --- a/src/gallium/drivers/radeon/r600_texture.c
> +++ b/src/gallium/drivers/radeon/r600_texture.c
> @@ -2193,112 +2193,127 @@ void vi_separate_dcc_process_and_reset_stats(struct pipe_context *ctx,
>  /* FAST COLOR CLEAR */
>
>  static void evergreen_set_clear_color(struct r600_texture *rtex,
>                                       enum pipe_format surface_format,
>                                       const union pipe_color_union *color)
>  {
>         union util_color uc;
>
>         memset(&uc, 0, sizeof(uc));
>
> -       if (util_format_is_pure_uint(surface_format)) {
> +       if (util_format_get_blocksizebits(surface_format) == 128) {
> +               /* DCC fast clear only:
> +                *   CLEAR_WORD0 = R = G = B
> +                *   CLEAR_WORD1 = A
> +                */
> +               assert(color->ui[0] == color->ui[1] &&
> +                      color->ui[0] == color->ui[2]);
> +               uc.ui[0] = color->ui[0];
> +               uc.ui[1] = color->ui[3];
> +       } else if (util_format_is_pure_uint(surface_format)) {
>                 util_format_write_4ui(surface_format, color->ui, 0, &uc, 0, 0, 0, 1, 1);
>         } else if (util_format_is_pure_sint(surface_format)) {
>                 util_format_write_4i(surface_format, color->i, 0, &uc, 0, 0, 0, 1, 1);
>         } else {
>                 util_pack_color(color->f, surface_format, &uc);
>         }
>
>         memcpy(rtex->color_clear_value, &uc, 2 * sizeof(uint32_t));
>  }
>
> -static void vi_get_fast_clear_parameters(enum pipe_format surface_format,
> +static bool 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;
>         bool main_value = false;
>         bool extra_value = false;
>         int extra_channel;
>         const struct util_format_description *desc = util_format_description(surface_format);
>
> +       if (desc->block.bits == 128 &&
> +           (color->ui[0] != color->ui[1] ||
> +            color->ui[0] != color->ui[2]))
> +               return false;
> +

Don't we also need to return false if the pixel size is 128 bits and
and the clear values aren't 0/1 (or integer format equivalents)? You
can probably do that by replacing most of the "return true;"
statements with "return desc->bloc.bits <= 64;".

Furthermore, as far as I understood, if the DCC texture is bound to
CB, then tiles always get expanded to the clear color that we have in
the registers. However there is only space for 64 bits in there. Does
the hardware automatically ignore these values for 128 bit formats?

- Bas

>         *clear_words_needed = true;
>         *reset_value = 0x20202020U;
>
>         /* If we want to clear without needing a fast clear eliminate step, we
>          * can set each channel to 0 or 1 (or 0/max for integer formats). We
>          * have two sets of flags, one for the last or first channel(extra) and
>          * one for the other channels(main).
>          */
>
>         if (surface_format == PIPE_FORMAT_R11G11B10_FLOAT ||
>             surface_format == PIPE_FORMAT_B5G6R5_UNORM ||
>             surface_format == PIPE_FORMAT_B5G6R5_SRGB) {
>                 extra_channel = -1;
>         } else if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN) {
>                 if(r600_translate_colorswap(surface_format, false) <= 1)
>                         extra_channel = desc->nr_channels - 1;
>                 else
>                         extra_channel = 0;
>         } else
> -               return;
> +               return true;
>
>         for (i = 0; i < 4; ++i) {
>                 int index = desc->swizzle[i] - PIPE_SWIZZLE_X;
>
>                 if (desc->swizzle[i] < PIPE_SWIZZLE_X ||
>                     desc->swizzle[i] > PIPE_SWIZZLE_W)
>                         continue;
>
>                 if (desc->channel[i].pure_integer &&
>                     desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
>                         /* Use the maximum value for clamping the clear color. */
>                         int max = u_bit_consecutive(0, desc->channel[i].size - 1);
>
>                         values[i] = color->i[i] != 0;
>                         if (color->i[i] != 0 && MIN2(color->i[i], max) != max)
> -                               return;
> +                               return true;
>                 } else if (desc->channel[i].pure_integer &&
>                            desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) {
>                         /* Use the maximum value for clamping the clear color. */
>                         unsigned max = u_bit_consecutive(0, desc->channel[i].size);
>
>                         values[i] = color->ui[i] != 0U;
>                         if (color->ui[i] != 0U && MIN2(color->ui[i], max) != max)
> -                               return;
> +                               return true;
>                 } else {
>                         values[i] = color->f[i] != 0.0F;
>                         if (color->f[i] != 0.0F && color->f[i] != 1.0F)
> -                               return;
> +                               return true;
>                 }
>
>                 if (index == extra_channel)
>                         extra_value = values[i];
>                 else
>                         main_value = values[i];
>         }
>
>         for (int i = 0; i < 4; ++i)
>                 if (values[i] != main_value &&
>                     desc->swizzle[i] - PIPE_SWIZZLE_X != extra_channel &&
>                     desc->swizzle[i] >= PIPE_SWIZZLE_X &&
>                     desc->swizzle[i] <= PIPE_SWIZZLE_W)
> -                       return;
> +                       return true;
>
>         *clear_words_needed = false;
>         if (main_value)
>                 *reset_value |= 0x80808080U;
>
>         if (extra_value)
>                 *reset_value |= 0x40404040U;
> +       return true;
>  }
>
>  void vi_dcc_clear_level(struct r600_common_context *rctx,
>                         struct r600_texture *rtex,
>                         unsigned level, unsigned clear_value)
>  {
>         struct pipe_resource *dcc_buffer;
>         uint64_t dcc_offset;
>
>         assert(rtex->dcc_offset && rtex->surface.level[level].dcc_enabled);
> @@ -2417,25 +2432,20 @@ void evergreen_do_fast_color_clear(struct r600_common_context *rctx,
>
>                 if (!fb->cbufs[i])
>                         continue;
>
>                 /* if this colorbuffer is not being cleared */
>                 if (!(*buffers & clear_bit))
>                         continue;
>
>                 tex = (struct r600_texture *)fb->cbufs[i]->texture;
>
> -               /* 128-bit formats are unusupported */
> -               if (util_format_get_blocksizebits(fb->cbufs[i]->format) > 64) {
> -                       continue;
> -               }
> -
>                 /* the clear is allowed if all layers are bound */
>                 if (fb->cbufs[i]->u.tex.first_layer != 0 ||
>                     fb->cbufs[i]->u.tex.last_layer != util_max_layer(&tex->resource.b.b, 0)) {
>                         continue;
>                 }
>
>                 /* cannot clear mipmapped textures */
>                 if (fb->cbufs[i]->texture->last_level != 0) {
>                         continue;
>                 }
> @@ -2482,27 +2492,36 @@ void evergreen_do_fast_color_clear(struct r600_common_context *rctx,
>                         uint32_t reset_value;
>                         bool clear_words_needed;
>
>                         if (rctx->screen->debug_flags & DBG_NO_DCC_CLEAR)
>                                 continue;
>
>                         /* We can change the micro tile mode before a full clear. */
>                         if (rctx->screen->chip_class >= SI)
>                                 si_set_optimal_micro_tile_mode(rctx->screen, tex);
>
> -                       vi_get_fast_clear_parameters(fb->cbufs[i]->format, color, &reset_value, &clear_words_needed);
> +                       if (!vi_get_fast_clear_parameters(fb->cbufs[i]->format,
> +                                                         color, &reset_value,
> +                                                         &clear_words_needed))
> +                               continue;
> +
>                         vi_dcc_clear_level(rctx, tex, 0, reset_value);
>
>                         if (clear_words_needed)
>                                 tex->dirty_level_mask |= 1 << fb->cbufs[i]->u.tex.level;
>                         tex->separate_dcc_dirty = true;
>                 } else {
> +                       /* 128-bit formats are unusupported */
> +                       if (util_format_get_blocksizebits(fb->cbufs[i]->format) > 64) {
> +                               continue;
> +                       }
> +
>                         /* Stoney/RB+ doesn't work with CMASK fast clear. */
>                         if (rctx->family == CHIP_STONEY)
>                                 continue;
>
>                         /* ensure CMASK is enabled */
>                         r600_texture_alloc_cmask_separate(rctx->screen, tex);
>                         if (tex->cmask.size == 0) {
>                                 continue;
>                         }
>
> --
> 2.7.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list