[Mesa-dev] [PATCH 2/3] radeonsi: implement vertex color clamping

Marek Olšák maraeo at gmail.com
Sat Oct 10 18:17:29 PDT 2015


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

This is only supported in the compatibility profile (without GS and tess).
---
 src/gallium/drivers/radeonsi/si_pipe.c          |  2 +-
 src/gallium/drivers/radeonsi/si_shader.c        | 42 +++++++++++++++++++++++++
 src/gallium/drivers/radeonsi/si_shader.h        |  8 +++--
 src/gallium/drivers/radeonsi/si_state.c         |  2 ++
 src/gallium/drivers/radeonsi/si_state_shaders.c |  2 +-
 5 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c
index 894fc59..d4be6f9 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.c
+++ b/src/gallium/drivers/radeonsi/si_pipe.c
@@ -271,6 +271,7 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
 	case PIPE_CAP_START_INSTANCE:
 	case PIPE_CAP_NPOT_TEXTURES:
 	case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
+	case PIPE_CAP_VERTEX_COLOR_CLAMPED:
 	case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
         case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
 	case PIPE_CAP_TGSI_INSTANCEID:
@@ -331,7 +332,6 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
 	/* Unsupported features. */
 	case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
 	case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
-	case PIPE_CAP_VERTEX_COLOR_CLAMPED:
 	case PIPE_CAP_USER_VERTEX_BUFFERS:
 	case PIPE_CAP_FAKE_SW_MSAA:
 	case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index 1f9b2b6..8da2f77 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -2075,6 +2075,45 @@ static void si_llvm_emit_vs_epilogue(struct lp_build_tgsi_context * bld_base)
 
 	outputs = MALLOC((info->num_outputs + 1) * sizeof(outputs[0]));
 
+	/* Vertex color clamping.
+	 *
+	 * This uses a state constant loaded in a user data SGPR and
+	 * an IF statement is added that clamps all colors if the constant
+	 * is true.
+	 */
+	if (si_shader_ctx->type == TGSI_PROCESSOR_VERTEX &&
+	    !si_shader_ctx->shader->is_gs_copy_shader) {
+		struct lp_build_if_state if_ctx;
+		LLVMValueRef cond = NULL;
+		LLVMValueRef addr, val;
+
+		for (i = 0; i < info->num_outputs; i++) {
+			if (info->output_semantic_name[i] != TGSI_SEMANTIC_COLOR &&
+			    info->output_semantic_name[i] != TGSI_SEMANTIC_BCOLOR)
+				continue;
+
+			/* We've found a color. */
+			if (!cond) {
+				/* The state is in the first bit of the user SGPR. */
+				cond = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn,
+						    SI_PARAM_VS_STATE_BITS);
+				cond = LLVMBuildTrunc(gallivm->builder, cond,
+						      LLVMInt1TypeInContext(gallivm->context), "");
+				lp_build_if(&if_ctx, gallivm, cond);
+			}
+
+			for (j = 0; j < 4; j++) {
+				addr = si_shader_ctx->radeon_bld.soa.outputs[i][j];
+				val = LLVMBuildLoad(gallivm->builder, addr, "");
+				val = radeon_llvm_saturate(bld_base, val);
+				LLVMBuildStore(gallivm->builder, val, addr);
+			}
+		}
+
+		if (cond)
+			lp_build_endif(&if_ctx);
+	}
+
 	for (i = 0; i < info->num_outputs; i++) {
 		outputs[i].name = info->output_semantic_name[i];
 		outputs[i].sid = info->output_semantic_index[i];
@@ -3444,6 +3483,9 @@ static void create_function(struct si_shader_context *si_shader_ctx)
 			if (shader->is_gs_copy_shader) {
 				last_array_pointer = SI_PARAM_CONST;
 				num_params = SI_PARAM_CONST+1;
+			} else {
+				params[SI_PARAM_VS_STATE_BITS] = i32;
+				num_params = SI_PARAM_VS_STATE_BITS+1;
 			}
 
 			/* The locations of the other parameters are assigned dynamically. */
diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h
index fa5930a..54dad72 100644
--- a/src/gallium/drivers/radeonsi/si_shader.h
+++ b/src/gallium/drivers/radeonsi/si_shader.h
@@ -83,6 +83,7 @@ struct radeon_shader_reloc;
 #define SI_SGPR_VERTEX_BUFFER	8  /* VS only */
 #define SI_SGPR_BASE_VERTEX	10 /* VS only */
 #define SI_SGPR_START_INSTANCE	11 /* VS only */
+#define SI_SGPR_VS_STATE_BITS	12 /* VS(VS) only */
 #define SI_SGPR_LS_OUT_LAYOUT	12 /* VS(LS) only */
 #define SI_SGPR_TCS_OUT_OFFSETS	8  /* TCS & TES only */
 #define SI_SGPR_TCS_OUT_LAYOUT	9  /* TCS & TES only */
@@ -90,8 +91,9 @@ struct radeon_shader_reloc;
 #define SI_SGPR_ALPHA_REF	8  /* PS only */
 #define SI_SGPR_PS_STATE_BITS	9  /* PS only */
 
-#define SI_VS_NUM_USER_SGPR	12
-#define SI_LS_NUM_USER_SGPR	13
+#define SI_VS_NUM_USER_SGPR	13 /* API VS */
+#define SI_ES_NUM_USER_SGPR	12 /* API VS */
+#define SI_LS_NUM_USER_SGPR	13 /* API VS */
 #define SI_TCS_NUM_USER_SGPR	11
 #define SI_TES_NUM_USER_SGPR	10
 #define SI_GS_NUM_USER_SGPR	8
@@ -108,6 +110,8 @@ struct radeon_shader_reloc;
 #define SI_PARAM_VERTEX_BUFFER	4
 #define SI_PARAM_BASE_VERTEX	5
 #define SI_PARAM_START_INSTANCE	6
+/* [0] = clamp vertex color */
+#define SI_PARAM_VS_STATE_BITS	7
 /* the other VS parameters are assigned dynamically */
 
 /* Offsets where TCS outputs and TCS patch outputs live in LDS:
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index 3aafe8a..a81060a 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -760,6 +760,8 @@ static void *si_create_rs_state(struct pipe_context *ctx,
 				   state->fill_back != PIPE_POLYGON_MODE_FILL) |
 		S_028814_POLYMODE_FRONT_PTYPE(si_translate_fill(state->fill_front)) |
 		S_028814_POLYMODE_BACK_PTYPE(si_translate_fill(state->fill_back)));
+	si_pm4_set_reg(pm4, R_00B130_SPI_SHADER_USER_DATA_VS_0 +
+		            SI_SGPR_VS_STATE_BITS * 4, state->clamp_vertex_color);
 
 	/* Precalculate polygon offset states for 16-bit, 24-bit, and 32-bit zbuffers. */
 	for (i = 0; i < 3; i++) {
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c
index c00f8f4..c98509b 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -179,7 +179,7 @@ static void si_shader_es(struct si_shader *shader)
 
 	if (shader->selector->type == PIPE_SHADER_VERTEX) {
 		vgpr_comp_cnt = shader->uses_instanceid ? 3 : 0;
-		num_user_sgprs = SI_VS_NUM_USER_SGPR;
+		num_user_sgprs = SI_ES_NUM_USER_SGPR;
 	} else if (shader->selector->type == PIPE_SHADER_TESS_EVAL) {
 		vgpr_comp_cnt = 3; /* all components are needed for TES */
 		num_user_sgprs = SI_TES_NUM_USER_SGPR;
-- 
2.1.4



More information about the mesa-dev mailing list