[Mesa-dev] [PATCH] radv: Fix up 2_10_10_10 alpha sign.

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Mon May 14 20:33:23 UTC 2018


Pre-Vega HW always interprets the alpha for this format as unsigned,
so we have to implement a fixup to do the sign correctly for signed
formats.

v2: Improve indexing mess.

CC: 18.0 <mesa-stable at lists.freedesktop.org>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=106480
Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
(Backport of 3d4d388e392 "radv: Fix up 2_10_10_10 alpha sign.")
---
 src/amd/common/ac_nir_to_llvm.c | 67 ++++++++++++++++++++++++++++-----
 src/amd/common/ac_nir_to_llvm.h | 12 ++++++
 src/amd/vulkan/radv_pipeline.c  | 29 +++++++++++++-
 src/amd/vulkan/radv_private.h   |  1 +
 4 files changed, 98 insertions(+), 11 deletions(-)

diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c
index d82a059df84..f3afb237038 100644
--- a/src/amd/common/ac_nir_to_llvm.c
+++ b/src/amd/common/ac_nir_to_llvm.c
@@ -5335,6 +5335,48 @@ static void visit_cf_list(struct ac_nir_context *ctx,
 	}
 }
 
+/* For 2_10_10_10 formats the alpha is handled as unsigned by pre-vega HW.
+ * so we may need to fix it up. */
+static LLVMValueRef
+adjust_vertex_fetch_alpha(struct nir_to_llvm_context *ctx,
+                          unsigned adjustment,
+                          LLVMValueRef alpha)
+{
+	if (adjustment == RADV_ALPHA_ADJUST_NONE)
+		return alpha;
+
+	LLVMValueRef c30 = LLVMConstInt(ctx->ac.i32, 30, 0);
+
+	if (adjustment == RADV_ALPHA_ADJUST_SSCALED)
+		alpha = LLVMBuildFPToUI(ctx->ac.builder, alpha, ctx->ac.i32, "");
+	else
+		alpha = ac_to_integer(&ctx->ac, alpha);
+
+	/* For the integer-like cases, do a natural sign extension.
+	 *
+	 * For the SNORM case, the values are 0.0, 0.333, 0.666, 1.0
+	 * and happen to contain 0, 1, 2, 3 as the two LSBs of the
+	 * exponent.
+	 */
+	alpha = LLVMBuildShl(ctx->ac.builder, alpha,
+	                     adjustment == RADV_ALPHA_ADJUST_SNORM ?
+	                     LLVMConstInt(ctx->ac.i32, 7, 0) : c30, "");
+	alpha = LLVMBuildAShr(ctx->ac.builder, alpha, c30, "");
+
+	/* Convert back to the right type. */
+	if (adjustment == RADV_ALPHA_ADJUST_SNORM) {
+		LLVMValueRef clamp;
+		LLVMValueRef neg_one = LLVMConstReal(ctx->ac.f32, -1.0);
+		alpha = LLVMBuildSIToFP(ctx->ac.builder, alpha, ctx->ac.f32, "");
+		clamp = LLVMBuildFCmp(ctx->ac.builder, LLVMRealULT, alpha, neg_one, "");
+		alpha = LLVMBuildSelect(ctx->ac.builder, clamp, neg_one, alpha, "");
+	} else if (adjustment == RADV_ALPHA_ADJUST_SSCALED) {
+		alpha = LLVMBuildSIToFP(ctx->ac.builder, alpha, ctx->ac.f32, "");
+	}
+
+	return alpha;
+}
+
 static void
 handle_vs_input_decl(struct nir_to_llvm_context *ctx,
 		     struct nir_variable *variable)
