spirv: Add a helper for getting the NIR type of a vtn_type
authorJason Ekstrand <jason@jlekstrand.net>
Fri, 29 May 2020 22:57:34 +0000 (17:57 -0500)
committerJason Ekstrand <jason@jlekstrand.net>
Fri, 24 Jul 2020 03:43:21 +0000 (22:43 -0500)
There are a few cases, atomic counters being one example, where the type
used by vtn_ssa_value is not the same as the type we want NIR to use in
derefs and variables.  To solve this, we add a helper which converts
between the types for us.  In the next commit, we'll be adding another
major user of this: images and samplers.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5278>

src/compiler/spirv/spirv_to_nir.c
src/compiler/spirv/vtn_private.h
src/compiler/spirv/vtn_variables.c

index 7f595c2be367879299b0060653f2c463d051ba1b..a35dbfc0a7ad3f8f9fc886db72bf4de6f0397227 100644 (file)
@@ -702,6 +702,33 @@ vtn_type_copy(struct vtn_builder *b, struct vtn_type *src)
    return dest;
 }
 
+static const struct glsl_type *
+wrap_type_in_array(const struct glsl_type *type,
+                   const struct glsl_type *array_type)
+{
+   if (!glsl_type_is_array(array_type))
+      return type;
+
+   const struct glsl_type *elem_type =
+      wrap_type_in_array(type, glsl_get_array_element(array_type));
+   return glsl_array_type(elem_type, glsl_get_length(array_type),
+                          glsl_get_explicit_stride(array_type));
+}
+
+const struct glsl_type *
+vtn_type_get_nir_type(struct vtn_builder *b, struct vtn_type *type,
+                      enum vtn_variable_mode mode)
+{
+   if (mode == vtn_variable_mode_atomic_counter) {
+      vtn_fail_if(glsl_without_array(type->type) != glsl_uint_type(),
+                  "Variables in the AtomicCounter storage class should be "
+                  "(possibly arrays of arrays of) uint.");
+      return wrap_type_in_array(glsl_atomic_uint_type(), type->type);
+   }
+
+   return type->type;
+}
+
 static struct vtn_type *
 mutable_matrix_member(struct vtn_builder *b, struct vtn_type *type, int member)
 {
index 3ff28a7d1c9e42e3448db0d5bb3b2f96f50d4aa4..b4e75617bfa48882c7bb7be5de872665387c3339 100644 (file)
@@ -562,6 +562,10 @@ struct vtn_variable {
    enum gl_access_qualifier access;
 };
 
+const struct glsl_type *
+vtn_type_get_nir_type(struct vtn_builder *b, struct vtn_type *type,
+                      enum vtn_variable_mode mode);
+
 struct vtn_image_pointer {
    struct vtn_pointer *image;
    nir_ssa_def *coord;
index 05535bce83fb087f61276e127d12ef1d38442e36..a16765eaa86458d4a16d3c6a117635568e67179a 100644 (file)
@@ -361,7 +361,8 @@ vtn_nir_deref_pointer_dereference(struct vtn_builder *b,
       nir_variable_mode nir_mode =
          base->mode == vtn_variable_mode_ssbo ? nir_var_mem_ssbo : nir_var_mem_ubo;
 
-      tail = nir_build_deref_cast(&b->nb, desc, nir_mode, type->type,
+      tail = nir_build_deref_cast(&b->nb, desc, nir_mode,
+                                  vtn_type_get_nir_type(b, type, base->mode),
                                   base->ptr_type->stride);
    } else {
       assert(base->var && base->var->var);
@@ -602,29 +603,6 @@ vtn_pointer_dereference(struct vtn_builder *b,
    }
 }
 
-/* Returns an atomic_uint type based on the original uint type. The returned
- * type will be equivalent to the original one but will have an atomic_uint
- * type as leaf instead of an uint.
- *
- * Manages uint scalars, arrays, and arrays of arrays of any nested depth.
- */
-static const struct glsl_type *
-repair_atomic_type(const struct glsl_type *type)
-{
-   assert(glsl_get_base_type(glsl_without_array(type)) == GLSL_TYPE_UINT);
-   assert(glsl_type_is_scalar(glsl_without_array(type)));
-
-   if (glsl_type_is_array(type)) {
-      const struct glsl_type *atomic =
-         repair_atomic_type(glsl_get_array_element(type));
-
-      return glsl_array_type(atomic, glsl_get_length(type),
-                             glsl_get_explicit_stride(type));
-   } else {
-      return glsl_atomic_uint_type();
-   }
-}
-
 nir_deref_instr *
 vtn_pointer_to_deref(struct vtn_builder *b, struct vtn_pointer *ptr)
 {
@@ -2015,7 +1993,8 @@ vtn_pointer_from_ssa(struct vtn_builder *b, nir_ssa_def *ssa,
          ptr->offset = ssa;
       }
    } else {
-      const struct glsl_type *deref_type = ptr_type->deref->type;
+      const struct glsl_type *deref_type =
+         vtn_type_get_nir_type(b, ptr_type->deref, ptr->mode);
       if (!vtn_pointer_is_external_block(b, ptr)) {
          ptr->deref = nir_build_deref_cast(&b->nb, ssa, nir_mode,
                                            deref_type, ptr_type->stride);
@@ -2040,8 +2019,7 @@ vtn_pointer_from_ssa(struct vtn_builder *b, nir_ssa_def *ssa,
           * storage class with Block can be used.
           */
          ptr->deref = nir_build_deref_cast(&b->nb, ssa, nir_mode,
-                                           ptr_type->deref->type,
-                                           ptr_type->stride);
+                                           deref_type, ptr_type->stride);
          ptr->deref->dest.ssa.num_components =
             glsl_get_vector_elements(ptr_type->type);
          ptr->deref->dest.ssa.bit_size = glsl_get_bit_size(ptr_type->type);
@@ -2195,19 +2173,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
       /* For these, we create the variable normally */
       var->var = rzalloc(b->shader, nir_variable);
       var->var->name = ralloc_strdup(var->var, val->name);
-
-      if (var->mode == vtn_variable_mode_atomic_counter) {
-         /* Need to tweak the nir type here as at vtn_handle_type we don't
-          * have the access to storage_class, that is the one that points us
-          * that is an atomic uint.
-          */
-         var->var->type = repair_atomic_type(var->type->type);
-      } else {
-         /* 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 = var->type->type;
-      }
+      var->var->type = vtn_type_get_nir_type(b, var->type, var->mode);
       var->var->data.mode = nir_mode;
       var->var->data.location = -1;
       var->var->interface_type = NULL;
@@ -2218,8 +2184,8 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
       var->var = rzalloc(b->shader, nir_variable);
       var->var->name = ralloc_strdup(var->var, val->name);
 
-      var->var->type = var->type->type;
-      var->var->interface_type = var->type->type;
+      var->var->type = vtn_type_get_nir_type(b, var->type, var->mode);
+      var->var->interface_type = var->var->type;
 
       var->var->data.mode = nir_mode;
       var->var->data.location = -1;
@@ -2234,7 +2200,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 = var->type->type;
+      var->var->type = vtn_type_get_nir_type(b, var->type, var->mode);
       var->var->data.mode = nir_var_mem_shared;
       break;
 
@@ -2291,7 +2257,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 = var->type->type;
+      var->var->type = vtn_type_get_nir_type(b, var->type, var->mode);
       var->var->data.mode = nir_mode;
       var->var->data.patch = var->patch;
 
@@ -2309,7 +2275,8 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
             iface_type = iface_type->array_element;
       }
       if (iface_type->base_type == vtn_base_type_struct && iface_type->block)
-         var->var->interface_type = iface_type->type;
+         var->var->interface_type = vtn_type_get_nir_type(b, iface_type,
+                                                          var->mode);
 
       if (per_vertex_type->base_type == vtn_base_type_struct &&
           per_vertex_type->block) {