nir/spirv: Insert movs around image intrinsics
authorJason Ekstrand <jason.ekstrand@intel.com>
Mon, 18 Jan 2016 23:00:01 +0000 (15:00 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 19 Jan 2016 01:21:05 +0000 (17:21 -0800)
Image intrinsics always take a vec4 coordinate and always return a vec4.
This simplifies the intrinsics a but but also means that they don't
actually match the incomming SPIR-V.  In order to compensate for this, we
add swizzling movs for both source and destination to get the right number
of components.

src/glsl/nir/spirv/spirv_to_nir.c

index dc95b40f9c390fb672190775839efedfd49f382e..ef24156a48e5e6d78cbc2209ffc5a7c9b548e06b 100644 (file)
@@ -2650,7 +2650,15 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
    nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->shader, op);
    intrin->variables[0] =
       nir_deref_as_var(nir_copy_deref(&intrin->instr, &image.deref->deref));
-   intrin->src[0] = nir_src_for_ssa(image.coord);
+
+   /* The image coordinate is always 4 components but we may not have that
+    * many.  Swizzle to compensate.
+    */
+   unsigned swiz[4];
+   for (unsigned i = 0; i < 4; i++)
+      swiz[i] = i < image.coord->num_components ? i : 0;
+   intrin->src[0] = nir_src_for_ssa(nir_swizzle(&b->nb, image.coord,
+                                                swiz, 4, false));
    intrin->src[1] = nir_src_for_ssa(image.sample);
 
    switch (opcode) {
@@ -2694,13 +2702,20 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode,
    if (opcode != SpvOpImageWrite) {
       struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
       struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type;
-      nir_ssa_dest_init(&intrin->instr, &intrin->dest,
-                        glsl_get_vector_elements(type->type), NULL);
+      nir_ssa_dest_init(&intrin->instr, &intrin->dest, 4, NULL);
+
+      nir_builder_instr_insert(&b->nb, &intrin->instr);
+
+      /* The image intrinsics always return 4 channels but we may not want
+       * that many.  Emit a mov to trim it down.
+       */
+      unsigned swiz[4] = {0, 1, 2, 3};
       val->ssa = vtn_create_ssa_value(b, type->type);
-      val->ssa->def = &intrin->dest.ssa;
+      val->ssa->def = nir_swizzle(&b->nb, &intrin->dest.ssa, swiz,
+                                  glsl_get_vector_elements(type->type), false);
+   } else {
+      nir_builder_instr_insert(&b->nb, &intrin->instr);
    }
-
-   nir_builder_instr_insert(&b->nb, &intrin->instr);
 }
 
 static void