Bas Nieuwenhuizen <b...@basnieuwenhuizen.nl> writes:

> 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.
>
> CC: 18.0 18.1 <mesa-sta...@lists.freedesktop.org>

I couldn't apply this to 18.0.  You will probably need to provide a
backport for Juan.

> ---
>  src/amd/vulkan/radv_nir_to_llvm.c | 61 ++++++++++++++++++++++++++++---
>  src/amd/vulkan/radv_pipeline.c    | 30 +++++++++++++--
>  src/amd/vulkan/radv_private.h     |  1 +
>  src/amd/vulkan/radv_shader.h      | 12 ++++++
>  4 files changed, 95 insertions(+), 9 deletions(-)
>
> diff --git a/src/amd/vulkan/radv_nir_to_llvm.c 
> b/src/amd/vulkan/radv_nir_to_llvm.c
> index f98940f0d8f..9d9ecda63cf 100644
> --- a/src/amd/vulkan/radv_nir_to_llvm.c
> +++ b/src/amd/vulkan/radv_nir_to_llvm.c
> @@ -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 = LLVMBuildBitCast(ctx->ac.builder, alpha, ctx->ac.i32, 
> "");
> +
> +     /* 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,
> @@ -1884,9 +1925,11 @@ handle_vs_input_decl(struct radv_shader_context *ctx,
>  
>       variable->data.driver_location = idx * 4;
>  
> -     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];
> +     for (unsigned i = 0; i < attrib_count; ++i, ++idx, ++index) {
> +             LLVMValueRef output[4];
> +
> +             if (ctx->options->key.vs.instance_rate_inputs & (1u << index)) {
> +                     uint32_t divisor = 
> ctx->options->key.vs.instance_rate_divisors[index];
>  
>                       if (divisor) {
>                               buffer_index = LLVMBuildAdd(ctx->ac.builder, 
> ctx->abi.instance_id,
> @@ -1910,7 +1953,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, index, false);
>  
>               t_list = ac_build_load_to_sgpr(&ctx->ac, t_list_ptr, t_offset);
>  
> @@ -1923,9 +1966,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);
> +                     output[chan] = LLVMBuildExtractElement(ctx->ac.builder, 
> input, llvm_chan, "");
> +             }
> +
> +             unsigned alpha_adjust = (ctx->options->key.vs.alpha_adjust >> 
> (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(idx, chan)] =
> -                             ac_to_integer(&ctx->ac, 
> LLVMBuildExtractElement(ctx->ac.builder,
> -                                                     input, llvm_chan, ""));
> +                             ac_to_integer(&ctx->ac, output[chan]);
>               }
>       }
>  }
> diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c
> index b4e4f3211e2..c3b1195bede 100644
> --- a/src/amd/vulkan/radv_pipeline.c
> +++ b/src/amd/vulkan/radv_pipeline.c
> @@ -1769,13 +1769,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)
> @@ -1804,6 +1827,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];
>  
> diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
> index 5d67271961b..3ffd494befc 100644
> --- a/src/amd/vulkan/radv_private.h
> +++ b/src/amd/vulkan/radv_private.h
> @@ -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;
> diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h
> index 6588b787724..d636583d82f 100644
> --- a/src/amd/vulkan/radv_shader.h
> +++ b/src/amd/vulkan/radv_shader.h
> @@ -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;
> -- 
> 2.17.0
>
> _______________________________________________
> mesa-stable mailing list
> mesa-sta...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-stable
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to