Mesa (master): freedreno/a6xx: UBWC support

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Mar 1 15:52:16 UTC 2019


Module: Mesa
Branch: master
Commit: 3e6758a4e774d2906aba31410462346bd00a79cf
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=3e6758a4e774d2906aba31410462346bd00a79cf

Author: Fritz Koenig <frkoenig at google.com>
Date:   Mon Jan  7 11:58:53 2019 -0800

freedreno/a6xx: UBWC support

Universal bandwidth compression(UBWC) reduces memory bandwidth
by compressing buffers. This compression takes the form of
a full sized image buffer as well as a smaller metadata buffer.

---

 src/gallium/drivers/freedreno/a6xx/fd6_blitter.c   | 70 +++++++++++++----
 src/gallium/drivers/freedreno/a6xx/fd6_emit.c      | 23 ++++--
 src/gallium/drivers/freedreno/a6xx/fd6_format.h    |  7 ++
 src/gallium/drivers/freedreno/a6xx/fd6_gmem.c      | 91 +++++++++++++++++-----
 src/gallium/drivers/freedreno/a6xx/fd6_texture.c   |  7 ++
 src/gallium/drivers/freedreno/a6xx/fd6_texture.h   |  1 +
 src/gallium/drivers/freedreno/freedreno_resource.h |  5 ++
 7 files changed, 160 insertions(+), 44 deletions(-)

diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
index b9118699dc0..f16eda74456 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
@@ -276,13 +276,15 @@ emit_blit_buffer(struct fd_ringbuffer *ring, const struct pipe_blit_info *info)
 		/*
 		 * Emit source:
 		 */
-		OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_INFO, 13);
+		OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_INFO, 10);
 		OUT_RING(ring, A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(RB6_R8_UNORM) |
-				A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(TILE6_LINEAR) |
-				 A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX) | 0x500000);
+				A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(src->tile_mode) |
+				 A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX) |
+				 COND(fd6_ubwc_enabled(src, src->tile_mode), A6XX_SP_PS_2D_SRC_INFO_FLAGS) |
+				 0x500000);
 		OUT_RING(ring, A6XX_SP_PS_2D_SRC_SIZE_WIDTH(sshift + w) |
 				 A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(1)); /* SP_PS_2D_SRC_SIZE */
-		OUT_RELOC(ring, src->bo, soff, 0, 0);    /* SP_PS_2D_SRC_LO/HI */
+		OUT_RELOC(ring, src->bo, soff + src->offset, 0, 0);    /* SP_PS_2D_SRC_LO/HI */
 		OUT_RING(ring, A6XX_SP_PS_2D_SRC_PITCH_PITCH(p));
 
 		OUT_RING(ring, 0x00000000);
@@ -291,18 +293,25 @@ emit_blit_buffer(struct fd_ringbuffer *ring, const struct pipe_blit_info *info)
 		OUT_RING(ring, 0x00000000);
 		OUT_RING(ring, 0x00000000);
 
-		OUT_RING(ring, 0x00000000);
-		OUT_RING(ring, 0x00000000);
-		OUT_RING(ring, 0x00000000);
+		if (fd6_ubwc_enabled(src, src->tile_mode)) {
+			OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_FLAGS_LO, 6);
+			OUT_RELOC(ring, src->bo, soff + src->ubwc_offset, 0, 0);
+			OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(src->ubwc_pitch) |
+					 A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(src->ubwc_size));
+			OUT_RING(ring, 0x00000000);
+			OUT_RING(ring, 0x00000000);
+			OUT_RING(ring, 0x00000000);
+		}
 
 		/*
 		 * Emit destination:
 		 */
 		OUT_PKT4(ring, REG_A6XX_RB_2D_DST_INFO, 9);
 		OUT_RING(ring, A6XX_RB_2D_DST_INFO_COLOR_FORMAT(RB6_R8_UNORM) |
-				 A6XX_RB_2D_DST_INFO_TILE_MODE(TILE6_LINEAR) |
-				 A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX));
-		OUT_RELOC(ring, dst->bo, doff, 0, 0);    /* RB_2D_DST_LO/HI */
+				 A6XX_RB_2D_DST_INFO_TILE_MODE(dst->tile_mode) |
+				 A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX) |
+				 COND(fd6_ubwc_enabled(dst, dst->tile_mode), A6XX_RB_2D_DST_INFO_FLAGS));
+		OUT_RELOC(ring, dst->bo, doff + dst->offset, 0, 0);    /* RB_2D_DST_LO/HI */
 		OUT_RING(ring, A6XX_RB_2D_DST_SIZE_PITCH(p));
 		OUT_RING(ring, 0x00000000);
 		OUT_RING(ring, 0x00000000);
