radv: Fix up 2_10_10_10 alpha sign.
authorBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Sat, 12 May 2018 21:50:04 +0000 (23:50 +0200)
committerBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Mon, 14 May 2018 16:58:20 +0000 (18:58 +0200)
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 18.1 <mesa-stable@lists.freedesktop.org>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=106480
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
src/amd/vulkan/radv_nir_to_llvm.c
src/amd/vulkan/radv_pipeline.c
src/amd/vulkan/radv_private.h
src/amd/vulkan/radv_shader.h

index f98940f0d8f2919b4f42de1b7337144f29de1f01..47c52dc437b04a8b470faf102d7caa11bdb3e819 100644 (file)
@@ -1865,6 +1865,47 @@ static LLVMValueRef radv_get_sampler_desc(struct ac_shader_abi *abi,
        return ac_build_load_to_sgpr(&ctx->ac, list, index);
 }
 
+/* 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 radv_shader_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 radv_shader_context *ctx,
@@ -1875,18 +1916,19 @@ handle_vs_input_decl(struct radv_shader_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);
        uint8_t input_usage_mask =
                ctx->shader_info->info.vs.input_usage_mask[variable->data.location];
        unsigned num_channels = util_last_bit(input_usage_mask);
 
-       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))) {
-                       uint32_t divisor = ctx->options->key.vs.instance_rate_divisors[index + i];
+               if (ctx->options->key.vs.instance_rate_inputs & (1u << attrib_index)) {
+                       uint32_t divisor = ctx->options->key.vs.instance_rate_divisors[attrib_index];
 
                        if (divisor) {
                                buffer_index = LLVMBuildAdd(ctx->ac.builder, ctx->abi.instance_id,
@@ -1910,7 +1952,7 @@ handle_vs_input_decl(struct radv_shader_context *ctx,
                } else
                        buffer_index = LLVMBuildAdd(ctx->ac.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);
 
@@ -1923,9 +1965,15 @@ handle_vs_input_decl(struct radv_shader_context *ctx,
 
                for (unsigned chan = 0; chan < 4; chan++) {
                        LLVMValueRef llvm_chan = LLVMConstInt(ctx->ac.i32, chan, false);
-                       ctx->inputs[ac_llvm_reg_index_soa(idx, chan)] =
-                               ac_to_integer(&ctx->ac, LLVMBuildExtractElement(ctx->ac.builder,
-                                                       input, llvm_chan, ""));
+                       output[chan] = LLVMBuildExtractElement(ctx->ac.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[ac_llvm_reg_index_soa(variable->data.location + i, chan)] =
+                               ac_to_integer(&ctx->ac, output[chan]);
                }
        }
 }
index 7a577dae413a58708f4a247480820fbedcd61c80..52734a308a92cfd721d3ef82ab954835c0430b1a 100644 (file)
@@ -1813,13 +1813,36 @@ 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)) {
-                       unsigned location = input_state->pVertexAttributeDescriptions[i].location;
                        key.instance_rate_inputs |= 1u << location;
                        key.instance_rate_divisors[location] = instance_rate_divisors[binding];
                }
+
+               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)
@@ -1848,6 +1871,7 @@ radv_fill_shader_keys(struct radv_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;
        for (unsigned i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
                keys[MESA_SHADER_VERTEX].vs.instance_rate_divisors[i] = key->instance_rate_divisors[i];
 
index 4805acab280c1ef90a64e9cb600bd424f8f901de..e3eed887fae098e02005cee01f2337553f427e68 100644 (file)
@@ -352,6 +352,7 @@ struct radv_pipeline_cache {
 struct radv_pipeline_key {
        uint32_t instance_rate_inputs;
        uint32_t instance_rate_divisors[MAX_VERTEX_ATTRIBS];
+       uint64_t vertex_alpha_adjust;
        unsigned tess_input_vertices;
        uint32_t col_format;
        uint32_t is_int8;
index 12878307ecdac1491316f6c7dc55e911fe97f6e2..b711cba80cfbfd3b23d0e4784b2f68b4b83916a8 100644 (file)
@@ -55,9 +55,21 @@ struct radv_shader_module {
        char data[0];
 };
 
+enum {
+       RADV_ALPHA_ADJUST_NONE = 0,
+       RADV_ALPHA_ADJUST_SNORM = 1,
+       RADV_ALPHA_ADJUST_SINT = 2,
+       RADV_ALPHA_ADJUST_SSCALED = 3,
+};
+
 struct radv_vs_variant_key {
        uint32_t instance_rate_inputs;
        uint32_t instance_rate_divisors[MAX_VERTEX_ATTRIBS];
+
+       /* 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;