radeonsi: initialize textures using DCC to black when possible
authorMarek Olšák <marek.olsak@amd.com>
Wed, 23 Jan 2019 16:34:48 +0000 (11:34 -0500)
committerMarek Olšák <marek.olsak@amd.com>
Wed, 6 Feb 2019 16:17:21 +0000 (11:17 -0500)
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/radeonsi/si_clear.c
src/gallium/drivers/radeonsi/si_pipe.h
src/gallium/drivers/radeonsi/si_texture.c

index a2f34c79104271f372eff60ab56aaae113cf0182..9a00bb73b944c302996d771bfb58d444e6e5c1c4 100644 (file)
@@ -34,15 +34,6 @@ enum {
        SI_CLEAR_SURFACE = SI_SAVE_FRAMEBUFFER | SI_SAVE_FRAGMENT_STATE,
 };
 
-enum si_dcc_clear_code
-{
-       DCC_CLEAR_COLOR_0000   = 0x00000000,
-       DCC_CLEAR_COLOR_0001   = 0x40404040,
-       DCC_CLEAR_COLOR_1110   = 0x80808080,
-       DCC_CLEAR_COLOR_1111   = 0xC0C0C0C0,
-       DCC_CLEAR_COLOR_REG    = 0x20202020,
-};
-
 static void si_alloc_separate_cmask(struct si_screen *sscreen,
                                    struct si_texture *tex)
 {
index ff36b3272b40fbc37eef4c9e47f29f7fc8bcd0bb..1af3c5ff9b7ea80692deaf36aa0cd2622141feed 100644 (file)
 #define SI_RESOURCE_FLAG_32BIT         (PIPE_RESOURCE_FLAG_DRV_PRIV << 6)
 #define SI_RESOURCE_FLAG_SO_FILLED_SIZE        (PIPE_RESOURCE_FLAG_DRV_PRIV << 7)
 
+enum si_clear_code
+{
+       DCC_CLEAR_COLOR_0000   = 0x00000000,
+       DCC_CLEAR_COLOR_0001   = 0x40404040,
+       DCC_CLEAR_COLOR_1110   = 0x80808080,
+       DCC_CLEAR_COLOR_1111   = 0xC0C0C0C0,
+       DCC_CLEAR_COLOR_REG    = 0x20202020,
+       DCC_UNCOMPRESSED       = 0xFFFFFFFF,
+};
+
 /* Debug flags. */
 enum {
        /* Shader logging options: */
index 422b0bc3a851d942bac23d19008ac5dee594f9fd..a50088d2d8f8971728f35a74393ec3763f90bef7 100644 (file)
@@ -1242,10 +1242,59 @@ si_texture_create_object(struct pipe_screen *screen,
 
        /* Initialize DCC only if the texture is not being imported. */
        if (!buf && tex->dcc_offset) {
-               si_screen_clear_buffer(sscreen, &tex->buffer.b.b,
-                                        tex->dcc_offset,
-                                        tex->surface.dcc_size,
-                                        0xFFFFFFFF);
+               /* Clear DCC to black for all tiles with DCC enabled.
+                *
+                * This fixes corruption in 3DMark Slingshot Extreme, which
+                * uses uninitialized textures, causing corruption.
+                */
+               if (tex->surface.num_dcc_levels == tex->buffer.b.b.last_level + 1 &&
+                   tex->buffer.b.b.nr_samples <= 2) {
+                       /* Simple case - all tiles have DCC enabled. */
+                       si_screen_clear_buffer(sscreen, &tex->buffer.b.b,
+                                              tex->dcc_offset,
+                                              tex->surface.dcc_size,
+                                              DCC_CLEAR_COLOR_0000);
+               } else if (sscreen->info.chip_class >= GFX9) {
+                       /* Clear to uncompressed. Clearing this to black is complicated. */
+                       si_screen_clear_buffer(sscreen, &tex->buffer.b.b,
+                                              tex->dcc_offset,
+                                              tex->surface.dcc_size,
+                                              DCC_UNCOMPRESSED);
+               } else {
+                       /* GFX8: Initialize mipmap levels and multisamples separately. */
+                       if (tex->buffer.b.b.nr_samples >= 2) {
+                               /* Clearing this to black is complicated. */
+                               si_screen_clear_buffer(sscreen, &tex->buffer.b.b,
+                                                      tex->dcc_offset,
+                                                      tex->surface.dcc_size,
+                                                      DCC_UNCOMPRESSED);
+                       } else {
+                               /* Clear the enabled mipmap levels to black. */
+                               unsigned size = 0;
+
+                               for (unsigned i = 0; i < tex->surface.num_dcc_levels; i++) {
+                                       if (!tex->surface.u.legacy.level[i].dcc_fast_clear_size)
+                                               break;
+
+                                       size = tex->surface.u.legacy.level[i].dcc_offset +
+                                              tex->surface.u.legacy.level[i].dcc_fast_clear_size;
+                               }
+
+                               /* Mipmap levels with DCC. */
+                               if (size) {
+                                       si_screen_clear_buffer(sscreen, &tex->buffer.b.b,
+                                                              tex->dcc_offset, size,
+                                                              DCC_CLEAR_COLOR_0000);
+                               }
+                               /* Mipmap levels without DCC. */
+                               if (size != tex->surface.dcc_size) {
+                                       si_screen_clear_buffer(sscreen, &tex->buffer.b.b,
+                                                              tex->dcc_offset + size,
+                                                              tex->surface.dcc_size - size,
+                                                              DCC_UNCOMPRESSED);
+                               }
+                       }
+               }
        }
 
        /* Initialize the CMASK base register value. */