spirv: Tell which opcode or value is unhandled when failing
[mesa.git] / src / compiler / spirv / vtn_variables.c
index 69dd72941baed28de9d51ccfdb8cd60195093b5d..ad6c3789573e85025d1cb873de6d33c1b010b206 100644 (file)
@@ -79,9 +79,7 @@ vtn_access_link_as_ssa(struct vtn_builder *b, struct vtn_access_link link,
       nir_ssa_def *ssa = vtn_ssa_value(b, link.id)->def;
       if (ssa->bit_size != bit_size)
          ssa = nir_i2i(&b->nb, ssa, bit_size);
-      if (stride != 1)
-         ssa = nir_imul_imm(&b->nb, ssa, stride);
-      return ssa;
+      return nir_imul_imm(&b->nb, ssa, stride);
    }
 }
 
@@ -116,7 +114,7 @@ vtn_variable_resource_index(struct vtn_builder *b, struct vtn_variable *var,
                             nir_ssa_def *desc_array_index)
 {
    if (!desc_array_index) {
-      vtn_assert(glsl_type_is_struct(var->type->type));
+      vtn_assert(glsl_type_is_struct_or_ifc(var->type->type));
       desc_array_index = nir_imm_int(&b->nb, 0);
    }
 
@@ -315,7 +313,7 @@ vtn_nir_deref_pointer_dereference(struct vtn_builder *b,
    }
 
    for (; idx < deref_chain->length; idx++) {
-      if (glsl_type_is_struct(type->type)) {
+      if (glsl_type_is_struct_or_ifc(type->type)) {
          vtn_assert(deref_chain->link[idx].mode == vtn_access_mode_literal);
          unsigned field = deref_chain->link[idx].id;
          tail = nir_build_deref_struct(&b->nb, tail, field);
@@ -492,6 +490,7 @@ vtn_ssa_offset_pointer_dereference(struct vtn_builder *b,
          break;
       }
 
+      case GLSL_TYPE_INTERFACE:
       case GLSL_TYPE_STRUCT: {
          vtn_assert(deref_chain->link[idx].mode == vtn_access_mode_literal);
          unsigned member = deref_chain->link[idx].id;
@@ -591,28 +590,29 @@ vtn_pointer_to_deref(struct vtn_builder *b, struct vtn_pointer *ptr)
 
 static void
 _vtn_local_load_store(struct vtn_builder *b, bool load, nir_deref_instr *deref,
-                      struct vtn_ssa_value *inout)
+                      struct vtn_ssa_value *inout,
+                      enum gl_access_qualifier access)
 {
    if (glsl_type_is_vector_or_scalar(deref->type)) {
       if (load) {
-         inout->def = nir_load_deref(&b->nb, deref);
+         inout->def = nir_load_deref_with_access(&b->nb, deref, access);
       } else {
-         nir_store_deref(&b->nb, deref, inout->def, ~0);
+         nir_store_deref_with_access(&b->nb, deref, inout->def, ~0, access);
       }
    } else if (glsl_type_is_array(deref->type) ||
               glsl_type_is_matrix(deref->type)) {
       unsigned elems = glsl_get_length(deref->type);
       for (unsigned i = 0; i < elems; i++) {
          nir_deref_instr *child =
-            nir_build_deref_array(&b->nb, deref, nir_imm_int(&b->nb, i));
-         _vtn_local_load_store(b, load, child, inout->elems[i]);
+            nir_build_deref_array_imm(&b->nb, deref, i);
+         _vtn_local_load_store(b, load, child, inout->elems[i], access);
       }
    } else {
-      vtn_assert(glsl_type_is_struct(deref->type));
+      vtn_assert(glsl_type_is_struct_or_ifc(deref->type));
       unsigned elems = glsl_get_length(deref->type);
       for (unsigned i = 0; i < elems; i++) {
          nir_deref_instr *child = nir_build_deref_struct(&b->nb, deref, i);
-         _vtn_local_load_store(b, load, child, inout->elems[i]);
+         _vtn_local_load_store(b, load, child, inout->elems[i], access);
       }
    }
 }
@@ -645,11 +645,12 @@ get_deref_tail(nir_deref_instr *deref)
 }
 
 struct vtn_ssa_value *
-vtn_local_load(struct vtn_builder *b, nir_deref_instr *src)
+vtn_local_load(struct vtn_builder *b, nir_deref_instr *src,
+               enum gl_access_qualifier access)
 {
    nir_deref_instr *src_tail = get_deref_tail(src);
    struct vtn_ssa_value *val = vtn_create_ssa_value(b, src_tail->type);
-   _vtn_local_load_store(b, true, src_tail, val);
+   _vtn_local_load_store(b, true, src_tail, val, access);
 
    if (src_tail != src) {
       val->type = src->type;
@@ -665,13 +666,13 @@ vtn_local_load(struct vtn_builder *b, nir_deref_instr *src)
 
 void
 vtn_local_store(struct vtn_builder *b, struct vtn_ssa_value *src,
-                nir_deref_instr *dest)
+                nir_deref_instr *dest, enum gl_access_qualifier access)
 {
    nir_deref_instr *dest_tail = get_deref_tail(dest);
 
    if (dest_tail != dest) {
       struct vtn_ssa_value *val = vtn_create_ssa_value(b, dest_tail->type);
-      _vtn_local_load_store(b, true, dest_tail, val);
+      _vtn_local_load_store(b, true, dest_tail, val, access);
 
       if (nir_src_is_const(dest->arr.index))
          val->def = vtn_vector_insert(b, val->def, src->def,
@@ -679,9 +680,9 @@ vtn_local_store(struct vtn_builder *b, struct vtn_ssa_value *src,
       else
          val->def = vtn_vector_insert_dynamic(b, val->def, src->def,
                                               dest->arr.index.ssa);
-      _vtn_local_load_store(b, false, dest_tail, val);
+      _vtn_local_load_store(b, false, dest_tail, val, access);
    } else {
-      _vtn_local_load_store(b, false, dest_tail, src);
+      _vtn_local_load_store(b, false, dest_tail, src, access);
    }
 }
 
@@ -782,7 +783,8 @@ _vtn_load_store_tail(struct vtn_builder *b, nir_intrinsic_op op, bool load,
       nir_intrinsic_set_range(instr, access_size);
    }
 
-   if (op == nir_intrinsic_load_ssbo ||
+   if (op == nir_intrinsic_load_ubo ||
+       op == nir_intrinsic_load_ssbo ||
        op == nir_intrinsic_store_ssbo) {
       nir_intrinsic_set_access(instr, access);
    }
@@ -936,6 +938,7 @@ _vtn_block_load_store(struct vtn_builder *b, nir_intrinsic_op op, bool load,
       return;
    }
 
+   case GLSL_TYPE_INTERFACE:
    case GLSL_TYPE_STRUCT: {
       unsigned elems = glsl_get_length(type->type);
       for (unsigned i = 0; i < elems; i++) {
@@ -1014,6 +1017,7 @@ vtn_block_store(struct vtn_builder *b, struct vtn_ssa_value *src,
 static void
 _vtn_variable_load_store(struct vtn_builder *b, bool load,
                          struct vtn_pointer *ptr,
+                         enum gl_access_qualifier access,
                          struct vtn_ssa_value **inout)
 {
    enum glsl_base_type base_type = glsl_get_base_type(ptr->type->type);
@@ -1045,21 +1049,24 @@ _vtn_variable_load_store(struct vtn_builder *b, bool load,
              */
             if (load) {
                *inout = vtn_create_ssa_value(b, ptr->type->type);
-               (*inout)->def = nir_load_deref(&b->nb, deref);
+               (*inout)->def = nir_load_deref_with_access(&b->nb, deref,
+                                                          ptr->type->access | access);
             } else {
-               nir_store_deref(&b->nb, deref, (*inout)->def, ~0);
+               nir_store_deref_with_access(&b->nb, deref, (*inout)->def, ~0,
+                                           ptr->type->access | access);
             }
          } else {
             if (load) {
-               *inout = vtn_local_load(b, deref);
+               *inout = vtn_local_load(b, deref, ptr->type->access | access);
             } else {
-               vtn_local_store(b, *inout, deref);
+               vtn_local_store(b, *inout, deref, ptr->type->access | access);
             }
          }
          return;
       }
       /* Fall through */
 
+   case GLSL_TYPE_INTERFACE:
    case GLSL_TYPE_ARRAY:
    case GLSL_TYPE_STRUCT: {
       unsigned elems = glsl_get_length(ptr->type->type);
@@ -1079,7 +1086,8 @@ _vtn_variable_load_store(struct vtn_builder *b, bool load,
       for (unsigned i = 0; i < elems; i++) {
          chain.link[0].id = i;
          struct vtn_pointer *elem = vtn_pointer_dereference(b, ptr, &chain);
-         _vtn_variable_load_store(b, load, elem, &(*inout)->elems[i]);
+         _vtn_variable_load_store(b, load, elem, ptr->type->access | access,
+                                  &(*inout)->elems[i]);
       }
       return;
    }
@@ -1096,7 +1104,7 @@ vtn_variable_load(struct vtn_builder *b, struct vtn_pointer *src)
       return vtn_block_load(b, src);
    } else {
       struct vtn_ssa_value *val = NULL;
-      _vtn_variable_load_store(b, true, src, &val);
+      _vtn_variable_load_store(b, true, src, src->access, &val);
       return val;
    }
 }
@@ -1110,7 +1118,7 @@ vtn_variable_store(struct vtn_builder *b, struct vtn_ssa_value *src,
                  dest->mode == vtn_variable_mode_workgroup);
       vtn_block_store(b, src, dest);
    } else {
-      _vtn_variable_load_store(b, false, dest, &src);
+      _vtn_variable_load_store(b, false, dest, dest->access, &src);
    }
 }
 
@@ -1142,6 +1150,7 @@ _vtn_variable_copy(struct vtn_builder *b, struct vtn_pointer *dest,
       vtn_variable_store(b, vtn_variable_load(b, src), dest);
       return;
 
+   case GLSL_TYPE_INTERFACE:
    case GLSL_TYPE_ARRAY:
    case GLSL_TYPE_STRUCT: {
       struct vtn_access_chain chain = {
@@ -1337,6 +1346,10 @@ vtn_get_builtin_location(struct vtn_builder *b,
       *location = SYSTEM_VALUE_GLOBAL_INVOCATION_ID;
       set_mode_system_value(b, mode);
       break;
+   case SpvBuiltInGlobalLinearId:
+      *location = SYSTEM_VALUE_GLOBAL_INVOCATION_INDEX;
+      set_mode_system_value(b, mode);
+      break;
    case SpvBuiltInBaseVertex:
       /* OpenGL gl_BaseVertex (SYSTEM_VALUE_BASE_VERTEX) is not the same
        * semantic as SPIR-V BaseVertex (SYSTEM_VALUE_FIRST_VERTEX).
@@ -1409,7 +1422,8 @@ vtn_get_builtin_location(struct vtn_builder *b,
       set_mode_system_value(b, mode);
       break;
    default:
-      vtn_fail("unsupported builtin: %u", builtin);
+      vtn_fail("Unsupported builtin: %s (%u)",
+               spirv_builtin_to_string(builtin), builtin);
    }
 }
 
@@ -1551,7 +1565,7 @@ apply_var_decoration(struct vtn_builder *b,
       break;
 
    default:
-      vtn_fail("Unhandled decoration");
+      vtn_fail_with_decoration("Unhandled decoration", dec->decoration);
    }
 }
 
@@ -1682,6 +1696,22 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
    }
 }
 
+static void
+ptr_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
+                  const struct vtn_decoration *dec, void *void_ptr)
+{
+   struct vtn_pointer *ptr = void_ptr;
+
+   switch (dec->decoration) {
+   case SpvDecorationNonUniformEXT:
+      ptr->access |= ACCESS_NON_UNIFORM;
+      break;
+
+   default:
+      break;
+   }
+}
+
 static enum vtn_variable_mode
 vtn_storage_class_to_mode(struct vtn_builder *b,
                           SpvStorageClass class,
@@ -1750,7 +1780,8 @@ vtn_storage_class_to_mode(struct vtn_builder *b,
       break;
    case SpvStorageClassGeneric:
    default:
-      vtn_fail("Unhandled variable storage class");
+      vtn_fail("Unhandled variable storage class: %s (%u)",
+               spirv_storageclass_to_string(class), class);
    }
 
    if (nir_mode_out)
@@ -1870,9 +1901,8 @@ vtn_pointer_from_ssa(struct vtn_builder *b, nir_ssa_def *ssa,
    } else {
       const struct glsl_type *deref_type = ptr_type->deref->type;
       if (!vtn_pointer_is_external_block(b, ptr)) {
-         assert(ssa->bit_size == 32 && ssa->num_components == 1);
          ptr->deref = nir_build_deref_cast(&b->nb, ssa, nir_mode,
-                                           glsl_get_bare_type(deref_type), 0);
+                                           deref_type, 0);
       } else if (vtn_type_contains_block(b, ptr->type) &&
                  ptr->mode != vtn_variable_mode_phys_ssbo) {
          /* This is a pointer to somewhere in an array of blocks, not a
@@ -2053,7 +2083,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
          /* Private variables don't have any explicit layout but some layouts
           * may have leaked through due to type deduplication in the SPIR-V.
           */
-         var->var->type = glsl_get_bare_type(var->type->type);
+         var->var->type = var->type->type;
       }
       var->var->data.mode = nir_mode;
       var->var->data.location = -1;
@@ -2071,7 +2101,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
           * layouts may have leaked through due to type deduplication in the
           * SPIR-V.
           */
-         var->var->type = glsl_get_bare_type(var->type->type);
+         var->var->type = var->type->type;
          var->var->data.mode = nir_var_mem_shared;
       }
       break;
@@ -2097,7 +2127,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
       var->patch = false;
       vtn_foreach_decoration(b, val, var_is_patch_cb, &var->patch);
       if (glsl_type_is_array(var->type->type) &&
-          glsl_type_is_struct(without_array->type)) {
+          glsl_type_is_struct_or_ifc(without_array->type)) {
          vtn_foreach_decoration(b, vtn_value(b, without_array->id,
                                              vtn_value_type_type),
                                 var_is_patch_cb, &var->patch);
@@ -2129,7 +2159,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
        * the SPIR-V.  We do, however, keep the layouts in the variable's
        * interface_type because we need offsets for XFB arrays of blocks.
        */
-      var->var->type = glsl_get_bare_type(var->type->type);
+      var->var->type = var->type->type;
       var->var->data.mode = nir_mode;
       var->var->data.patch = var->patch;
 
@@ -2189,6 +2219,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
    }
 
    vtn_foreach_decoration(b, val, var_decoration_cb, var);
+   vtn_foreach_decoration(b, val, ptr_decoration_cb, val->pointer);
 
    if ((var->mode == vtn_variable_mode_input ||
         var->mode == vtn_variable_mode_output) &&
@@ -2315,30 +2346,32 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
 
    case SpvOpAccessChain:
    case SpvOpPtrAccessChain:
-   case SpvOpInBoundsAccessChain: {
+   case SpvOpInBoundsAccessChain:
+   case SpvOpInBoundsPtrAccessChain: {
       struct vtn_access_chain *chain = vtn_access_chain_create(b, count - 4);
-      chain->ptr_as_array = (opcode == SpvOpPtrAccessChain);
+      chain->ptr_as_array = (opcode == SpvOpPtrAccessChain || opcode == SpvOpInBoundsPtrAccessChain);
 
       unsigned idx = 0;
       for (int i = 4; i < count; i++) {
          struct vtn_value *link_val = vtn_untyped_value(b, w[i]);
          if (link_val->value_type == vtn_value_type_constant) {
             chain->link[idx].mode = vtn_access_mode_literal;
-            switch (glsl_get_bit_size(link_val->type->type)) {
+            const unsigned bit_size = glsl_get_bit_size(link_val->type->type);
+            switch (bit_size) {
             case 8:
-               chain->link[idx].id = link_val->constant->values[0].i8[0];
+               chain->link[idx].id = link_val->constant->values[0][0].i8;
                break;
             case 16:
-               chain->link[idx].id = link_val->constant->values[0].i16[0];
+               chain->link[idx].id = link_val->constant->values[0][0].i16;
                break;
             case 32:
-               chain->link[idx].id = link_val->constant->values[0].i32[0];
+               chain->link[idx].id = link_val->constant->values[0][0].i32;
                break;
             case 64:
-               chain->link[idx].id = link_val->constant->values[0].i64[0];
+               chain->link[idx].id = link_val->constant->values[0][0].i64;
                break;
             default:
-               vtn_fail("Invalid bit size");
+               vtn_fail("Invalid bit size: %u", bit_size);
             }
          } else {
             chain->link[idx].mode = vtn_access_mode_id;
@@ -2365,12 +2398,17 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
          val->sampled_image->image =
             vtn_pointer_dereference(b, base_val->sampled_image->image, chain);
          val->sampled_image->sampler = base_val->sampled_image->sampler;
+         vtn_foreach_decoration(b, val, ptr_decoration_cb,
+                                val->sampled_image->image);
+         vtn_foreach_decoration(b, val, ptr_decoration_cb,
+                                val->sampled_image->sampler);
       } else {
          vtn_assert(base_val->value_type == vtn_value_type_pointer);
          struct vtn_value *val =
             vtn_push_value(b, w[2], vtn_value_type_pointer);
          val->pointer = vtn_pointer_dereference(b, base_val->pointer, chain);
          val->pointer->ptr_type = ptr_type;
+         vtn_foreach_decoration(b, val, ptr_decoration_cb, val->pointer);
       }
       break;
    }
@@ -2535,6 +2573,6 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
 
    case SpvOpCopyMemorySized:
    default:
-      vtn_fail("Unhandled opcode");
+      vtn_fail_with_opcode("Unhandled opcode", opcode);
    }
 }