[1/5] radeonsi: initialize textures using DCC to black when possible

Submitted by Marek Olšák on Jan. 31, 2019, 6:56 p.m.

Details

Message ID 20190131185629.2458-1-maraeo@gmail.com
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in Mesa

Not browsing as part of any series.

Commit Message

Marek Olšák Jan. 31, 2019, 6:56 p.m.
From: Marek Olšák <marek.olsak@amd.com>

---
 src/gallium/drivers/radeonsi/si_clear.c   |  9 ----
 src/gallium/drivers/radeonsi/si_pipe.h    | 10 ++++
 src/gallium/drivers/radeonsi/si_texture.c | 57 +++++++++++++++++++++--
 3 files changed, 63 insertions(+), 13 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/gallium/drivers/radeonsi/si_clear.c b/src/gallium/drivers/radeonsi/si_clear.c
index a2f34c79104..9a00bb73b94 100644
--- a/src/gallium/drivers/radeonsi/si_clear.c
+++ b/src/gallium/drivers/radeonsi/si_clear.c
@@ -27,29 +27,20 @@ 
 
 #include "util/u_format.h"
 #include "util/u_pack_color.h"
 #include "util/u_surface.h"
 
 enum {
 	SI_CLEAR         = SI_SAVE_FRAGMENT_STATE,
 	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)
 {
 	if (tex->cmask_buffer || !tex->surface.cmask_size)
                 return;
 
 	tex->cmask_buffer =
 		si_aligned_buffer_create(&sscreen->b,
 					 SI_RESOURCE_FLAG_UNMAPPABLE,
 					 PIPE_USAGE_DEFAULT,
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index ff36b3272b4..1af3c5ff9b7 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -104,20 +104,30 @@ 
 
 #define SI_RESOURCE_FLAG_TRANSFER	(PIPE_RESOURCE_FLAG_DRV_PRIV << 0)
 #define SI_RESOURCE_FLAG_FLUSHED_DEPTH	(PIPE_RESOURCE_FLAG_DRV_PRIV << 1)
 #define SI_RESOURCE_FLAG_FORCE_MSAA_TILING (PIPE_RESOURCE_FLAG_DRV_PRIV << 2)
 #define SI_RESOURCE_FLAG_DISABLE_DCC	(PIPE_RESOURCE_FLAG_DRV_PRIV << 3)
 #define SI_RESOURCE_FLAG_UNMAPPABLE	(PIPE_RESOURCE_FLAG_DRV_PRIV << 4)
 #define SI_RESOURCE_FLAG_READ_ONLY	(PIPE_RESOURCE_FLAG_DRV_PRIV << 5)
 #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: */
 	DBG_VS = PIPE_SHADER_VERTEX,
 	DBG_PS = PIPE_SHADER_FRAGMENT,
 	DBG_GS = PIPE_SHADER_GEOMETRY,
 	DBG_TCS = PIPE_SHADER_TESS_CTRL,
 	DBG_TES = PIPE_SHADER_TESS_EVAL,
 	DBG_CS = PIPE_SHADER_COMPUTE,
 	DBG_NO_IR,
diff --git a/src/gallium/drivers/radeonsi/si_texture.c b/src/gallium/drivers/radeonsi/si_texture.c
index 422b0bc3a85..a50088d2d8f 100644
--- a/src/gallium/drivers/radeonsi/si_texture.c
+++ b/src/gallium/drivers/radeonsi/si_texture.c
@@ -1235,24 +1235,73 @@  si_texture_create_object(struct pipe_screen *screen,
 			clear_value = 0x0000030F;
 
 		si_screen_clear_buffer(sscreen, &tex->buffer.b.b,
 					 tex->htile_offset,
 					 tex->surface.htile_size,
 					 clear_value);
 	}
 
 	/* 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. */
 	tex->cmask_base_address_reg =
 		(tex->buffer.gpu_address + tex->cmask_offset) >> 8;
 
 	if (sscreen->debug_flags & DBG(VM)) {
 		fprintf(stderr, "VM start=0x%"PRIX64"  end=0x%"PRIX64" | Texture %ix%ix%i, %i levels, %i samples, %s\n",
 			tex->buffer.gpu_address,
 			tex->buffer.gpu_address + tex->buffer.buf->size,