[Mesa-dev] [PATCH 03/10] radeonsi: set some image descriptor fields at bind time

Marek Olšák maraeo at gmail.com
Thu May 19 10:59:11 UTC 2016


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

mainly the fields that can change by reallocating a texture and changing
the tile mode
---
 src/gallium/drivers/radeonsi/si_descriptors.c | 64 +++++++++++++----
 src/gallium/drivers/radeonsi/si_pipe.h        |  3 +
 src/gallium/drivers/radeonsi/si_state.c       | 99 ++++++++++++---------------
 src/gallium/drivers/radeonsi/si_state.h       | 16 ++++-
 4 files changed, 111 insertions(+), 71 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 855b79e..48b1e14 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -60,6 +60,7 @@
 #include "si_shader.h"
 #include "sid.h"
 
+#include "util/u_format.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 #include "util/u_suballoc.h"
@@ -294,40 +295,70 @@ static void si_sampler_views_begin_new_cs(struct si_context *sctx,
 			      RADEON_USAGE_READWRITE, RADEON_PRIO_DESCRIPTORS);
 }
 
+void si_set_mutable_tex_desc_fields(struct r600_texture *tex,
+				    const struct radeon_surf_level *base_level_info,
+				    unsigned base_level, unsigned block_width,
+				    bool is_stencil, uint32_t *state)
+{
+	uint64_t va = tex->resource.gpu_address + base_level_info->offset;
+	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;
+	state[6] &= C_008F28_COMPRESSION_EN;
+
+	state[0] = va >> 8;
+	state[1] |= S_008F14_BASE_ADDRESS_HI(va >> 40);
+	state[3] |= S_008F1C_TILING_INDEX(si_tile_mode_index(tex, base_level,
+							     is_stencil));
+	state[4] |= S_008F20_PITCH(pitch - 1);
+
+	if (tex->dcc_offset) {
+		state[6] |= S_008F28_COMPRESSION_EN(1);
+		state[7] = (tex->resource.gpu_address +
+			    tex->dcc_offset +
+			    base_level_info->dcc_offset) >> 8;
+	}
+}
+
 static void si_set_sampler_view(struct si_context *sctx,
 				struct si_sampler_views *views,
 				unsigned slot, struct pipe_sampler_view *view)
 {
 	struct si_sampler_view *rview = (struct si_sampler_view*)view;
 
-	if (view && view->texture && view->texture->target != PIPE_BUFFER &&
-	    G_008F28_COMPRESSION_EN(rview->state[6]) &&
-	    ((struct r600_texture*)view->texture)->dcc_offset == 0) {
-		rview->state[6] &= C_008F28_COMPRESSION_EN &
-		                   C_008F28_ALPHA_IS_ON_MSB;
-	} else if (views->views[slot] == view)
+	if (views->views[slot] == view)
 		return;
 
 	if (view) {
 		struct r600_texture *rtex = (struct r600_texture *)view->texture;
+		uint32_t *desc = views->desc.list + slot * 16;
 
 		si_sampler_view_add_buffer(sctx, view->texture,
 					   RADEON_USAGE_READ);
 
 		pipe_sampler_view_reference(&views->views[slot], view);
-		memcpy(views->desc.list + slot * 16, rview->state, 8*4);
+		memcpy(desc, rview->state, 8*4);
+
+		if (view->texture && view->texture->target != PIPE_BUFFER)
+			si_set_mutable_tex_desc_fields(rtex,
+						       rview->base_level_info,
+						       rview->base_level,
+						       rview->block_width,
+						       false, desc);
 
 		if (view->texture && view->texture->target != PIPE_BUFFER &&
 		    rtex->fmask.size) {
-			memcpy(views->desc.list + slot*16 + 8,
+			memcpy(desc + 8,
 			       rview->fmask_state, 8*4);
 		} else {
 			/* Disable FMASK and bind sampler state in [12:15]. */
-			memcpy(views->desc.list + slot*16 + 8,
+			memcpy(desc + 8,
 			       null_texture_descriptor, 4*4);
 
 			if (views->sampler_states[slot])
-				memcpy(views->desc.list + slot*16 + 12,
+				memcpy(desc + 12,
 				       views->sampler_states[slot], 4*4);
 		}
 
@@ -513,6 +544,7 @@ si_set_shader_images(struct pipe_context *pipe, unsigned shader,
 			struct r600_texture *tex = (struct r600_texture *)res;
 			unsigned level;
 			unsigned width, height, depth;
+			uint32_t *desc = images->desc.list + slot * 8;
 
 			assert(!tex->is_depth);
 			assert(tex->fmask.size == 0);
@@ -538,13 +570,17 @@ si_set_shader_images(struct pipe_context *pipe, unsigned shader,
 			height = u_minify(res->b.b.height0, level);
 			depth = u_minify(res->b.b.depth0, level);
 
-			si_make_texture_descriptor(screen, tex, false, res->b.b.target,
+			si_make_texture_descriptor(screen, tex,
+						   false, res->b.b.target,
 						   views[i].format, swizzle,
-						   level, 0, 0,
+						   0, 0,
 						   views[i].u.tex.first_layer, views[i].u.tex.last_layer,
 						   width, height, depth,
-						   images->desc.list + slot * 8,
-						   NULL);
+						   desc, NULL);
+			si_set_mutable_tex_desc_fields(tex, tex->surface.level,
+						       level,
+						       util_format_get_blockwidth(views[i].format),
+						       false, desc);
 		}
 
 		images->desc.enabled_mask |= 1u << slot;
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 33d3d25..89f4f51 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -121,6 +121,9 @@ struct si_sampler_view {
          * [4..7] = buffer descriptor */
 	uint32_t			state[8];
 	uint32_t			fmask_state[8];
+	const struct radeon_surf_level	*base_level_info;
+	unsigned			base_level;
+	unsigned			block_width;
 	bool is_stencil_sampler;
 };
 
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index aefa336..45b4021 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -1834,19 +1834,6 @@ boolean si_is_format_supported(struct pipe_screen *screen,
 	return retval == usage;
 }
 
-static unsigned si_tile_mode_index(struct r600_texture *rtex, unsigned level,
-				   bool stencil)
-{
-	unsigned tile_mode_index = 0;
-
-	if (stencil) {
-		tile_mode_index = rtex->surface.stencil_tiling_index[level];
-	} else {
-		tile_mode_index = rtex->surface.tiling_index[level];
-	}
-	return tile_mode_index;
-}
-
 /*
  * framebuffer handling
  */
@@ -2619,42 +2606,19 @@ si_make_texture_descriptor(struct si_screen *screen,
 			   enum pipe_texture_target target,
 			   enum pipe_format pipe_format,
 			   const unsigned char state_swizzle[4],
-			   unsigned base_level, unsigned first_level, unsigned last_level,
+			   unsigned first_level, unsigned last_level,
 			   unsigned first_layer, unsigned last_layer,
 			   unsigned width, unsigned height, unsigned depth,
 			   uint32_t *state,
 			   uint32_t *fmask_state)
 {
 	struct pipe_resource *res = &tex->resource.b.b;
-	const struct radeon_surf_level *surflevel = tex->surface.level;
 	const struct util_format_description *desc;
 	unsigned char swizzle[4];
 	int first_non_void;
 	unsigned num_format, data_format, type;
-	uint32_t pitch;
 	uint64_t va;
 
-	/* Texturing with separate depth and stencil. */
-	if (tex->is_depth && !tex->is_flushing_texture) {
-		switch (pipe_format) {
-		case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
-			pipe_format = PIPE_FORMAT_Z32_FLOAT;
-			break;
-		case PIPE_FORMAT_X8Z24_UNORM:
-		case PIPE_FORMAT_S8_UINT_Z24_UNORM:
-			/* Z24 is always stored like this. */
-			pipe_format = PIPE_FORMAT_Z24X8_UNORM;
-			break;
-		case PIPE_FORMAT_X24S8_UINT:
-		case PIPE_FORMAT_S8X24_UINT:
-		case PIPE_FORMAT_X32_S8X24_UINT:
-			pipe_format = PIPE_FORMAT_S8_UINT;
-			surflevel = tex->surface.stencil_level;
-			break;
-		default:;
-		}
-	}
-
 	desc = util_format_description(pipe_format);
 
 	if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
@@ -2774,12 +2738,8 @@ si_make_texture_descriptor(struct si_screen *screen,
 	} else if (type == V_008F1C_SQ_RSRC_IMG_CUBE)
 		depth = res->array_size / 6;
 
-	pitch = surflevel[base_level].nblk_x * util_format_get_blockwidth(pipe_format);
-	va = tex->resource.gpu_address + surflevel[base_level].offset;
-
-	state[0] = va >> 8;
-	state[1] = (S_008F14_BASE_ADDRESS_HI(va >> 40) |
-		    S_008F14_DATA_FORMAT(data_format) |
+	state[0] = 0;
+	state[1] = (S_008F14_DATA_FORMAT(data_format) |
 		    S_008F14_NUM_FORMAT(num_format));
 	state[2] = (S_008F18_WIDTH(width - 1) |
 		    S_008F18_HEIGHT(height - 1));
@@ -2792,24 +2752,19 @@ si_make_texture_descriptor(struct si_screen *screen,
 		    S_008F1C_LAST_LEVEL(res->nr_samples > 1 ?
 					util_logbase2(res->nr_samples) :
 					last_level) |
-		    S_008F1C_TILING_INDEX(si_tile_mode_index(tex, base_level, false)) |
 		    S_008F1C_POW2_PAD(res->last_level > 0) |
 		    S_008F1C_TYPE(type));
-	state[4] = (S_008F20_DEPTH(depth - 1) | S_008F20_PITCH(pitch - 1));
+	state[4] = S_008F20_DEPTH(depth - 1);
 	state[5] = (S_008F24_BASE_ARRAY(first_layer) |
 		    S_008F24_LAST_ARRAY(last_layer));
+	state[6] = 0;
+	state[7] = 0;
 
 	if (tex->dcc_offset) {
 		unsigned swap = r600_translate_colorswap(pipe_format, FALSE);
 
-		state[6] = S_008F28_COMPRESSION_EN(1) | S_008F28_ALPHA_IS_ON_MSB(swap <= 1);
-		state[7] = (tex->resource.gpu_address +
-			    tex->dcc_offset +
-			    surflevel[base_level].dcc_offset) >> 8;
+		state[6] = S_008F28_ALPHA_IS_ON_MSB(swap <= 1);
 	} else {
-		state[6] = 0;
-		state[7] = 0;
-
 		/* The last dword is unused by hw. The shader uses it to clear
 		 * bits in the first dword of sampler state.
 		 */
@@ -2887,6 +2842,8 @@ si_create_sampler_view_custom(struct pipe_context *ctx,
 	unsigned char state_swizzle[4];
 	unsigned height, depth, width;
 	unsigned last_layer = state->u.tex.last_layer;
+	enum pipe_format pipe_format;
+	const struct radeon_surf_level *surflevel;
 
 	if (!view)
 		return NULL;
@@ -2958,13 +2915,40 @@ si_create_sampler_view_custom(struct pipe_context *ctx,
 	    state->target == PIPE_TEXTURE_CUBE)
 		last_layer = state->u.tex.first_layer;
 
-	si_make_texture_descriptor(sctx->screen, tmp, true, state->target,
-				   state->format, state_swizzle,
-				   base_level, first_level, last_level,
+	/* Texturing with separate depth and stencil. */
+	pipe_format = state->format;
+	surflevel = tmp->surface.level;
+
+	if (tmp->is_depth && !tmp->is_flushing_texture) {
+		switch (pipe_format) {
+		case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+			pipe_format = PIPE_FORMAT_Z32_FLOAT;
+			break;
+		case PIPE_FORMAT_X8Z24_UNORM:
+		case PIPE_FORMAT_S8_UINT_Z24_UNORM:
+			/* Z24 is always stored like this. */
+			pipe_format = PIPE_FORMAT_Z24X8_UNORM;
+			break;
+		case PIPE_FORMAT_X24S8_UINT:
+		case PIPE_FORMAT_S8X24_UINT:
+		case PIPE_FORMAT_X32_S8X24_UINT:
+			pipe_format = PIPE_FORMAT_S8_UINT;
+			surflevel = tmp->surface.stencil_level;
+			break;
+		default:;
+		}
+	}
+
+	si_make_texture_descriptor(sctx->screen, tmp, true,
+				   state->target, pipe_format, state_swizzle,
+				   first_level, last_level,
 				   state->u.tex.first_layer, last_layer,
 				   width, height, depth,
 				   view->state, view->fmask_state);
 
+	view->base_level_info = &surflevel[base_level];
+	view->base_level = base_level;
+	view->block_width = util_format_get_blockwidth(pipe_format);
 	return &view->base;
 }
 
@@ -3438,11 +3422,14 @@ static void si_query_opaque_metadata(struct r600_common_screen *rscreen,
 
 	si_make_texture_descriptor(sscreen, rtex, true,
 				   res->target, res->format,
-				   swizzle, 0, 0, res->last_level, 0,
+				   swizzle, 0, res->last_level, 0,
 				   is_array ? res->array_size - 1 : 0,
 				   res->width0, res->height0, res->depth0,
 				   desc, NULL);
 
+	si_set_mutable_tex_desc_fields(rtex, &rtex->surface.level[0], 0,
+				       rtex->surface.blk_w, false, desc);
+
 	/* Clear the base address and set the relative DCC offset. */
 	desc[0] = 0;
 	desc[1] &= C_008F14_BASE_ADDRESS_HI;
diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h
index f2a3b03..c74214a 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -248,6 +248,10 @@ struct si_buffer_resources {
 
 /* si_descriptors.c */
 void si_ce_enable_loads(struct radeon_winsys_cs *ib);
+void si_set_mutable_tex_desc_fields(struct r600_texture *tex,
+				    const struct radeon_surf_level *base_level_info,
+				    unsigned base_level, unsigned block_width,
+				    bool is_stencil, uint32_t *state);
 void si_set_ring_buffer(struct pipe_context *ctx, uint slot,
 			struct pipe_resource *buffer,
 			unsigned stride, unsigned num_records,
@@ -294,7 +298,7 @@ si_make_texture_descriptor(struct si_screen *screen,
 			   enum pipe_texture_target target,
 			   enum pipe_format pipe_format,
 			   const unsigned char state_swizzle[4],
-			   unsigned base_level, unsigned first_level, unsigned last_level,
+			   unsigned first_level, unsigned last_level,
 			   unsigned first_layer, unsigned last_layer,
 			   unsigned width, unsigned height, unsigned depth,
 			   uint32_t *state,
@@ -319,4 +323,14 @@ void si_ce_post_draw_synchronization(struct si_context *sctx);
 void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo);
 void si_trace_emit(struct si_context *sctx);
 
+
+static inline unsigned
+si_tile_mode_index(struct r600_texture *rtex, unsigned level, bool stencil)
+{
+	if (stencil)
+		return rtex->surface.stencil_tiling_index[level];
+	else
+		return rtex->surface.tiling_index[level];
+}
+
 #endif
-- 
2.7.4



More information about the mesa-dev mailing list