@@ -310,6 +319,15 @@ emit_blit_buffer(struct fd_ringbuffer *ring, const struct pipe_blit_info *info)
 		OUT_RING(ring, 0x00000000);
 		OUT_RING(ring, 0x00000000);
 
+		if (fd6_ubwc_enabled(dst, dst->tile_mode)) {
+			OUT_PKT4(ring, REG_A6XX_RB_2D_DST_FLAGS_LO, 6);
+			OUT_RELOC(ring, dst->bo, doff + dst->ubwc_offset, 0, 0);
+			OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(dst->ubwc_pitch) |
+					 A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(dst->ubwc_size));
+			OUT_RING(ring, 0x00000000);
+			OUT_RING(ring, 0x00000000);
+			OUT_RING(ring, 0x00000000);
+		}
 		/*
 		 * Blit command:
 		 */
@@ -453,25 +471,33 @@ emit_blit_texture(struct fd_ringbuffer *ring, const struct pipe_blit_info *info)
 
 		enum a3xx_msaa_samples samples = fd_msaa_samples(src->base.nr_samples);
 
-		OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_INFO, 13);
+		OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_INFO, 10);
 		OUT_RING(ring, A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(sfmt) |
 				A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(stile) |
 				A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(sswap) |
 				 A6XX_SP_PS_2D_SRC_INFO_SAMPLES(samples) |
+				 COND(fd6_ubwc_enabled(src, stile), A6XX_SP_PS_2D_SRC_INFO_FLAGS) |
 				 0x500000 | filter);
 		OUT_RING(ring, A6XX_SP_PS_2D_SRC_SIZE_WIDTH(width) |
 				 A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(height)); /* SP_PS_2D_SRC_SIZE */
-		OUT_RELOC(ring, src->bo, soff, 0, 0);    /* SP_PS_2D_SRC_LO/HI */
+		OUT_RELOC(ring, src->bo, soff + src->offset, 0, 0);    /* SP_PS_2D_SRC_LO/HI */
 		OUT_RING(ring, A6XX_SP_PS_2D_SRC_PITCH_PITCH(spitch));
+
 		OUT_RING(ring, 0x00000000);
 		OUT_RING(ring, 0x00000000);
 		OUT_RING(ring, 0x00000000);
 		OUT_RING(ring, 0x00000000);
 		OUT_RING(ring, 0x00000000);
 
-		OUT_RING(ring, 0x00000000);
-		OUT_RING(ring, 0x00000000);
-		OUT_RING(ring, 0x00000000);
+		if (fd6_ubwc_enabled(src, stile)) {
+			OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_FLAGS_LO, 6);
+			OUT_RELOC(ring, src->bo, soff + src->ubwc_offset, 0, 0);
+			OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(src->ubwc_pitch) |
+					 A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(src->ubwc_size));
+			OUT_RING(ring, 0x00000000);
+			OUT_RING(ring, 0x00000000);
+			OUT_RING(ring, 0x00000000);
+		}
 
 		/*
 		 * Emit destination:
@@ -479,8 +505,9 @@ emit_blit_texture(struct fd_ringbuffer *ring, const struct pipe_blit_info *info)
 		OUT_PKT4(ring, REG_A6XX_RB_2D_DST_INFO, 9);
 		OUT_RING(ring, A6XX_RB_2D_DST_INFO_COLOR_FORMAT(dfmt) |
 				 A6XX_RB_2D_DST_INFO_TILE_MODE(dtile) |
-				 A6XX_RB_2D_DST_INFO_COLOR_SWAP(dswap));
-		OUT_RELOCW(ring, dst->bo, doff, 0, 0);    /* RB_2D_DST_LO/HI */
+				 A6XX_RB_2D_DST_INFO_COLOR_SWAP(dswap) |
+				 COND(fd6_ubwc_enabled(dst, dtile), A6XX_RB_2D_DST_INFO_FLAGS));
+		OUT_RELOCW(ring, dst->bo, doff + dst->offset, 0, 0);    /* RB_2D_DST_LO/HI */
 		OUT_RING(ring, A6XX_RB_2D_DST_SIZE_PITCH(dpitch));
 		OUT_RING(ring, 0x00000000);
 		OUT_RING(ring, 0x00000000);
@@ -488,6 +515,15 @@ emit_blit_texture(struct fd_ringbuffer *ring, const struct pipe_blit_info *info)
 		OUT_RING(ring, 0x00000000);
 		OUT_RING(ring, 0x00000000);
 
+		if (fd6_ubwc_enabled(dst, dtile)) {
+			OUT_PKT4(ring, REG_A6XX_RB_2D_DST_FLAGS_LO, 6);
+			OUT_RELOC(ring, dst->bo, doff + dst->ubwc_offset, 0, 0);
+			OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(dst->ubwc_pitch) |
+					 A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(dst->ubwc_size));
+			OUT_RING(ring, 0x00000000);
+			OUT_RING(ring, 0x00000000);
+			OUT_RING(ring, 0x00000000);
+		}
 		/*
 		 * Blit command:
 		 */
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
index 9fdc352c699..6115fda3b1a 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
@@ -411,17 +411,22 @@ fd6_emit_textures(struct fd_pipe *pipe, struct fd_ringbuffer *ring,
 			static const struct fd6_pipe_sampler_view dummy_view = {};
 			const struct fd6_pipe_sampler_view *view = tex->textures[i] ?
 				fd6_pipe_sampler_view(tex->textures[i]) : &dummy_view;
+			struct fd_resource *rsc = NULL;
+
+			if (view->base.texture)
+				rsc = fd_resource(view->base.texture);
 
 			OUT_RING(state, view->texconst0);
 			OUT_RING(state, view->texconst1);
 			OUT_RING(state, view->texconst2);
-			OUT_RING(state, view->texconst3);
+			OUT_RING(state, view->texconst3 |
+				COND(rsc && view->ubwc_enabled,
+					A6XX_TEX_CONST_3_FLAG | A6XX_TEX_CONST_3_UNK27));
 
-			if (view->base.texture) {
-				struct fd_resource *rsc = fd_resource(view->base.texture);
+			if (rsc) {
 				if (view->base.format == PIPE_FORMAT_X32_S8X24_UINT)
 					rsc = rsc->stencil;
-				OUT_RELOC(state, rsc->bo, view->offset,
+				OUT_RELOC(state, rsc->bo, view->offset + rsc->offset,
 					(uint64_t)view->texconst5 << 32, 0);
 			} else {
 				OUT_RING(state, 0x00000000);
@@ -429,8 +434,14 @@ fd6_emit_textures(struct fd_pipe *pipe, struct fd_ringbuffer *ring,
 			}
 
 			OUT_RING(state, view->texconst6);
-			OUT_RING(state, view->texconst7);
-			OUT_RING(state, view->texconst8);
+
+			if (rsc && view->ubwc_enabled) {
+				OUT_RELOC(state, rsc->bo, view->offset + rsc->ubwc_offset, 0, 0);
+			} else {
+				OUT_RING(state, 0);
+				OUT_RING(state, 0);
+			}
+
 			OUT_RING(state, view->texconst9);
 			OUT_RING(state, view->texconst10);
 			OUT_RING(state, view->texconst11);
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_format.h b/src/gallium/drivers/freedreno/a6xx/fd6_format.h
index 321794771b3..a1ed03d60f4 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_format.h
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_format.h
@@ -28,6 +28,7 @@
 #ifndef FD6_UTIL_H_
 #define FD6_UTIL_H_
 
+#include "freedreno_resource.h"
 #include "freedreno_util.h"
 
 #include "a6xx.xml.h"
@@ -113,4 +114,10 @@ fd6_ifmt(enum a6xx_color_fmt fmt)
 	}
 }
 
+static inline bool
+fd6_ubwc_enabled(struct fd_resource *rsc, enum a6xx_tile_mode tile_mode)
+{
+	return rsc->ubwc_size && tile_mode == TILE6_3;
+}
+
 #endif /* FD6_UTIL_H_ */
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
index fa1090d0eaf..1c1ca65598c 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
@@ -98,6 +98,12 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb,
 		else
 			tile_mode = rsc->tile_mode;
 
+		if (rsc->tile_mode &&
+			fd_resource_level_linear(psurf->texture, psurf->u.tex.level))
+			tile_mode = TILE6_LINEAR;
+		else
+			tile_mode = rsc->tile_mode;
+
 		debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
 		debug_assert((offset + slice->size0) <= fd_bo_size(rsc->bo));
 
@@ -107,23 +113,23 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb,
 				A6XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap));
 		OUT_RING(ring, A6XX_RB_MRT_PITCH(stride));
 		OUT_RING(ring, A6XX_RB_MRT_ARRAY_PITCH(slice->size0));
-		OUT_RELOCW(ring, rsc->bo, offset, 0, 0);	/* BASE_LO/HI */
+		OUT_RELOCW(ring, rsc->bo, offset + rsc->offset, 0, 0);	/* BASE_LO/HI */
 		OUT_RING(ring, base);			/* RB_MRT[i].BASE_GMEM */
 		OUT_PKT4(ring, REG_A6XX_SP_FS_MRT_REG(i), 1);
 		OUT_RING(ring, A6XX_SP_FS_MRT_REG_COLOR_FORMAT(format) |
 				COND(sint, A6XX_SP_FS_MRT_REG_COLOR_SINT) |
 				COND(uint, A6XX_SP_FS_MRT_REG_COLOR_UINT));
 
-#if 0
-		/* when we support UBWC, these would be the system memory
-		 * addr/pitch/etc:
-		 */
-		OUT_PKT4(ring, REG_A6XX_RB_MRT_FLAG_BUFFER(i), 4);
-		OUT_RING(ring, 0x00000000);    /* RB_MRT_FLAG_BUFFER[i].ADDR_LO */
-		OUT_RING(ring, 0x00000000);    /* RB_MRT_FLAG_BUFFER[i].ADDR_HI */
-		OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH(0));
-		OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH(0));
-#endif
+		OUT_PKT4(ring, REG_A6XX_RB_MRT_FLAG_BUFFER(i), 3);
+		if (fd6_ubwc_enabled(rsc, tile_mode)) {
+			OUT_RELOCW(ring, rsc->bo, offset + rsc->ubwc_offset, 0, 0);	/* BASE_LO/HI */
+			OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(rsc->ubwc_pitch) |
+				A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(rsc->ubwc_size));
+		} else {
+			OUT_RING(ring, 0x00000000);    /* RB_MRT_FLAG_BUFFER[i].ADDR_LO */
+			OUT_RING(ring, 0x00000000);    /* RB_MRT_FLAG_BUFFER[i].ADDR_HI */
+			OUT_RING(ring, 0x00000000);
+		}
 	}
 
 	OUT_PKT4(ring, REG_A6XX_RB_SRGB_CNTL, 1);
@@ -166,20 +172,29 @@ emit_zs(struct fd_ringbuffer *ring, struct pipe_surface *zsbuf,
 		uint32_t size = slice->size0;
 		uint32_t base = gmem ? gmem->zsbuf_base[0] : 0;
 
+		bool ubwc_enabled =
+			!fd_resource_level_linear(zsbuf->texture, zsbuf->u.tex.level) && rsc->ubwc_size;
+
 		OUT_PKT4(ring, REG_A6XX_RB_DEPTH_BUFFER_INFO, 6);
 		OUT_RING(ring, A6XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(fmt));
 		OUT_RING(ring, A6XX_RB_DEPTH_BUFFER_PITCH(stride));
 		OUT_RING(ring, A6XX_RB_DEPTH_BUFFER_ARRAY_PITCH(size));
-		OUT_RELOCW(ring, rsc->bo, 0, 0, 0);  /* RB_DEPTH_BUFFER_BASE_LO/HI */
+		OUT_RELOCW(ring, rsc->bo, rsc->offset, 0, 0);  /* RB_DEPTH_BUFFER_BASE_LO/HI */
 		OUT_RING(ring, base); /* RB_DEPTH_BUFFER_BASE_GMEM */
 
 		OUT_PKT4(ring, REG_A6XX_GRAS_SU_DEPTH_BUFFER_INFO, 1);
 		OUT_RING(ring, A6XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(fmt));
 
 		OUT_PKT4(ring, REG_A6XX_RB_DEPTH_FLAG_BUFFER_BASE_LO, 3);
-		OUT_RING(ring, 0x00000000);    /* RB_DEPTH_FLAG_BUFFER_BASE_LO */
-		OUT_RING(ring, 0x00000000);    /* RB_DEPTH_FLAG_BUFFER_BASE_HI */
-		OUT_RING(ring, 0x00000000);    /* RB_DEPTH_FLAG_BUFFER_PITCH */
+		if (ubwc_enabled) {
+			OUT_RELOCW(ring, rsc->bo, rsc->ubwc_offset, 0, 0);	/* BASE_LO/HI */
+			OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(rsc->ubwc_pitch) |
+				A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(rsc->ubwc_size));
+		} else {
+			OUT_RING(ring, 0x00000000);    /* RB_MRT_FLAG_BUFFER[i].ADDR_LO */
+			OUT_RING(ring, 0x00000000);    /* RB_MRT_FLAG_BUFFER[i].ADDR_HI */
+			OUT_RING(ring, 0x00000000);
+		}
 
 		if (rsc->lrz) {
 			OUT_PKT4(ring, REG_A6XX_GRAS_LRZ_BUFFER_BASE_LO, 5);
@@ -261,10 +276,32 @@ patch_draws(struct fd_batch *batch, enum pc_di_vis_cull_mode vismode)
 }
 
 static void
