<div dir="ltr">Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Jul 9, 2018 at 5:21 AM Alejandro Piñeiro <<a href="mailto:apinheiro@igalia.com">apinheiro@igalia.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Neil Roberts <<a href="mailto:nroberts@igalia.com" target="_blank">nroberts@igalia.com</a>><br>
<br>
If the glsl is something like this:<br>
<br>
  in vec4 some_input;<br>
  interpolateAtCentroid(some_input[idx])<br>
<br>
then it now gets generated as if it were:<br>
<br>
  interpolateAtCentroid(some_input)[idx]<br>
<br>
This is necessary because the index will get generated as a series of<br>
nir_bcsel instructions so it would no longer be an input variable. It<br>
is similar to what is done for GLSL in ca63a5ed3e9efb2bd645b42.<br>
<br>
Although I can’t find anything explicit in the Vulkan specs to say<br>
this should be allowed, the SPIR-V spec just says “the operand<br>
interpolant must be a pointer to the Input Storage Class”, which I<br>
guess doesn’t rule out any type of pointer to an input.<br>
<br>
This was found using the spec/glsl-4.40/execution/fs-interpolateAt*<br>
Piglit tests with the ARB_gl_spirv branch.<br>
<br>
Signed-off-by: Neil Roberts <<a href="mailto:nroberts@igalia.com" target="_blank">nroberts@igalia.com</a>><br>
Signed-off-by: Alejandro Piñeiro <<a href="mailto:apinheiro@igalia.com" target="_blank">apinheiro@igalia.com</a>><br>
<br>
v2: update after nir_deref_instr land on master. Implemented by<br>
    Alejandro Piñeiro. Special thanks to Jason Ekstrand for guidance<br>
    at the new nir_deref_instr world.<br>
---<br>
<br>
Although this was initially detected while testing the ARB_gl_spirv<br>
ongoing implementation, as v1, this can be tested on Vulkan using<br>
vkrunner:<br>
<br>
git clone <a href="https://github.com/Igalia/vkrunner.git" rel="noreferrer" target="_blank">https://github.com/Igalia/vkrunner.git</a> -b tests<br>
cd vkrunner && ./autogen.sh && make<br>
./src/vkrunner examples/interpolation/*.shader_test<br>
<br>
 src/compiler/spirv/vtn_glsl450.c | 38 +++++++++++++++++++++++++++++++++-----<br>
 1 file changed, 33 insertions(+), 5 deletions(-)<br>
<br>
diff --git a/src/compiler/spirv/vtn_glsl450.c b/src/compiler/spirv/vtn_glsl450.c<br>
index 7f941ceeb0d..8393450f2f4 100644<br>
--- a/src/compiler/spirv/vtn_glsl450.c<br>
+++ b/src/compiler/spirv/vtn_glsl450.c<br>
@@ -802,7 +802,22 @@ handle_glsl450_interpolation(struct vtn_builder *b, enum GLSLstd450 opcode,<br>
<br>
    struct vtn_pointer *ptr =<br>
       vtn_value(b, w[5], vtn_value_type_pointer)->pointer;<br>
-   intrin->src[0] = nir_src_for_ssa(&vtn_pointer_to_deref(b, ptr)->dest.ssa);<br>
+   nir_deref_instr *deref = vtn_pointer_to_deref(b, ptr);<br>
+<br>
+   /* If the value we are interpolating has an index into a vector then<br>
+    * interpolate the vector and index the result of that instead. This is<br>
+    * necessary because the index will get generated as a series of nir_bcsel<br>
+    * instructions so it would no longer be an input variable.<br>
+    */<br>
+   const bool vec_array_deref = deref->deref_type == nir_deref_type_array &&<br>
+      glsl_type_is_vector(nir_deref_instr_parent(deref)->type);<br>
+<br>
+   nir_deref_instr *vec_deref = NULL;<br>
+   if (vec_array_deref) {<br>
+      vec_deref = deref;<br>
+      deref = nir_deref_instr_parent(deref);<br>
+   }<br>
+   intrin->src[0] = nir_src_for_ssa(&deref->dest.ssa);<br>
<br>
    switch (opcode) {<br>
    case GLSLstd450InterpolateAtCentroid:<br>
@@ -815,13 +830,26 @@ handle_glsl450_interpolation(struct vtn_builder *b, enum GLSLstd450 opcode,<br>
       vtn_fail("Invalid opcode");<br>
    }<br>
<br>
-   intrin->num_components = glsl_get_vector_elements(dest_type);<br>
+   intrin->num_components = glsl_get_vector_elements(deref->type);<br>
    nir_ssa_dest_init(&intrin->instr, &intrin->dest,<br>
-                     glsl_get_vector_elements(dest_type),<br>
-                     glsl_get_bit_size(dest_type), NULL);<br>
-   val->ssa->def = &intrin->dest.ssa;<br>
+                     glsl_get_vector_elements(deref->type),<br>
+                     glsl_get_bit_size(deref->type), NULL);<br>
<br>
    nir_builder_instr_insert(&b->nb, &intrin->instr);<br>
+<br>
+   if (vec_array_deref) {<br>
+      assert(vec_deref);<br>
+      nir_const_value *const_index = nir_src_as_const_value(vec_deref->arr.index);<br>
+      if (const_index) {<br>
+         val->ssa->def = vtn_vector_extract(b, &intrin->dest.ssa,<br>
+                                            const_index->u32[0]);<br>
+      } else {<br>
+         val->ssa->def = vtn_vector_extract_dynamic(b, &intrin->dest.ssa,<br>
+                                                    vec_deref->arr.index.ssa);<br>
+      }<br>
+   } else {<br>
+      val->ssa->def = &intrin->dest.ssa;<br>
+   }<br>
 }<br>
<br>
 bool<br>
-- <br>
2.14.1<br>
<br>
</blockquote></div>