[Mesa-dev] [PATCH 07/14] radv: add texture descriptor/fmask/cmask support for GFX9

Dave Airlie airlied at gmail.com
Mon Jun 5 23:14:39 UTC 2017


From: Dave Airlie <airlied at redhat.com>

This adds gfx9 support for the texture descriptor along
with the fmask/cmask allocation routines.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 src/amd/vulkan/radv_image.c | 189 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 158 insertions(+), 31 deletions(-)

diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c
index df0498d..9a2f32b 100644
--- a/src/amd/vulkan/radv_image.c
+++ b/src/amd/vulkan/radv_image.c
@@ -196,27 +196,74 @@ si_set_mutable_tex_desc_fields(struct radv_device *device,
 			       uint32_t *state)
 {
 	uint64_t gpu_address = device->ws->buffer_get_va(image->bo) + image->offset;
-	uint64_t va = gpu_address + base_level_info->offset;
+	uint64_t va = gpu_address;
 	unsigned pitch = base_level_info->nblk_x * block_width;
-
-	state[1] &= C_008F14_BASE_ADDRESS_HI;
-	state[3] &= C_008F1C_TILING_INDEX;
-	state[4] &= C_008F20_PITCH_GFX6;
-	state[6] &= C_008F28_COMPRESSION_EN;
-
-	assert(!(va & 255));
+	enum chip_class chip_class = device->physical_device->rad_info.chip_class;
+	uint64_t meta_va = 0;
+	if (chip_class >= GFX9) {
+		if (is_stencil)
+			va += image->surface.u.gfx9.stencil_offset;
+		else
+			va += image->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);
 	state[3] |= S_008F1C_TILING_INDEX(si_tile_mode_index(image, base_level,
 							     is_stencil));
 	state[4] |= S_008F20_PITCH_GFX6(pitch - 1);
 
-	if (image->surface.dcc_size && first_level < image->surface.num_dcc_levels) {
-		state[6] |= S_008F28_COMPRESSION_EN(1);
-		state[7] = (gpu_address +
-			    image->dcc_offset +
-			    base_level_info->dcc_offset) >> 8;
+	if (chip_class >= VI) {
+		state[6] &= C_008F28_COMPRESSION_EN;
+		state[7] = 0;
+		if (image->surface.dcc_size && first_level < image->surface.num_dcc_levels) {
+			uint64_t meta_va = gpu_address + image->dcc_offset;
+			if (chip_class <= VI)
+				meta_va += base_level_info->dcc_offset;
+			state[6] |= S_008F28_COMPRESSION_EN(1);
+			state[7] = meta_va >> 8;
+
+		}
+	}
+
+	if (chip_class >= GFX9) {
+		state[3] &= C_008F1C_SW_MODE;
+		state[4] &= C_008F20_PITCH_GFX9;
+
+		if (is_stencil) {
+			state[3] |= S_008F1C_SW_MODE(image->surface.u.gfx9.stencil.swizzle_mode);
+			state[4] |= S_008F20_PITCH_GFX9(image->surface.u.gfx9.stencil.epitch);
+		} else {
+			state[3] |= S_008F1C_SW_MODE(image->surface.u.gfx9.surf.swizzle_mode);
+			state[4] |= S_008F20_PITCH_GFX9(image->surface.u.gfx9.surf.epitch);
+		}
+
+		state[5] &= C_008F24_META_DATA_ADDRESS &
+			    C_008F24_META_PIPE_ALIGNED &
+			    C_008F24_META_RB_ALIGNED;
+		if (meta_va) {
+			struct gfx9_surf_meta_flags meta;
+
+			if (image->dcc_offset)
+				meta = image->surface.u.gfx9.dcc;
+			else
+				meta = image->surface.u.gfx9.htile;
+
+			state[5] |= S_008F24_META_DATA_ADDRESS(meta_va >> 40) |
+				    S_008F24_META_PIPE_ALIGNED(meta.pipe_aligned) |
+				    S_008F24_META_RB_ALIGNED(meta.rb_aligned);
+		}
+	} else {
+		/* SI-CI-VI */
+		unsigned pitch = base_level_info->nblk_x * block_width;
+		unsigned index = si_tile_mode_index(image, base_level, is_stencil);
+
+		state[3] &= C_008F1C_TILING_INDEX;
+		state[3] |= S_008F1C_TILING_INDEX(index);
+		state[4] &= C_008F20_PITCH_GFX6;
+		state[4] |= S_008F20_PITCH_GFX6(pitch - 1);
 	}
 }
 
@@ -242,6 +289,36 @@ static unsigned radv_tex_dim(VkImageType image_type, VkImageViewType view_type,
 		unreachable("illegale image type");
 	}
 }
