From 531a26d5aa03d8f4499f901f040132c5f712219a Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Fri, 24 Jan 2020 10:55:55 +0100 Subject: [PATCH] spirv: implement SPV_AMD_shader_explicit_vertex_parameter Signed-off-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen Part-of: --- src/compiler/shader_info.h | 1 + src/compiler/spirv/spirv_to_nir.c | 3 ++ src/compiler/spirv/vtn_amd.c | 64 +++++++++++++++++++++++++++++++ src/compiler/spirv/vtn_private.h | 5 +++ 4 files changed, 73 insertions(+) diff --git a/src/compiler/shader_info.h b/src/compiler/shader_info.h index 4aa138943a7..d13e51a47a6 100644 --- a/src/compiler/shader_info.h +++ b/src/compiler/shader_info.h @@ -84,6 +84,7 @@ struct spirv_supported_capabilities { bool amd_shader_ballot; bool amd_trinary_minmax; bool amd_image_read_write_lod; + bool amd_shader_explicit_vertex_parameter; }; typedef struct shader_info { diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 258e33b723b..411212c6b8f 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -398,6 +398,9 @@ vtn_handle_extension(struct vtn_builder *b, SpvOp opcode, } else if ((strcmp(ext, "SPV_AMD_shader_trinary_minmax") == 0) && (b->options && b->options->caps.amd_trinary_minmax)) { val->ext_handler = vtn_handle_amd_shader_trinary_minmax_instruction; + } else if ((strcmp(ext, "SPV_AMD_shader_explicit_vertex_parameter") == 0) + && (b->options && b->options->caps.amd_shader_explicit_vertex_parameter)) { + val->ext_handler = vtn_handle_amd_shader_explicit_vertex_parameter_instruction; } else if (strcmp(ext, "OpenCL.std") == 0) { val->ext_handler = vtn_handle_opencl_instruction; } else if (strstr(ext, "NonSemantic.") == ext) { diff --git a/src/compiler/spirv/vtn_amd.c b/src/compiler/spirv/vtn_amd.c index efdcfdb514c..55f87c2f98e 100644 --- a/src/compiler/spirv/vtn_amd.c +++ b/src/compiler/spirv/vtn_amd.c @@ -168,3 +168,67 @@ vtn_handle_amd_shader_trinary_minmax_instruction(struct vtn_builder *b, SpvOp ex return true; } + +bool +vtn_handle_amd_shader_explicit_vertex_parameter_instruction(struct vtn_builder *b, SpvOp ext_opcode, + const uint32_t *w, unsigned count) +{ + const struct glsl_type *dest_type = + vtn_value(b, w[1], vtn_value_type_type)->type->type; + + struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa); + val->ssa = vtn_create_ssa_value(b, dest_type); + + nir_intrinsic_op op; + switch ((enum ShaderExplicitVertexParameterAMD)ext_opcode) { + case InterpolateAtVertexAMD: + op = nir_intrinsic_interp_deref_at_vertex; + break; + default: + unreachable("unknown opcode"); + } + + nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->nb.shader, op); + + struct vtn_pointer *ptr = + vtn_value(b, w[5], vtn_value_type_pointer)->pointer; + nir_deref_instr *deref = vtn_pointer_to_deref(b, ptr); + + /* If the value we are interpolating has an index into a vector then + * interpolate the vector and index the result of that instead. This is + * necessary because the index will get generated as a series of nir_bcsel + * instructions so it would no longer be an input variable. + */ + const bool vec_array_deref = deref->deref_type == nir_deref_type_array && + glsl_type_is_vector(nir_deref_instr_parent(deref)->type); + + nir_deref_instr *vec_deref = NULL; + if (vec_array_deref) { + vec_deref = deref; + deref = nir_deref_instr_parent(deref); + } + intrin->src[0] = nir_src_for_ssa(&deref->dest.ssa); + intrin->src[1] = nir_src_for_ssa(vtn_ssa_value(b, w[6])->def); + + intrin->num_components = glsl_get_vector_elements(deref->type); + nir_ssa_dest_init(&intrin->instr, &intrin->dest, + glsl_get_vector_elements(deref->type), + glsl_get_bit_size(deref->type), NULL); + + nir_builder_instr_insert(&b->nb, &intrin->instr); + + if (vec_array_deref) { + assert(vec_deref); + if (nir_src_is_const(vec_deref->arr.index)) { + val->ssa->def = vtn_vector_extract(b, &intrin->dest.ssa, + nir_src_as_uint(vec_deref->arr.index)); + } else { + val->ssa->def = vtn_vector_extract_dynamic(b, &intrin->dest.ssa, + vec_deref->arr.index.ssa); + } + } else { + val->ssa->def = &intrin->dest.ssa; + } + + return true; +} diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index 92daf1352bd..4b2d28978d9 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -891,6 +891,11 @@ bool vtn_handle_amd_shader_ballot_instruction(struct vtn_builder *b, SpvOp ext_o bool vtn_handle_amd_shader_trinary_minmax_instruction(struct vtn_builder *b, SpvOp ext_opcode, const uint32_t *words, unsigned count); +bool vtn_handle_amd_shader_explicit_vertex_parameter_instruction(struct vtn_builder *b, + SpvOp ext_opcode, + const uint32_t *words, + unsigned count); + SpvMemorySemanticsMask vtn_storage_class_to_memory_semantics(SpvStorageClass sc); void vtn_emit_memory_barrier(struct vtn_builder *b, SpvScope scope, -- 2.30.2