nir/spirv: Handle location decorations on structure members
authorJason Ekstrand <jason.ekstrand@intel.com>
Tue, 24 May 2016 21:17:16 +0000 (14:17 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Wed, 25 May 2016 04:12:56 +0000 (21:12 -0700)
src/compiler/spirv/vtn_variables.c

index d156fb468c82bf4e94dfc2313b93fa59dbf74a3d..8abd8ee9a0fd4fd4b813ba0404e2ea591ee01dd2 100644 (file)
@@ -901,8 +901,27 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
    case SpvDecorationDescriptorSet:
       vtn_var->descriptor_set = dec->literals[0];
       return;
+   default:
+      break;
+   }
 
-   case SpvDecorationLocation: {
+   /* Now we handle decorations that apply to a particular nir_variable */
+   nir_variable *nir_var = vtn_var->var;
+   if (val->value_type == vtn_value_type_access_chain) {
+      assert(val->access_chain->length == 0);
+      assert(val->access_chain->var == void_var);
+      assert(member == -1);
+   } else {
+      assert(val->value_type == vtn_value_type_type);
+      if (member != -1)
+         nir_var = vtn_var->members[member];
+   }
+
+   /* Location is odd in that it can apply in three different cases: To a
+    * non-split variable, to a whole split variable, or to one structure
+    * member of a split variable.
+    */
+   if (dec->decoration == SpvDecorationLocation) {
       unsigned location = dec->literals[0];
       bool is_vertex_input;
       if (b->shader->stage == MESA_SHADER_FRAGMENT &&
@@ -921,10 +940,12 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
          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;
+      if (nir_var) {
+         /* This handles the member and lone variable cases */
+         nir_var->data.location = location;
+         nir_var->data.explicit_location = true;
       } else {
+         /* This handles the structure member case */
          assert(vtn_var->members);
          unsigned length =
             glsl_get_length(glsl_without_array(vtn_var->type->type));
@@ -939,22 +960,6 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
       return;
    }
 
-   default:
-      break;
-   }
-
-   /* Now we handle decorations that apply to a particular nir_variable */
-   nir_variable *nir_var = vtn_var->var;
-   if (val->value_type == vtn_value_type_access_chain) {
-      assert(val->access_chain->length == 0);
-      assert(val->access_chain->var == void_var);
-      assert(member == -1);
-   } else {
-      assert(val->value_type == vtn_value_type_type);
-      if (member != -1)
-         nir_var = vtn_var->members[member];
-   }
-
    if (nir_var == NULL)
       return;
 
@@ -1037,6 +1042,9 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
    case SpvDecorationPatch:
       unreachable("Tessellation not yet supported");
 
+   case SpvDecorationLocation:
+      unreachable("Handled above");
+
    case SpvDecorationBlock:
    case SpvDecorationBufferBlock:
    case SpvDecorationArrayStride: