[Mesa-dev] [PATCH 13/14] radeonsi: program tile swizzle for color and FMASK surfaces for GFX & SDMA

Marek Olšák maraeo at gmail.com
Mon Jul 31 23:40:36 UTC 2017


From: Marek Olšák <marek.olsak at amd.com>

---
 src/gallium/drivers/radeon/r600_pipe_common.h |  1 +
 src/gallium/drivers/radeon/r600_texture.c     |  4 +++-
 src/gallium/drivers/radeonsi/cik_sdma.c       |  7 +++++++
 src/gallium/drivers/radeonsi/si_descriptors.c | 13 ++++++++++++-
 src/gallium/drivers/radeonsi/si_state.c       | 12 ++++++++++--
 5 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index b391cbb..fb52dfb 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -195,20 +195,21 @@ struct r600_transfer {
 };
 
 struct r600_fmask_info {
 	uint64_t offset;
 	uint64_t size;
 	unsigned alignment;
 	unsigned pitch_in_pixels;
 	unsigned bank_height;
 	unsigned slice_tile_max;
 	unsigned tile_mode_index;
+	unsigned tile_swizzle;
 };
 
 struct r600_cmask_info {
 	uint64_t offset;
 	uint64_t size;
 	unsigned alignment;
 	unsigned slice_tile_max;
 	uint64_t base_address_reg;
 };
 
diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c
index 07df2d4..e3d462e 100644
--- a/src/gallium/drivers/radeon/r600_texture.c
+++ b/src/gallium/drivers/radeon/r600_texture.c
@@ -750,20 +750,21 @@ void r600_texture_get_fmask_info(struct r600_common_screen *rscreen,
 
 	assert(fmask.u.legacy.level[0].mode == RADEON_SURF_MODE_2D);
 
 	out->slice_tile_max = (fmask.u.legacy.level[0].nblk_x * fmask.u.legacy.level[0].nblk_y) / 64;
 	if (out->slice_tile_max)
 		out->slice_tile_max -= 1;
 
 	out->tile_mode_index = fmask.u.legacy.tiling_index[0];
 	out->pitch_in_pixels = fmask.u.legacy.level[0].nblk_x;
 	out->bank_height = fmask.u.legacy.bankh;
+	out->tile_swizzle = fmask.tile_swizzle;
 	out->alignment = MAX2(256, fmask.surf_alignment);
 	out->size = fmask.surf_size;
 }
 
 static void r600_texture_allocate_fmask(struct r600_common_screen *rscreen,
 					struct r600_texture *rtex)
 {
 	r600_texture_get_fmask_info(rscreen, rtex,
 				    rtex->resource.b.b.nr_samples, &rtex->fmask);
 
@@ -1440,21 +1441,21 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
 
 static struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
 						      const struct pipe_resource *templ,
 						      struct winsys_handle *whandle,
                                                       unsigned usage)
 {
 	struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
 	struct pb_buffer *buf = NULL;
 	unsigned stride = 0, offset = 0;
 	unsigned array_mode;
-	struct radeon_surf surface;
+	struct radeon_surf surface = {};
 	int r;
 	struct radeon_bo_metadata metadata = {};
 	struct r600_texture *rtex;
 	bool is_scanout;
 
 	/* Support only 2D textures without mipmaps */
 	if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
 	      templ->depth0 != 1 || templ->last_level != 0)
 		return NULL;
 
@@ -1504,20 +1505,21 @@ static struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen
 	rtex->resource.external_usage = usage;
 
 	if (rscreen->apply_opaque_metadata)
 		rscreen->apply_opaque_metadata(rscreen, rtex, &metadata);
 
 	/* Validate that addrlib arrived at the same surface parameters. */
 	if (rscreen->chip_class >= GFX9) {
 		assert(metadata.u.gfx9.swizzle_mode == surface.u.gfx9.surf.swizzle_mode);
 	}
 
+	assert(rtex->surface.tile_swizzle == 0);
 	return &rtex->resource.b.b;
 }
 
 bool r600_init_flushed_depth_texture(struct pipe_context *ctx,
 				     struct pipe_resource *texture,
 				     struct r600_texture **staging)
 {
 	struct r600_texture *rtex = (struct r600_texture*)texture;
 	struct pipe_resource resource;
 	struct r600_texture **flushed_depth_texture = staging ?
diff --git a/src/gallium/drivers/radeonsi/cik_sdma.c b/src/gallium/drivers/radeonsi/cik_sdma.c
index 99285a6..8154d72 100644
--- a/src/gallium/drivers/radeonsi/cik_sdma.c
+++ b/src/gallium/drivers/radeonsi/cik_sdma.c
@@ -155,20 +155,24 @@ static bool cik_sdma_copy_texture(struct si_context *sctx,
 	uint64_t src_address = rsrc->resource.gpu_address +
 			       rsrc->surface.u.legacy.level[src_level].offset;
 	unsigned dst_mode = rdst->surface.u.legacy.level[dst_level].mode;
 	unsigned src_mode = rsrc->surface.u.legacy.level[src_level].mode;
 	unsigned dst_tile_index = rdst->surface.u.legacy.tiling_index[dst_level];
 	unsigned src_tile_index = rsrc->surface.u.legacy.tiling_index[src_level];
 	unsigned dst_tile_mode = info->si_tile_mode_array[dst_tile_index];
 	unsigned src_tile_mode = info->si_tile_mode_array[src_tile_index];
 	unsigned dst_micro_mode = G_009910_MICRO_TILE_MODE_NEW(dst_tile_mode);
 	unsigned src_micro_mode = G_009910_MICRO_TILE_MODE_NEW(src_tile_mode);
+	unsigned dst_tile_swizzle = dst_mode == RADEON_SURF_MODE_2D ?
+					    rdst->surface.tile_swizzle : 0;
+	unsigned src_tile_swizzle = src_mode == RADEON_SURF_MODE_2D ?
+					    rsrc->surface.tile_swizzle : 0;
 	unsigned dst_pitch = rdst->surface.u.legacy.level[dst_level].nblk_x;
 	unsigned src_pitch = rsrc->surface.u.legacy.level[src_level].nblk_x;
 	uint64_t dst_slice_pitch = rdst->surface.u.legacy.level[dst_level].slice_size / bpp;
 	uint64_t src_slice_pitch = rsrc->surface.u.legacy.level[src_level].slice_size / bpp;
 	unsigned dst_width = minify_as_blocks(rdst->resource.b.b.width0,
 					      dst_level, rdst->surface.blk_w);
 	unsigned src_width = minify_as_blocks(rsrc->resource.b.b.width0,
 					      src_level, rsrc->surface.blk_w);
 	unsigned dst_height = minify_as_blocks(rdst->resource.b.b.height0,
 					       dst_level, rdst->surface.blk_h);
@@ -198,20 +202,23 @@ static bool cik_sdma_copy_texture(struct si_context *sctx,
 	dsty /= rdst->surface.blk_h;
 
 	if (srcx >= (1 << 14) ||
 	    srcy >= (1 << 14) ||
 	    srcz >= (1 << 11) ||
 	    dstx >= (1 << 14) ||
 	    dsty >= (1 << 14) ||
 	    dstz >= (1 << 11))
 		return false;
 
+	dst_address |= dst_tile_swizzle << 8;
+	src_address |= src_tile_swizzle << 8;
+
 	/* Linear -> linear sub-window copy. */
 	if (dst_mode == RADEON_SURF_MODE_LINEAR_ALIGNED &&
 	    src_mode == RADEON_SURF_MODE_LINEAR_ALIGNED &&
 	    /* check if everything fits into the bitfields */
 	    src_pitch <= (1 << 14) &&
 	    dst_pitch <= (1 << 14) &&
 	    src_slice_pitch <= (1 << 28) &&
 	    dst_slice_pitch <= (1 << 28) &&
 	    copy_width <= (1 << 14) &&
 	    copy_height <= (1 << 14) &&
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 4de6086..d50a24c 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -415,30 +415,41 @@ void si_set_mutable_tex_desc_fields(struct si_screen *sscreen,
 		else
 			va += tex->surface.u.gfx9.surf_offset;
 	} else {
 		va += base_level_info->offset;
 	}
 
 	state[0] = va >> 8;
 	state[1] &= C_008F14_BASE_ADDRESS_HI;
 	state[1] |= S_008F14_BASE_ADDRESS_HI(va >> 40);
 
+	/* Only macrotiled modes can set tile swizzle.
+	 * GFX9 doesn't use (legacy) base_level_info.
+	 */
+	if (sscreen->b.chip_class >= GFX9 ||
+	    base_level_info->mode == RADEON_SURF_MODE_2D)
+		state[0] |= tex->surface.tile_swizzle;
+
 	if (sscreen->b.chip_class >= VI) {
 		state[6] &= C_008F28_COMPRESSION_EN;
 		state[7] = 0;
 
 		if (vi_dcc_enabled(tex, first_level)) {
 			meta_va = (!tex->dcc_separate_buffer ? tex->resource.gpu_address : 0) +
 				  tex->dcc_offset;
 
-			if (sscreen->b.chip_class <= VI)
+			if (sscreen->b.chip_class == VI) {
 				meta_va += base_level_info->dcc_offset;
+				assert(base_level_info->mode == RADEON_SURF_MODE_2D);
+			}
+
+			meta_va |= (uint32_t)tex->surface.tile_swizzle << 8;
 		} else if (tex->tc_compatible_htile && first_level == 0) {
 			meta_va = tex->resource.gpu_address + tex->htile_offset;
 		}
 
 		if (meta_va) {
 			state[6] |= S_008F28_COMPRESSION_EN(1);
 			state[7] = meta_va >> 8;
 		}
 	}
 
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index 6e67824..c9bb108 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -2760,47 +2760,51 @@ static void si_emit_framebuffer_state(struct si_context *sctx, struct r600_atom
 						  RADEON_USAGE_READWRITE,
 						  RADEON_PRIO_DCC);
 
 		/* Compute mutable surface parameters. */
 		cb_color_base = tex->resource.gpu_address >> 8;
 		cb_color_fmask = 0;
 		cb_dcc_base = 0;
 		cb_color_info = cb->cb_color_info | tex->cb_color_info;
 		cb_color_attrib = cb->cb_color_attrib;
 
-		if (tex->fmask.size)
+		if (tex->fmask.size) {
 			cb_color_fmask = (tex->resource.gpu_address + tex->fmask.offset) >> 8;
+			cb_color_fmask |= tex->fmask.tile_swizzle;
+		}
 
 		/* Set up DCC. */
 		if (vi_dcc_enabled(tex, cb->base.u.tex.level)) {
 			bool is_msaa_resolve_dst = state->cbufs[0] &&
 						   state->cbufs[0]->texture->nr_samples > 1 &&
 						   state->cbufs[1] == &cb->base &&
 						   state->cbufs[1]->texture->nr_samples <= 1;
 
 			if (!is_msaa_resolve_dst)
 				cb_color_info |= S_028C70_DCC_ENABLE(1);
 
 			cb_dcc_base = ((!tex->dcc_separate_buffer ? tex->resource.gpu_address : 0) +
 				       tex->dcc_offset) >> 8;
+			cb_dcc_base |= tex->surface.tile_swizzle;
 		}
 
 		if (sctx->b.chip_class >= GFX9) {
 			struct gfx9_surf_meta_flags meta;
 
 			if (tex->dcc_offset)
 				meta = tex->surface.u.gfx9.dcc;
 			else
 				meta = tex->surface.u.gfx9.cmask;
 
 			/* Set mutable surface parameters. */
 			cb_color_base += tex->surface.u.gfx9.surf_offset >> 8;
+			cb_color_base |= tex->surface.tile_swizzle;
 			if (!tex->fmask.size)
 				cb_color_fmask = cb_color_base;
 			cb_color_attrib |= S_028C74_COLOR_SW_MODE(tex->surface.u.gfx9.surf.swizzle_mode) |
 					   S_028C74_FMASK_SW_MODE(tex->surface.u.gfx9.fmask.swizzle_mode) |
 					   S_028C74_RB_ALIGNED(meta.rb_aligned) |
 					   S_028C74_PIPE_ALIGNED(meta.pipe_aligned);
 
 			radeon_set_context_reg_seq(cs, R_028C60_CB_COLOR0_BASE + i * 0x3C, 15);
 			radeon_emit(cs, cb_color_base);		/* CB_COLOR0_BASE */
 			radeon_emit(cs, cb_color_base >> 32);	/* CB_COLOR0_BASE_EXT */
@@ -2821,20 +2825,24 @@ static void si_emit_framebuffer_state(struct si_context *sctx, struct r600_atom
 			radeon_set_context_reg(cs, R_0287A0_CB_MRT0_EPITCH + i * 4,
 					       S_0287A0_EPITCH(tex->surface.u.gfx9.surf.epitch));
 		} else {
 			/* Compute mutable surface parameters (SI-CI-VI). */
 			const struct legacy_surf_level *level_info =
 				&tex->surface.u.legacy.level[cb->base.u.tex.level];
 			unsigned pitch_tile_max, slice_tile_max, tile_mode_index;
 			unsigned cb_color_pitch, cb_color_slice, cb_color_fmask_slice;
 
 			cb_color_base += level_info->offset >> 8;
+			/* Only macrotiled modes can set tile swizzle. */
+			if (level_info->mode == RADEON_SURF_MODE_2D)
+				cb_color_base |= tex->surface.tile_swizzle;
+
 			if (!tex->fmask.size)
 				cb_color_fmask = cb_color_base;
 			if (cb_dcc_base)
 				cb_dcc_base += level_info->dcc_offset >> 8;
 
 			pitch_tile_max = level_info->nblk_x / 8 - 1;
 			slice_tile_max = level_info->nblk_x *
 					 level_info->nblk_y / 64 - 1;
 			tile_mode_index = si_tile_mode_index(tex, cb->base.u.tex.level, false);
 
@@ -3409,21 +3417,21 @@ si_make_texture_descriptor(struct si_screen *screen,
 				break;
 			case 8:
 				data_format = V_008F14_IMG_DATA_FORMAT_FMASK32_S8_F8;
 				break;
 			default:
 				unreachable("invalid nr_samples");
 			}
 			num_format = V_008F14_IMG_NUM_FORMAT_UINT;
 		}
 
-		fmask_state[0] = va >> 8;
+		fmask_state[0] = (va >> 8) | tex->fmask.tile_swizzle;
 		fmask_state[1] = S_008F14_BASE_ADDRESS_HI(va >> 40) |
 				 S_008F14_DATA_FORMAT_GFX6(data_format) |
 				 S_008F14_NUM_FORMAT_GFX6(num_format);
 		fmask_state[2] = S_008F18_WIDTH(width - 1) |
 				 S_008F18_HEIGHT(height - 1);
 		fmask_state[3] = S_008F1C_DST_SEL_X(V_008F1C_SQ_SEL_X) |
 				 S_008F1C_DST_SEL_Y(V_008F1C_SQ_SEL_X) |
 				 S_008F1C_DST_SEL_Z(V_008F1C_SQ_SEL_X) |
 				 S_008F1C_DST_SEL_W(V_008F1C_SQ_SEL_X) |
 				 S_008F1C_TYPE(si_tex_dim(screen, tex, target, 0));
-- 
2.7.4



More information about the mesa-dev mailing list