-update_render_cntl(struct fd_batch *batch, bool binning)
+update_render_cntl(struct fd_batch *batch, struct pipe_framebuffer_state *pfb, bool binning)
 {
 	struct fd_ringbuffer *ring = batch->gmem;
 	uint32_t cntl = 0;
+	bool depth_ubwc_enable = false;
+	uint32_t mrts_ubwc_enable = 0;
+	int i;
+
+	if (pfb->zsbuf) {
+		struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
+		depth_ubwc_enable =
+			!fd_resource_level_linear(pfb->zsbuf->texture, pfb->zsbuf->u.tex.level) && rsc->ubwc_size;
+	}
+
+	for (i = 0; i < pfb->nr_cbufs; i++) {
+		if (!pfb->cbufs[i])
+			continue;
+
+		struct pipe_surface *psurf = pfb->cbufs[i];
+		struct fd_resource *rsc = fd_resource(psurf->texture);
+		if (!rsc->bo)
+			continue;
+
+		if (fd6_ubwc_enabled(rsc, rsc->tile_mode))
+			mrts_ubwc_enable |= 1 << i;
+	}
 
 	cntl |= A6XX_RB_RENDER_CNTL_UNK4;
 	if (binning)
@@ -273,7 +310,9 @@ update_render_cntl(struct fd_batch *batch, bool binning)
 	OUT_PKT7(ring, CP_REG_WRITE, 3);
 	OUT_RING(ring, 0x2);
 	OUT_RING(ring, REG_A6XX_RB_RENDER_CNTL);
-	OUT_RING(ring, cntl);
+	OUT_RING(ring, cntl |
+		COND(depth_ubwc_enable, A6XX_RB_RENDER_CNTL_FLAG_DEPTH) |
+		A6XX_RB_RENDER_CNTL_FLAG_MRTS(mrts_ubwc_enable));
 }
 
 static void
@@ -483,7 +522,7 @@ fd6_emit_tile_init(struct fd_batch *batch)
 	if (use_hw_binning(batch)) {
 		set_bin_size(ring, gmem->bin_w, gmem->bin_h,
 				A6XX_RB_BIN_CONTROL_BINNING_PASS | 0x6000000);
-		update_render_cntl(batch, true);
+		update_render_cntl(batch, pfb, true);
 		emit_binning_pass(batch);
 		patch_draws(batch, USE_VISIBILITY);
 
@@ -497,7 +536,7 @@ fd6_emit_tile_init(struct fd_batch *batch)
 		patch_draws(batch, IGNORE_VISIBILITY);
 	}
 
-	update_render_cntl(batch, false);
+	update_render_cntl(batch, pfb, false);
 }
 
 static void
@@ -640,14 +679,22 @@ emit_blit(struct fd_batch *batch,
 			 A6XX_RB_BLIT_DST_INFO_TILE_MODE(tile_mode) |
 			 A6XX_RB_BLIT_DST_INFO_SAMPLES(samples) |
 			 A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format) |
