nir/spirv: Properly assign locations to split structures
authorJason Ekstrand <jason.ekstrand@intel.com>
Thu, 21 Jan 2016 20:41:45 +0000 (12:41 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Fri, 22 Jan 2016 00:20:39 +0000 (16:20 -0800)
src/glsl/nir/spirv/spirv_to_nir.c
src/glsl/nir/spirv/vtn_private.h
src/glsl/nir/spirv/vtn_variables.c

index 7d9d0981269419479e938863f6c692ca361a3a31..32188e5f364378ecfae80b7f33cb44ea2158a1b0 100644 (file)
@@ -585,6 +585,7 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
 
    val->type = rzalloc(b, struct vtn_type);
    val->type->is_builtin = false;
+   val->type->val = val;
 
    switch (opcode) {
    case SpvOpTypeVoid:
index e0f4b220c4ce10a04522a152f8c8cd0d8f62cb2e..3840d8c4b650f59d81b324666d3f2e355c8aa7fe 100644 (file)
@@ -196,6 +196,9 @@ struct vtn_ssa_value {
 struct vtn_type {
    const struct glsl_type *type;
 
+   /* The value that declares this type.  Used for finding decorations */
+   struct vtn_value *val;
+
    /* for matrices, whether the matrix is stored row-major */
    bool row_major;
 
index 8171a5fc1563d5cffaf7db8946793cdbc6116812..5c37277412602edacba24945c9742d9d3c8c3cec 100644 (file)
@@ -887,6 +887,43 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
    case SpvDecorationDescriptorSet:
       vtn_var->descriptor_set = dec->literals[0];
       return;
+
+   case SpvDecorationLocation: {
+      unsigned location = dec->literals[0];
+      bool is_vertex_input;
+      if (b->shader->stage == MESA_SHADER_FRAGMENT &&
+          vtn_var->mode == vtn_variable_mode_output) {
+         is_vertex_input = false;
+         location += FRAG_RESULT_DATA0;
+      } else if (b->shader->stage == MESA_SHADER_VERTEX &&
+                 vtn_var->mode == vtn_variable_mode_input) {
+         is_vertex_input = true;
+         location += VERT_ATTRIB_GENERIC0;
+      } else if (vtn_var->mode == vtn_variable_mode_input ||
+                 vtn_var->mode == vtn_variable_mode_output) {
+         is_vertex_input = false;
+         location += VARYING_SLOT_VAR0;
+      } else {
+         assert(!"Location must be on input or output variable");
+      }
+
+      if (vtn_var->var) {
+         vtn_var->var->data.location = location;
+         vtn_var->var->data.explicit_location = true;
+      } else {
+         assert(vtn_var->members);
+         unsigned length = glsl_get_length(vtn_var->type->type);
+         for (unsigned i = 0; i < length; i++) {
+            vtn_var->members[i]->data.location = location;
+            vtn_var->members[i]->data.explicit_location = true;
+            location +=
+               glsl_count_attribute_slots(vtn_var->members[i]->interface_type,
+                                          is_vertex_input);
+         }
+      }
+      return;
+   }
+
    default:
       break;
    }
@@ -899,7 +936,6 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
       assert(member == -1);
    } else {
       assert(val->value_type == vtn_value_type_type);
-      assert(vtn_var->type == val->type);
       if (member != -1)
          nir_var = vtn_var->members[member];
    }
@@ -932,22 +968,6 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
    case SpvDecorationNonWritable:
       nir_var->data.read_only = true;
       break;
-   case SpvDecorationLocation:
-      nir_var->data.location = dec->literals[0];
-      if (b->shader->stage == MESA_SHADER_FRAGMENT &&
-          nir_var->data.mode == nir_var_shader_out) {
-         nir_var->data.location += FRAG_RESULT_DATA0;
-      } else if (b->shader->stage == MESA_SHADER_VERTEX &&
-                 nir_var->data.mode == nir_var_shader_in) {
-         nir_var->data.location += VERT_ATTRIB_GENERIC0;
-      } else if (nir_var->data.mode == nir_var_shader_in ||
-                 nir_var->data.mode == nir_var_shader_out) {
-         nir_var->data.location += VARYING_SLOT_VAR0;
-      } else {
-         assert(!"Location must be on input or output variable");
-      }
-      nir_var->data.explicit_location = true;
-      break;
    case SpvDecorationComponent:
       nir_var->data.location_frac = dec->literals[0];
       break;
@@ -1201,7 +1221,13 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
             var->var->interface_type = interface_type->type;
             var->var->data.mode = nir_mode;
          }
+
+         /* For inputs and outputs, we need to grab locations and builtin
+          * information from the interface type.
+          */
+         vtn_foreach_decoration(b, interface_type->val, var_decoration_cb, var);
          break;
+
       case vtn_variable_mode_param:
          unreachable("Not created through OpVariable");
       }