@@ -5344,14 +5386,15 @@ handle_vs_input_decl(struct nir_to_llvm_context *ctx,
 	LLVMValueRef t_list;
 	LLVMValueRef input;
 	LLVMValueRef buffer_index;
-	int index = variable->data.location - VERT_ATTRIB_GENERIC0;
-	int idx = variable->data.location;
 	unsigned attrib_count = glsl_count_attribute_slots(variable->type, true);
 
-	variable->data.driver_location = idx * 4;
+	variable->data.driver_location = variable->data.location * 4;
+
+	for (unsigned i = 0; i < attrib_count; ++i) {
+		LLVMValueRef output[4];
+		unsigned attrib_index = variable->data.location + i - VERT_ATTRIB_GENERIC0;
 
-	for (unsigned i = 0; i < attrib_count; ++i, ++idx) {
-		if (ctx->options->key.vs.instance_rate_inputs & (1u << (index + i))) {
+		if (ctx->options->key.vs.instance_rate_inputs & (1u << attrib_index)) {
 			buffer_index = LLVMBuildAdd(ctx->builder, ctx->abi.instance_id,
 			                            ctx->abi.start_instance, "");
 			if (ctx->options->key.vs.as_ls) {
@@ -5364,7 +5407,7 @@ handle_vs_input_decl(struct nir_to_llvm_context *ctx,
 		} else
 			buffer_index = LLVMBuildAdd(ctx->builder, ctx->abi.vertex_id,
 			                            ctx->abi.base_vertex, "");
-		t_offset = LLVMConstInt(ctx->ac.i32, index + i, false);
+		t_offset = LLVMConstInt(ctx->ac.i32, attrib_index, false);
 
 		t_list = ac_build_load_to_sgpr(&ctx->ac, t_list_ptr, t_offset);
 
@@ -5375,9 +5418,15 @@ handle_vs_input_decl(struct nir_to_llvm_context *ctx,
 
 		for (unsigned chan = 0; chan < 4; chan++) {
 			LLVMValueRef llvm_chan = LLVMConstInt(ctx->ac.i32, chan, false);
-			ctx->inputs[radeon_llvm_reg_index_soa(idx, chan)] =
-				ac_to_integer(&ctx->ac, LLVMBuildExtractElement(ctx->builder,
-							input, llvm_chan, ""));
+			output[chan] = LLVMBuildExtractElement(ctx->builder, input, llvm_chan, "");
+		}
+
+		unsigned alpha_adjust = (ctx->options->key.vs.alpha_adjust >> (attrib_index * 2)) & 3;
+		output[3] = adjust_vertex_fetch_alpha(ctx, alpha_adjust, output[3]);
+
+		for (unsigned chan = 0; chan < 4; chan++) {
+			ctx->inputs[radeon_llvm_reg_index_soa(variable->data.location + i, chan)] =
+				ac_to_integer(&ctx->ac, output[chan]);
 		}
 	}
 }
diff --git a/src/amd/common/ac_nir_to_llvm.h b/src/amd/common/ac_nir_to_llvm.h
index 1656289e06e..ab8221ee31a 100644
--- a/src/amd/common/ac_nir_to_llvm.h
+++ b/src/amd/common/ac_nir_to_llvm.h
@@ -39,8 +39,20 @@ struct radv_pipeline_layout;
 struct ac_llvm_context;
 struct ac_shader_abi;
 
+enum {
+	RADV_ALPHA_ADJUST_NONE = 0,
+	RADV_ALPHA_ADJUST_SNORM = 1,
+	RADV_ALPHA_ADJUST_SINT = 2,
+	RADV_ALPHA_ADJUST_SSCALED = 3,
+};
+
 struct ac_vs_variant_key {
 	uint32_t instance_rate_inputs;
+
+	/* For 2_10_10_10 formats the alpha is handled as unsigned by pre-vega HW.
+	 * so we may need to fix it up. */
+	uint64_t alpha_adjust;
+
 	uint32_t as_es:1;
 	uint32_t as_ls:1;
 	uint32_t export_prim_id:1;
diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c
index 4255b9315e7..aae67edd2a8 100644
--- a/src/amd/vulkan/radv_pipeline.c
+++ b/src/amd/vulkan/radv_pipeline.c
@@ -1755,10 +1755,34 @@ radv_generate_graphics_pipeline_key(struct radv_pipeline *pipeline,
 	}
 
 	for (unsigned i = 0; i < input_state->vertexAttributeDescriptionCount; ++i) {
-		unsigned binding;
-		binding = input_state->pVertexAttributeDescriptions[i].binding;
+		unsigned location = input_state->pVertexAttributeDescriptions[i].location;
+		unsigned binding = input_state->pVertexAttributeDescriptions[i].binding;
 		if (binding_input_rate & (1u << binding))
 			key.instance_rate_inputs |= 1u << input_state->pVertexAttributeDescriptions[i].location;
+
+		if (pipeline->device->physical_device->rad_info.chip_class <= VI &&
+		    pipeline->device->physical_device->rad_info.family != CHIP_STONEY) {
+			VkFormat format = input_state->pVertexAttributeDescriptions[i].format;
+			uint64_t adjust;
+			switch(format) {
+			case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
+			case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
+				adjust = RADV_ALPHA_ADJUST_SNORM;
+				break;
+			case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
+			case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
+				adjust = RADV_ALPHA_ADJUST_SSCALED;
+				break;
+			case VK_FORMAT_A2R10G10B10_SINT_PACK32:
+			case VK_FORMAT_A2B10G10R10_SINT_PACK32:
+				adjust = RADV_ALPHA_ADJUST_SINT;
+				break;
+			default:
+				adjust = 0;
+				break;
+			}
+			key.vertex_alpha_adjust |= adjust << (2 * location);
+		}
 	}
 
 	if (pCreateInfo->pTessellationState)
@@ -1787,6 +1811,7 @@ radv_fill_shader_keys(struct ac_shader_variant_key *keys,
                       nir_shader **nir)
 {
 	keys[MESA_SHADER_VERTEX].vs.instance_rate_inputs = key->instance_rate_inputs;
+	keys[MESA_SHADER_VERTEX].vs.alpha_adjust = key->vertex_alpha_adjust;
 
 	if (nir[MESA_SHADER_TESS_CTRL]) {
 		keys[MESA_SHADER_VERTEX].vs.as_ls = true;
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index 379ae79ccdf..b160aa93ecb 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -329,6 +329,7 @@ struct radv_pipeline_cache {
 
 struct radv_pipeline_key {
 	uint32_t instance_rate_inputs;
+	uint64_t vertex_alpha_adjust;
 	unsigned tess_input_vertices;
 	uint32_t col_format;
 	uint32_t is_int8;
-- 
2.17.0



More information about the mesa-dev mailing list