[Mesa-dev] [PATCH 7/9] radeonsi: use an SGPR instead of VGT_INDX_OFFSET

Marek Olšák maraeo at gmail.com
Sat Apr 26 06:27:40 PDT 2014


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

The draw indirect packets cannot set VGT_INDX_OFFSET, they can only set user
data SGPRs. This is the only way to support start/index_bias with indirect
drawing.

This breaks transform feedback with 4 buffers, because the calling convention
doesn't allow so many input SGPRs.
---
 src/gallium/drivers/radeonsi/si_shader.c     | 11 +++++++----
 src/gallium/drivers/radeonsi/si_shader.h     | 10 ++++++----
 src/gallium/drivers/radeonsi/si_state.c      |  1 +
 src/gallium/drivers/radeonsi/si_state_draw.c | 15 +++++++++------
 4 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index a27f7f8..6c0cba7 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -225,10 +225,12 @@ static void declare_input_vs(
 		si_shader_ctx->shader->shader.uses_instanceid = true;
 		buffer_index = get_instance_index_for_fetch(&si_shader_ctx->radeon_bld, divisor);
 	} else {
-		/* Load the buffer index, which is always stored in VGPR0
-		 * for Vertex Shaders */
-		buffer_index = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn,
-					    si_shader_ctx->param_vertex_id);
+		/* Load the buffer index for vertices. */
+		LLVMValueRef vertex_id = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn,
+						      si_shader_ctx->param_vertex_id);
+		LLVMValueRef base_vertex = LLVMGetParam(radeon_bld->main_fn,
+							SI_PARAM_BASE_VERTEX);
+		buffer_index = LLVMBuildAdd(gallivm->builder, base_vertex, vertex_id, "");
 	}
 
 	vec4_type = LLVMVectorType(base->elem_type, 4);
@@ -2116,6 +2118,7 @@ static void create_function(struct si_shader_context *si_shader_ctx)
 	switch (si_shader_ctx->type) {
 	case TGSI_PROCESSOR_VERTEX:
 		params[SI_PARAM_VERTEX_BUFFER] = params[SI_PARAM_CONST];
+		params[SI_PARAM_BASE_VERTEX] = i32;
 		params[SI_PARAM_START_INSTANCE] = i32;
 		num_params = SI_PARAM_START_INSTANCE+1;
 		if (shader->key.vs.as_es) {
diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h
index d667baf..eb056ac 100644
--- a/src/gallium/drivers/radeonsi/si_shader.h
+++ b/src/gallium/drivers/radeonsi/si_shader.h
@@ -36,10 +36,11 @@
 #define SI_SGPR_RESOURCE	4
 #define SI_SGPR_RW_BUFFERS	6  /* rings (& stream-out, VS only) */
 #define SI_SGPR_VERTEX_BUFFER	8  /* VS only */
-#define SI_SGPR_START_INSTANCE	10 /* VS only */
+#define SI_SGPR_BASE_VERTEX	10 /* VS only */
+#define SI_SGPR_START_INSTANCE	11 /* VS only */
 #define SI_SGPR_ALPHA_REF	8  /* PS only */
 
-#define SI_VS_NUM_USER_SGPR	11
+#define SI_VS_NUM_USER_SGPR	12
 #define SI_GS_NUM_USER_SGPR	8
 #define SI_PS_NUM_USER_SGPR	9
 
@@ -51,11 +52,12 @@
 
 /* VS only parameters */
 #define SI_PARAM_VERTEX_BUFFER	4
-#define SI_PARAM_START_INSTANCE	5
+#define SI_PARAM_BASE_VERTEX	5
+#define SI_PARAM_START_INSTANCE	6
 /* the other VS parameters are assigned dynamically */
 
 /* ES only parameters */
-#define SI_PARAM_ES2GS_OFFSET	6
+#define SI_PARAM_ES2GS_OFFSET	7
 
 /* GS only parameters */
 #define SI_PARAM_GS2VS_OFFSET	4
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index e8f2454..1660405 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -3159,6 +3159,7 @@ void si_init_config(struct si_context *sctx)
 		       S_02800C_FORCE_HIS_ENABLE1(V_02800C_FORCE_DISABLE));
 	si_pm4_set_reg(pm4, R_028400_VGT_MAX_VTX_INDX, ~0);
 	si_pm4_set_reg(pm4, R_028404_VGT_MIN_VTX_INDX, 0);
+	si_pm4_set_reg(pm4, R_028408_VGT_INDX_OFFSET, 0);
 
 	if (sctx->b.chip_class >= CIK) {
 		si_pm4_set_reg(pm4, R_00B118_SPI_SHADER_PGM_RSRC3_VS, S_00B118_CU_EN(0xffff));
diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c
index 0676b15..ab6b0e0 100644
--- a/src/gallium/drivers/radeonsi/si_state_draw.c
+++ b/src/gallium/drivers/radeonsi/si_state_draw.c
@@ -440,14 +440,8 @@ static bool si_update_draw_info_state(struct si_context *sctx,
 	}
 
 	si_pm4_set_reg(pm4, R_028A6C_VGT_GS_OUT_PRIM_TYPE, gs_out_prim);
-	si_pm4_set_reg(pm4, R_028408_VGT_INDX_OFFSET,
-		       info->indexed ? info->index_bias : info->start);
 	si_pm4_set_reg(pm4, R_02840C_VGT_MULTI_PRIM_IB_RESET_INDX, info->restart_index);
 	si_pm4_set_reg(pm4, R_028A94_VGT_MULTI_PRIM_IB_RESET_EN, info->primitive_restart);
-	si_pm4_set_reg(pm4, SI_SGPR_START_INSTANCE * 4 +
-		       (sctx->gs_shader ? R_00B330_SPI_SHADER_USER_DATA_ES_0 :
-			R_00B130_SPI_SHADER_USER_DATA_VS_0),
-		       info->start_instance);
 
         if (prim == V_008958_DI_PT_LINELIST)
                 ls_mask = 1;
@@ -744,6 +738,8 @@ static void si_state_draw(struct si_context *sctx,
 			  const struct pipe_draw_info *info,
 			  const struct pipe_index_buffer *ib)
 {
+	unsigned sh_base_reg = (sctx->gs_shader ? R_00B330_SPI_SHADER_USER_DATA_ES_0 :
+						  R_00B130_SPI_SHADER_USER_DATA_VS_0);
 	struct si_pm4_state *pm4 = si_pm4_alloc_state(sctx);
 
 	if (pm4 == NULL)
@@ -805,6 +801,13 @@ static void si_state_draw(struct si_context *sctx,
 	si_pm4_cmd_add(pm4, info->instance_count);
 	si_pm4_cmd_end(pm4, sctx->b.predicate_drawing);
 
+	if (!info->indirect) {
+		si_pm4_set_reg(pm4, sh_base_reg + SI_SGPR_BASE_VERTEX * 4,
+			       info->indexed ? info->index_bias : info->start);
+		si_pm4_set_reg(pm4, sh_base_reg + SI_SGPR_START_INSTANCE * 4,
+			       info->start_instance);
+	}
+
 	if (info->indexed) {
 		uint32_t max_size = (ib->buffer->width0 - ib->offset) /
 				 sctx->index_buffer.index_size;
-- 
1.8.3.2



More information about the mesa-dev mailing list