From: Marek Olšák <marek.ol...@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;
+
        *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@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to