spirv: implement SPV_AMD_shader_explicit_vertex_parameter
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Fri, 24 Jan 2020 09:55:55 +0000 (10:55 +0100)
committerMarge Bot <eric+marge@anholt.net>
Wed, 29 Jan 2020 09:49:50 +0000 (09:49 +0000)
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3578>

src/compiler/shader_info.h
src/compiler/spirv/spirv_to_nir.c
src/compiler/spirv/vtn_amd.c
src/compiler/spirv/vtn_private.h

index 4aa138943a7e63c897b7a56b78f2e4b1b364fcea..d13e51a47a6bbf6f82ce7eaeea5ccbfcb18bc887 100644 (file)
@@ -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 {
index 258e33b723b45620c33323df311b0db2048a0d26..411212c6b8f1437c34eabe87218d8050bcbff04e 100644 (file)
@@ -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) {
index efdcfdb514cf153d9ed79bfac6000bf5f9ccee1f..55f87c2f98e64859bc27c6ef5ea90f9232b89ceb 100644 (file)
@@ -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;
+}
index 92daf1352bd27bc878d55c95cb1270cd1715e8e7..4b2d28978d9267bb0b0a5b32698c8a8f36e35240 100644 (file)
@@ -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,