+
+static unsigned gfx9_border_color_swizzle(const unsigned char swizzle[4])
+{
+	unsigned bc_swizzle = V_008F20_BC_SWIZZLE_XYZW;
+
+	if (swizzle[3] == VK_SWIZZLE_X) {
+		/* For the pre-defined border color values (white, opaque
+		 * black, transparent black), the only thing that matters is
+		 * that the alpha channel winds up in the correct place
+		 * (because the RGB channels are all the same) so either of
+		 * these enumerations will work.
+		 */
+		if (swizzle[2] == VK_SWIZZLE_Y)
+			bc_swizzle = V_008F20_BC_SWIZZLE_WZYX;
+		else
+			bc_swizzle = V_008F20_BC_SWIZZLE_WXYZ;
+	} else if (swizzle[0] == VK_SWIZZLE_X) {
+		if (swizzle[1] == VK_SWIZZLE_Y)
+			bc_swizzle = V_008F20_BC_SWIZZLE_XYZW;
+		else
+			bc_swizzle = V_008F20_BC_SWIZZLE_XWYZ;
+	} else if (swizzle[1] == VK_SWIZZLE_X) {
+		bc_swizzle = V_008F20_BC_SWIZZLE_YXWZ;
+	} else if (swizzle[2] == VK_SWIZZLE_X) {
+		bc_swizzle = V_008F20_BC_SWIZZLE_ZYXW;
+	}
+
+	return bc_swizzle;
+}
+
 /**
  * Build the sampler view descriptor for a texture.
  */
@@ -314,11 +391,25 @@ si_make_texture_descriptor(struct radv_device *device,
 		    S_008F1C_TYPE(type));
 	state[4] = 0;
 	state[5] = S_008F24_BASE_ARRAY(first_layer);
-
 	state[6] = 0;
 	state[7] = 0;
 