-			 A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(swap));
-	OUT_RELOCW(ring, rsc->bo, offset, 0, 0);  /* RB_BLIT_DST_LO/HI */
+			 A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(swap) |
+			 COND(fd6_ubwc_enabled(rsc, tile_mode), A6XX_RB_BLIT_DST_INFO_FLAGS));
+	OUT_RELOCW(ring, rsc->bo, offset + rsc->offset, 0, 0);  /* RB_BLIT_DST_LO/HI */
 	OUT_RING(ring, A6XX_RB_BLIT_DST_PITCH(stride));
 	OUT_RING(ring, A6XX_RB_BLIT_DST_ARRAY_PITCH(size));
 
 	OUT_PKT4(ring, REG_A6XX_RB_BLIT_BASE_GMEM, 1);
 	OUT_RING(ring, base);
 
+	if (fd6_ubwc_enabled(rsc, tile_mode)) {
+		OUT_PKT4(ring, REG_A6XX_RB_BLIT_FLAG_DST_LO, 3);
+		OUT_RELOCW(ring, rsc->bo, offset + rsc->ubwc_offset, 0, 0);
+		OUT_RING(ring, A6XX_RB_MRT_FLAG_BUFFER_PITCH_PITCH(rsc->ubwc_pitch) |
+				 A6XX_RB_MRT_FLAG_BUFFER_PITCH_ARRAY_PITCH(rsc->ubwc_size));
+	}
+
 	fd6_emit_blit(batch, ring);
 }
 
@@ -1076,6 +1123,8 @@ fd6_emit_sysmem_prep(struct fd_batch *batch)
 	emit_zs(ring, pfb->zsbuf, NULL);
 	emit_mrt(ring, pfb, NULL);
 	emit_msaa(ring, pfb->samples);
+
+	update_render_cntl(batch, pfb, false);
 }
 
 static void
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_texture.c b/src/gallium/drivers/freedreno/a6xx/fd6_texture.c
index 0d6bec72b14..6f61f4ed3da 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_texture.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_texture.c
@@ -288,6 +288,13 @@ fd6_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
 					util_format_get_nblocksx(
 							format, rsc->slices[lvl].pitch) * rsc->cpp);
 		so->offset = fd_resource_offset(rsc, lvl, cso->u.tex.first_layer);
+
+		so->ubwc_enabled = rsc->ubwc_size && u_minify(prsc->width0, lvl) >= 16;
+	}
+
+	if (so->ubwc_enabled) {
+		so->texconst9 |= A6XX_TEX_CONST_9_FLAG_BUFFER_PITCH(rsc->ubwc_size);
+		so->texconst10 |= A6XX_TEX_CONST_10_FLAG_BUFFER_ARRAY_PITCH(rsc->ubwc_pitch);
 	}
 
 	so->texconst2 |= A6XX_TEX_CONST_2_TYPE(fd6_tex_type(cso->target));
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_texture.h b/src/gallium/drivers/freedreno/a6xx/fd6_texture.h
index 417aa72b9ae..122f60bba27 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_texture.h
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_texture.h
@@ -57,6 +57,7 @@ struct fd6_pipe_sampler_view {
 	uint32_t offset;
 	bool astc_srgb;
 	uint16_t seqno;
+	bool ubwc_enabled;
 };
 
 static inline struct fd6_pipe_sampler_view *
diff --git a/src/gallium/drivers/freedreno/freedreno_resource.h b/src/gallium/drivers/freedreno/freedreno_resource.h
index 9cdeea863bc..6a207fe2dc2 100644
--- a/src/gallium/drivers/freedreno/freedreno_resource.h
+++ b/src/gallium/drivers/freedreno/freedreno_resource.h
@@ -78,6 +78,11 @@ struct fd_resource {
 	/* TODO rename to secondary or auxiliary? */
 	struct fd_resource *stencil;
 
+	uint32_t offset;
+	uint32_t ubwc_offset;
+	uint32_t ubwc_pitch;
+	uint32_t ubwc_size;
+
 	/* bitmask of in-flight batches which reference this resource.  Note
 	 * that the batch doesn't hold reference to resources (but instead
 	 * the fd_ringbuffer holds refs to the underlying fd_bo), but in case




More information about the mesa-commit mailing list