-	{
+	if (device->physical_device->rad_info.chip_class >= GFX9) {
+		unsigned bc_swizzle = gfx9_border_color_swizzle(desc->swizzle);
+
+		/* Depth is the the last accessible layer on Gfx9.
+		 * The hw doesn't need to know the total number of layers.
+		 */
+		if (type == V_008F1C_SQ_RSRC_IMG_3D)
+			state[4] |= S_008F20_DEPTH(depth - 1);
+		else
+			state[4] |= S_008F20_DEPTH(last_layer);
+
+		state[4] |= S_008F20_BC_SWIZZLE(bc_swizzle);
+		state[5] |= S_008F24_MAX_MIP(image->info.samples > 1 ?
+					     util_logbase2(image->info.samples) :
+					     last_level);
+	} else {
 		state[3] |= S_008F1C_POW2_PAD(image->info.levels > 1);
 		state[4] |= S_008F20_DEPTH(depth - 1);
 		state[5] |= S_008F24_LAST_ARRAY(last_layer);
@@ -341,31 +432,49 @@ si_make_texture_descriptor(struct radv_device *device,
 
 	/* Initialize the sampler view for FMASK. */
 	if (image->fmask.size) {
-		uint32_t fmask_format;
+		uint32_t fmask_format, num_format;
 		uint64_t gpu_address = device->ws->buffer_get_va(image->bo);
 		uint64_t va;
 
 		va = gpu_address + image->offset + image->fmask.offset;
 
-		switch (image->info.samples) {
-		case 2:
-			fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK8_S2_F2;
-			break;
-		case 4:
-			fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK8_S4_F4;
-			break;
-		case 8:
-			fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK32_S8_F8;
-			break;
-		default:
-			assert(0);
-			fmask_format = V_008F14_IMG_DATA_FORMAT_INVALID;
+		if (device->physical_device->rad_info.chip_class >= GFX9) {
+			fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK;
+			switch (image->info.samples) {
+			case 2:
+				num_format = V_008F14_IMG_FMASK_8_2_2;
+				break;
+			case 4:
+				num_format = V_008F14_IMG_FMASK_8_4_4;
+				break;
+			case 8:
+				num_format = V_008F14_IMG_FMASK_32_8_8;
+				break;
+			default:
+				unreachable("invalid nr_samples");
+			}
+		} else {
+			switch (image->info.samples) {
+			case 2:
+				fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK8_S2_F2;
+				break;
+			case 4:
+				fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK8_S4_F4;
+				break;
+			case 8:
+				fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK32_S8_F8;
+				break;
+			default:
+				assert(0);
+				fmask_format = V_008F14_IMG_DATA_FORMAT_INVALID;
+			}
+			num_format = V_008F14_IMG_NUM_FORMAT_UINT;
 		}
 
 		fmask_state[0] = va >> 8;
 		fmask_state[1] = S_008F14_BASE_ADDRESS_HI(va >> 40) |
 			S_008F14_DATA_FORMAT_GFX6(fmask_format) |
-			S_008F14_NUM_FORMAT_GFX6(V_008F14_IMG_NUM_FORMAT_UINT);
+			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) |
@@ -378,7 +487,13 @@ si_make_texture_descriptor(struct radv_device *device,
 		fmask_state[6] = 0;
 		fmask_state[7] = 0;
 
-		{
+		if (device->physical_device->rad_info.chip_class >= GFX9) {
+			fmask_state[3] |= S_008F1C_SW_MODE(image->surface.u.gfx9.fmask.swizzle_mode);
+			fmask_state[4] |= S_008F20_DEPTH(last_layer) |
+					  S_008F20_PITCH_GFX9(image->surface.u.gfx9.fmask.epitch);
+			fmask_state[5] |= S_008F24_META_PIPE_ALIGNED(image->surface.u.gfx9.cmask.pipe_aligned) |
+					  S_008F24_META_RB_ALIGNED(image->surface.u.gfx9.cmask.rb_aligned);
+		} else {
 			fmask_state[3] |= S_008F1C_TILING_INDEX(image->fmask.tile_mode_index);
 			fmask_state[4] |= S_008F20_DEPTH(depth - 1) |
 				S_008F20_PITCH_GFX6(image->fmask.pitch_in_pixels - 1);
@@ -476,6 +591,12 @@ radv_image_get_fmask_info(struct radv_device *device,
 	struct ac_surf_info info = image->info;
 	memset(out, 0, sizeof(*out));
 
+	if (device->physical_device->rad_info.chip_class >= GFX9) {
+		out->alignment = image->surface.u.gfx9.fmask_alignment;
+		out->size = image->surface.u.gfx9.fmask_size;
+		return;
+	}
+
 	fmask.blk_w = image->surface.blk_w;
 	fmask.blk_h = image->surface.blk_h;
 	info.samples = 1;
@@ -533,6 +654,12 @@ radv_image_get_cmask_info(struct radv_device *device,
 	unsigned num_pipes = device->physical_device->rad_info.num_tile_pipes;
 	unsigned cl_width, cl_height;
 
+	if (device->physical_device->rad_info.chip_class >= GFX9) {
+		out->alignment = image->surface.u.gfx9.cmask_alignment;
+		out->size = image->surface.u.gfx9.cmask_size;
+		return;
+	}
+
 	switch (num_pipes) {
 	case 2:
 		cl_width = 32;
-- 
2.9.4



More information about the mesa-dev mailing list