glsl_type: Add support for explicitly laid out matrices and arrays
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 12 Dec 2018 20:32:19 +0000 (14:32 -0600)
committerJason Ekstrand <jason@jlekstrand.net>
Tue, 8 Jan 2019 00:38:29 +0000 (00:38 +0000)
SPIR-V allows for matrix and array types to be decorated with explicit
byte stride decorations and matrix types to be decorated row- or
column-major.  This commit adds support to glsl_type to encode this
information.  Because this doesn't work nicely with std430 and std140
alignments, we add asserts to ensure that we don't use any of the std430
or std140 layout functions with explicitly laid out types.

In SPIR-V, the layout information for matrices is applied to the parent
struct member instead of to the matrix type itself.  However, this is
gets rather clumsy when you're walking derefs trying to compute offsets
because, the moment you hit a matrix, you have to crawl back the deref
chain and find the struct.  Instead, we take the same path here as we've
taken in spirv_to_nir and put the decorations on the matrix type itself.

This also subtly adds support for strided vector types.  These don't
come up in SPIR-V directly but you can get one as the result of taking a
column from a row-major matrix or a row from a column-major matrix.

Reviewed-by: Alejandro PiƱeiro <apinheiro@igalia.com>
15 files changed:
src/compiler/glsl/gl_nir_lower_samplers_as_deref.c
src/compiler/glsl_types.cpp
src/compiler/glsl_types.h
src/compiler/nir/nir_lower_atomics_to_ssbo.c
src/compiler/nir/nir_lower_clip_cull_distance_arrays.c
src/compiler/nir/nir_lower_io_arrays_to_elements.c
src/compiler/nir/nir_split_per_member_structs.c
src/compiler/nir/nir_split_vars.c
src/compiler/nir_types.cpp
src/compiler/nir_types.h
src/compiler/spirv/spirv_to_nir.c
src/compiler/spirv/vtn_variables.c
src/gallium/auxiliary/nir/tgsi_to_nir.c
src/intel/vulkan/anv_nir_lower_multiview.c
src/mesa/program/prog_to_nir.c

index f3f2dd22df29cd5f2692442d3cf608a65263557a..96c751a1284e1a9a26d92d1b4ab1e45d59a689be 100644 (file)
@@ -99,7 +99,7 @@ remove_struct_derefs_prep(nir_deref_instr **p, char **name,
 
       remove_struct_derefs_prep(&p[1], name, location, type);
 
-      *type = glsl_array_type(*type, length);
+      *type = glsl_array_type(*type, length, glsl_get_explicit_stride(cur->type));
       break;
    }
 
index 67f3967d0c15a6533854177f5a147e666769ffec..00be0e00a9e7675eff42fdf9323ec115c73bcda3 100644 (file)
@@ -30,6 +30,7 @@
 
 
 mtx_t glsl_type::hash_mutex = _MTX_INITIALIZER_NP;
+hash_table *glsl_type::explicit_matrix_types = NULL;
 hash_table *glsl_type::array_types = NULL;
 hash_table *glsl_type::record_types = NULL;
 hash_table *glsl_type::interface_types = NULL;
@@ -38,13 +39,14 @@ hash_table *glsl_type::subroutine_types = NULL;
 
 glsl_type::glsl_type(GLenum gl_type,
                      glsl_base_type base_type, unsigned vector_elements,
-                     unsigned matrix_columns, const char *name) :
+                     unsigned matrix_columns, const char *name,
+                     unsigned explicit_stride, bool row_major) :
    gl_type(gl_type),
    base_type(base_type), sampled_type(GLSL_TYPE_VOID),
    sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
-   interface_packing(0), interface_row_major(0),
+   interface_packing(0), interface_row_major(row_major),
    vector_elements(vector_elements), matrix_columns(matrix_columns),
-   length(0)
+   length(0), explicit_stride(explicit_stride)
 {
    /* Values of these types must fit in the two bits of
     * glsl_type::sampled_type.
@@ -77,7 +79,8 @@ glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type,
    base_type(base_type), sampled_type(type),
    sampler_dimensionality(dim), sampler_shadow(shadow),
    sampler_array(array), interface_packing(0),
-   interface_row_major(0), length(0)
+   interface_row_major(0),
+   length(0), explicit_stride(0)
 {
    this->mem_ctx = ralloc_context(NULL);
    assert(this->mem_ctx != NULL);
@@ -97,7 +100,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
    sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
    interface_packing(0), interface_row_major(0),
    vector_elements(0), matrix_columns(0),
-   length(num_fields)
+   length(num_fields), explicit_stride(0)
 {
    unsigned int i;
 
@@ -127,7 +130,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
    interface_packing((unsigned) packing),
    interface_row_major((unsigned) row_major),
    vector_elements(0), matrix_columns(0),
-   length(num_fields)
+   length(num_fields), explicit_stride(0)
 {
    unsigned int i;
 
@@ -152,7 +155,7 @@ glsl_type::glsl_type(const glsl_type *return_type,
    sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
    interface_packing(0), interface_row_major(0),
    vector_elements(0), matrix_columns(0),
-   length(num_params)
+   length(num_params), explicit_stride(0)
 {
    unsigned int i;
 
@@ -181,7 +184,7 @@ glsl_type::glsl_type(const char *subroutine_name) :
    sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
    interface_packing(0), interface_row_major(0),
    vector_elements(1), matrix_columns(1),
-   length(0)
+   length(0), explicit_stride(0)
 {
    this->mem_ctx = ralloc_context(NULL);
    assert(this->mem_ctx != NULL);
@@ -389,6 +392,55 @@ const glsl_type *glsl_type::get_scalar_type() const
 }
 
 
+const glsl_type *glsl_type::get_bare_type() const
+{
+   switch (this->base_type) {
+   case GLSL_TYPE_UINT8:
+   case GLSL_TYPE_INT8:
+   case GLSL_TYPE_UINT16:
+   case GLSL_TYPE_INT16:
+   case GLSL_TYPE_FLOAT16:
+   case GLSL_TYPE_UINT:
+   case GLSL_TYPE_INT:
+   case GLSL_TYPE_FLOAT:
+   case GLSL_TYPE_BOOL:
+   case GLSL_TYPE_DOUBLE:
+   case GLSL_TYPE_UINT64:
+   case GLSL_TYPE_INT64:
+      return get_instance(this->base_type, this->vector_elements,
+                          this->matrix_columns);
+
+   case GLSL_TYPE_STRUCT:
+   case GLSL_TYPE_INTERFACE: {
+      glsl_struct_field *bare_fields = new glsl_struct_field[this->length];
+      for (unsigned i = 0; i < this->length; i++) {
+         bare_fields[i].type = this->fields.structure[i].type->get_bare_type();
+         bare_fields[i].name = this->fields.structure[i].name;
+      }
+      const glsl_type *bare_type =
+         get_record_instance(bare_fields, this->length, this->name);
+      delete[] bare_fields;
+      return bare_type;
+   }
+
+   case GLSL_TYPE_ARRAY:
+      return get_array_instance(this->fields.array->get_bare_type(),
+                                this->length);
+
+   case GLSL_TYPE_SAMPLER:
+   case GLSL_TYPE_IMAGE:
+   case GLSL_TYPE_ATOMIC_UINT:
+   case GLSL_TYPE_VOID:
+   case GLSL_TYPE_SUBROUTINE:
+   case GLSL_TYPE_FUNCTION:
+   case GLSL_TYPE_ERROR:
+      return this;
+   }
+
+   unreachable("Invalid base type");
+}
+
+
 static void
 hash_free_type_function(struct hash_entry *entry)
 {
@@ -407,6 +459,12 @@ _mesa_glsl_release_types(void)
     * object, or if process terminates), so no mutex-locking should be
     * necessary.
     */
+   if (glsl_type::explicit_matrix_types != NULL) {
+      _mesa_hash_table_destroy(glsl_type::explicit_matrix_types,
+                               hash_free_type_function);
+      glsl_type::explicit_matrix_types = NULL;
+   }
+
    if (glsl_type::array_types != NULL) {
       _mesa_hash_table_destroy(glsl_type::array_types, hash_free_type_function);
       glsl_type::array_types = NULL;
@@ -434,12 +492,13 @@ _mesa_glsl_release_types(void)
 }
 
 
-glsl_type::glsl_type(const glsl_type *array, unsigned length) :
+glsl_type::glsl_type(const glsl_type *array, unsigned length,
+                     unsigned explicit_stride) :
    base_type(GLSL_TYPE_ARRAY), sampled_type(GLSL_TYPE_VOID),
    sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
    interface_packing(0), interface_row_major(0),
    vector_elements(0), matrix_columns(0),
-   length(length), name(NULL)
+   length(length), name(NULL), explicit_stride(explicit_stride)
 {
    this->fields.array = array;
    /* Inherit the gl type of the base. The GL type is used for
@@ -521,10 +580,57 @@ VECN(components, int8_t, i8vec)
 VECN(components, uint8_t, u8vec)
 
 const glsl_type *
-glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns)
+glsl_type::get_instance(unsigned base_type, unsigned rows, unsigned columns,
+                        unsigned explicit_stride, bool row_major)
 {
-   if (base_type == GLSL_TYPE_VOID)
+   if (base_type == GLSL_TYPE_VOID) {
+      assert(explicit_stride == 0 && !row_major);
       return void_type;
+   }
+
+   /* Matrix and vector types with explicit strides have to be looked up in a
+    * table so they're handled separately.
+    */
+   if (explicit_stride > 0) {
+      const glsl_type *bare_type = get_instance(base_type, rows, columns);
+
+      assert(columns > 1 || !row_major);
+
+      char name[128];
+      util_snprintf(name, sizeof(name), "%sx%uB%s", bare_type->name,
+                    explicit_stride, row_major ? "RM" : "");
+
+      mtx_lock(&glsl_type::hash_mutex);
+
+      if (explicit_matrix_types == NULL) {
+         explicit_matrix_types =
+            _mesa_hash_table_create(NULL, _mesa_key_hash_string,
+                                    _mesa_key_string_equal);
+      }
+
+      const struct hash_entry *entry =
+         _mesa_hash_table_search(explicit_matrix_types, name);
+      if (entry == NULL) {
+         const glsl_type *t = new glsl_type(bare_type->gl_type,
+                                            (glsl_base_type)base_type,
+                                            rows, columns, name,
+                                            explicit_stride, row_major);
+
+         entry = _mesa_hash_table_insert(explicit_matrix_types,
+                                         t->name, (void *)t);
+      }
+
+      assert(((glsl_type *) entry->data)->base_type == base_type);
+      assert(((glsl_type *) entry->data)->vector_elements == rows);
+      assert(((glsl_type *) entry->data)->matrix_columns == columns);
+      assert(((glsl_type *) entry->data)->explicit_stride == explicit_stride);
+
+      mtx_unlock(&glsl_type::hash_mutex);
+
+      return (const glsl_type *) entry->data;
+   }
+
+   assert(!row_major);
 
    /* Treat GLSL vectors as Nx1 matrices.
     */
@@ -846,7 +952,9 @@ glsl_type::get_image_instance(enum glsl_sampler_dim dim,
 }
 
 const glsl_type *
-glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
+glsl_type::get_array_instance(const glsl_type *base,
+                              unsigned array_size,
+                              unsigned explicit_stride)
 {
    /* Generate a name using the base type pointer in the key.  This is
     * done because the name of the base type may not be unique across
@@ -854,7 +962,8 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
     * named 'foo'.
     */
    char key[128];
-   util_snprintf(key, sizeof(key), "%p[%u]", (void *) base, array_size);
+   util_snprintf(key, sizeof(key), "%p[%u]x%uB", (void *) base, array_size,
+                 explicit_stride);
 
    mtx_lock(&glsl_type::hash_mutex);
 
@@ -865,7 +974,7 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size)
 
    const struct hash_entry *entry = _mesa_hash_table_search(array_types, key);
    if (entry == NULL) {
-      const glsl_type *t = new glsl_type(base, array_size);
+      const glsl_type *t = new glsl_type(base, array_size, explicit_stride);
 
       entry = _mesa_hash_table_insert(array_types,
                                       strdup(key),
@@ -1599,6 +1708,7 @@ glsl_type::std140_size(bool row_major) const
     *     <N> basic machine units, the base alignment is 4<N>.
     */
    if (this->is_scalar() || this->is_vector()) {
+      assert(this->explicit_stride == 0);
       return this->vector_elements * N;
    }
 
@@ -1633,6 +1743,8 @@ glsl_type::std140_size(bool row_major) const
          array_len = 1;
       }
 
+      assert(element_type->explicit_stride == 0);
+
       if (row_major) {
          vec_type = get_instance(element_type->base_type,
                                  element_type->matrix_columns, 1);
@@ -1660,6 +1772,7 @@ glsl_type::std140_size(bool row_major) const
     *      the array are laid out in order, according to rule (9).
     */
    if (this->is_array()) {
+      assert(this->explicit_stride == 0);
       if (this->without_array()->is_record()) {
         return this->arrays_of_arrays_size() *
             this->without_array()->std140_size(row_major);
@@ -1834,6 +1947,8 @@ glsl_type::std430_array_stride(bool row_major) const
 {
    unsigned N = is_64bit() ? 8 : 4;
 
+   assert(explicit_stride == 0);
+
    /* Notice that the array stride of a vec3 is not 3 * N but 4 * N.
     * See OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout"
     *
@@ -1860,8 +1975,10 @@ glsl_type::std430_size(bool row_major) const
     * stride of arrays of scalars and vectors in rule 4 and of structures
     * in rule 9 are not rounded up a multiple of the base alignment of a vec4.
     */
-   if (this->is_scalar() || this->is_vector())
-         return this->vector_elements * N;
+   if (this->is_scalar() || this->is_vector()) {
+      assert(this->explicit_stride == 0);
+      return this->vector_elements * N;
+   }
 
    if (this->without_array()->is_matrix()) {
       const struct glsl_type *element_type;
@@ -1876,6 +1993,8 @@ glsl_type::std430_size(bool row_major) const
          array_len = 1;
       }
 
+      assert(element_type->explicit_stride == 0);
+
       if (row_major) {
          vec_type = get_instance(element_type->base_type,
                                  element_type->matrix_columns, 1);
@@ -1893,6 +2012,7 @@ glsl_type::std430_size(bool row_major) const
    }
 
    if (this->is_array()) {
+      assert(this->explicit_stride == 0);
       if (this->without_array()->is_record())
          return this->arrays_of_arrays_size() *
             this->without_array()->std430_size(row_major);
@@ -2092,9 +2212,12 @@ encode_type_to_blob(struct blob *blob, const glsl_type *type)
    case GLSL_TYPE_INT64:
    case GLSL_TYPE_BOOL:
       encoding = (type->base_type << 24) |
+         (type->interface_row_major << 10) |
          (type->vector_elements << 4) |
          (type->matrix_columns);
-      break;
+      blob_write_uint32(blob, encoding);
+      blob_write_uint32(blob, type->explicit_stride);
+      return;
    case GLSL_TYPE_SAMPLER:
       encoding = (type->base_type) << 24 |
          (type->sampler_dimensionality << 4) |
@@ -2119,6 +2242,7 @@ encode_type_to_blob(struct blob *blob, const glsl_type *type)
    case GLSL_TYPE_ARRAY:
       blob_write_uint32(blob, (type->base_type) << 24);
       blob_write_uint32(blob, type->length);
+      blob_write_uint32(blob, type->explicit_stride);
       encode_type_to_blob(blob, type->fields.array);
       return;
    case GLSL_TYPE_STRUCT:
@@ -2181,8 +2305,11 @@ decode_type_from_blob(struct blob_reader *blob)
    case GLSL_TYPE_INT16:
    case GLSL_TYPE_UINT64:
    case GLSL_TYPE_INT64:
-   case GLSL_TYPE_BOOL:
-      return glsl_type::get_instance(base_type, (u >> 4) & 0x0f, u & 0x0f);
+   case GLSL_TYPE_BOOL: {
+      unsigned explicit_stride = blob_read_uint32(blob);
+      return glsl_type::get_instance(base_type, (u >> 4) & 0x0f, u & 0x0f,
+                                     explicit_stride, (u >> 10) & 0x1);
+   }
    case GLSL_TYPE_SAMPLER:
       return glsl_type::get_sampler_instance((enum glsl_sampler_dim) ((u >> 4) & 0x07),
                                              (u >> 3) & 0x01,
@@ -2198,8 +2325,9 @@ decode_type_from_blob(struct blob_reader *blob)
       return glsl_type::atomic_uint_type;
    case GLSL_TYPE_ARRAY: {
       unsigned length = blob_read_uint32(blob);
+      unsigned explicit_stride = blob_read_uint32(blob);
       return glsl_type::get_array_instance(decode_type_from_blob(blob),
-                                           length);
+                                           length, explicit_stride);
    }
    case GLSL_TYPE_STRUCT:
    case GLSL_TYPE_INTERFACE: {
index d32b580acc1e5c7035885860b363b4ff8527381c..4d205fad1413c1e4358ff52f8847a31dbe74c5f1 100644 (file)
@@ -209,6 +209,13 @@ public:
     */
    const char *name;
 
+   /**
+    * Explicit array, matrix, or vector stride.  This is used to communicate
+    * explicit array layouts from SPIR-V.  Should be 0 if the type has no
+    * explicit stride.
+    */
+   unsigned explicit_stride;
+
    /**
     * Subtype of composite data types.
     */
@@ -271,11 +278,18 @@ public:
     */
    const glsl_type *get_scalar_type() const;
 
+   /**
+    * Gets the "bare" type without any decorations or layout information.
+    */
+   const glsl_type *get_bare_type() const;
+
    /**
     * Get the instance of a built-in scalar, vector, or matrix type
     */
    static const glsl_type *get_instance(unsigned base_type, unsigned rows,
-                                       unsigned columns);
+                                        unsigned columns,
+                                        unsigned explicit_stride = 0,
+                                        bool row_major = false);
 
    /**
     * Get the instance of a sampler type
@@ -292,7 +306,8 @@ public:
     * Get the instance of an array type
     */
    static const glsl_type *get_array_instance(const glsl_type *base,
-                                             unsigned elements);
+                                              unsigned elements,
+                                              unsigned explicit_stride = 0);
 
    /**
     * Get the instance of a record type
@@ -752,9 +767,13 @@ public:
     */
    const glsl_type *row_type() const
    {
-      return is_matrix()
-        ? get_instance(base_type, matrix_columns, 1)
-        : error_type;
+      if (!is_matrix())
+         return error_type;
+
+      if (explicit_stride && !interface_row_major)
+         return get_instance(base_type, matrix_columns, 1, explicit_stride);
+      else
+         return get_instance(base_type, matrix_columns, 1);
    }
 
    /**
@@ -766,9 +785,13 @@ public:
     */
    const glsl_type *column_type() const
    {
-      return is_matrix()
-        ? get_instance(base_type, vector_elements, 1)
-        : error_type;
+      if (!is_matrix())
+         return error_type;
+
+      if (explicit_stride && interface_row_major)
+         return get_instance(base_type, vector_elements, 1, explicit_stride);
+      else
+         return get_instance(base_type, vector_elements, 1);
    }
 
    /**
@@ -878,8 +901,9 @@ private:
 
    /** Constructor for vector and matrix types */
    glsl_type(GLenum gl_type,
-            glsl_base_type base_type, unsigned vector_elements,
-            unsigned matrix_columns, const char *name);
+             glsl_base_type base_type, unsigned vector_elements,
+             unsigned matrix_columns, const char *name,
+             unsigned explicit_stride = 0, bool row_major = false);
 
    /** Constructor for sampler or image types */
    glsl_type(GLenum gl_type, glsl_base_type base_type,
@@ -899,12 +923,15 @@ private:
    glsl_type(const glsl_type *return_type,
              const glsl_function_param *params, unsigned num_params);
 
-   /** Constructor for array types */
-   glsl_type(const glsl_type *array, unsigned length);
+   /** Constructors for array types */
+   glsl_type(const glsl_type *array, unsigned length, unsigned explicit_stride);
 
    /** Constructor for subroutine types */
    glsl_type(const char *name);
 
+   /** Hash table containing the known explicit matrix and vector types. */
+   static struct hash_table *explicit_matrix_types;
+
    /** Hash table containing the known array types. */
    static struct hash_table *array_types;
 
index d9acc5c3a792bb3cf072a8f2e40e898314ee32fc..ffa03dc27f802ef84dd263fa80882b3e3c7ccb5d 100644 (file)
@@ -219,7 +219,7 @@ nir_lower_atomics_to_ssbo(nir_shader *shader, unsigned ssbo_offset)
             char name[16];
 
             /* A length of 0 is used to denote unsized arrays */
-            const struct glsl_type *type = glsl_array_type(glsl_uint_type(), 0);
+            const struct glsl_type *type = glsl_array_type(glsl_uint_type(), 0, 0);
 
             snprintf(name, sizeof(name), "counter%d", var->data.binding);
 
index 2afbf9285c0672a1ac0a08b6a65017548f5b4b64..6e1557ef40d5e324c813b845303ccc6d0cfaa854 100644 (file)
@@ -62,10 +62,10 @@ get_unwrapped_array_length(nir_shader *nir, nir_variable *var)
 static void
 update_type(nir_variable *var, gl_shader_stage stage, unsigned length)
 {
-   const struct glsl_type *type = glsl_array_type(glsl_float_type(), length);
+   const struct glsl_type *type = glsl_array_type(glsl_float_type(), length, 0);
 
    if (nir_is_per_vertex_io(var, stage))
-      type = glsl_array_type(type, glsl_get_length(var->type));
+      type = glsl_array_type(type, glsl_get_length(var->type), 0);
 
    var->type = type;
 }
index 30d53f156ff68f100f393ff3025795480e0baf6b..3402024919957576329916e6be710ab769336fd9 100644 (file)
@@ -127,13 +127,12 @@ lower_array(nir_builder *b, nir_intrinsic_instr *intr, nir_variable *var,
          const struct glsl_type *type = glsl_without_array(element->type);
 
          /* This pass also splits matrices so we need give them a new type. */
-         if (glsl_type_is_matrix(type)) {
-            type = glsl_vector_type(glsl_get_base_type(type),
-                                    glsl_get_vector_elements(type));
-         }
+         if (glsl_type_is_matrix(type))
+            type = glsl_get_column_type(type);
 
          if (nir_is_per_vertex_io(var, b->shader->info.stage)) {
-            type = glsl_array_type(type, glsl_get_length(element->type));
+            type = glsl_array_type(type, glsl_get_length(element->type),
+                                   glsl_get_explicit_stride(element->type));
          }
 
          element->type = type;
index f649c8f474bf26eed521fa89b7ad39a0bc81f2a0..c1234c2e92a676d916b6ff26adea8f51ac29fcba 100644 (file)
@@ -50,7 +50,8 @@ member_type(const struct glsl_type *type, unsigned index)
    if (glsl_type_is_array(type)) {
       const struct glsl_type *elem =
          member_type(glsl_get_array_element(type), index);
-      return glsl_array_type(elem, glsl_get_length(type));
+      assert(glsl_get_explicit_stride(type) == 0);
+      return glsl_array_type(elem, glsl_get_length(type), 0);
    } else {
       assert(glsl_type_is_struct(type));
       assert(index < glsl_get_length(type));
index bf9205c51503be6aa5a6b1b10ddd26602bb628e5..e738ee3f3859756cfd2a206a57cc03c15cbfa50e 100644 (file)
@@ -58,7 +58,8 @@ wrap_type_in_array(const struct glsl_type *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));
+   assert(glsl_get_explicit_stride(array_type) == 0);
+   return glsl_array_type(elem_type, glsl_get_length(array_type), 0);
 }
 
 static int
@@ -341,6 +342,7 @@ init_var_list_array_infos(struct exec_list *vars,
 
       const struct glsl_type *type = var->type;
       for (int i = 0; i < num_levels; i++) {
+         assert(glsl_get_explicit_stride(type) == 0);
          info->levels[i].array_len = glsl_get_length(type);
          type = glsl_get_array_element(type);
 
@@ -506,7 +508,7 @@ split_var_list_arrays(nir_shader *shader,
                                           glsl_get_components(split_type),
                                           info->levels[i].array_len);
          } else {
-            split_type = glsl_array_type(split_type, info->levels[i].array_len);
+            split_type = glsl_array_type(split_type, info->levels[i].array_len, 0);
          }
       }
 
@@ -918,6 +920,7 @@ get_vec_var_usage(nir_variable *var,
    const struct glsl_type *type = var->type;
    for (unsigned i = 0; i < num_levels; i++) {
       usage->levels[i].array_len = glsl_get_length(type);
+      assert(glsl_get_explicit_stride(type) == 0);
       type = glsl_get_array_element(type);
    }
    assert(glsl_type_is_vector_or_scalar(type));
@@ -1290,7 +1293,7 @@ shrink_vec_var_list(struct exec_list *vars,
                                         new_num_comps,
                                         usage->levels[i].array_len);
          } else {
-            new_type = glsl_array_type(new_type, usage->levels[i].array_len);
+            new_type = glsl_array_type(new_type, usage->levels[i].array_len, 0);
          }
       }
       var->type = new_type;
index 2b4ff0702f291688872db867a649baa788857b2f..356252276b4a9ac0d093ec1a6011d052fd62a950 100644 (file)
@@ -59,6 +59,12 @@ glsl_without_array_or_matrix(const glsl_type *type)
    return type;
 }
 
+const glsl_type *
+glsl_get_bare_type(const glsl_type *type)
+{
+   return type->get_bare_type();
+}
+
 const glsl_type *
 glsl_get_struct_field(const glsl_type *type, unsigned index)
 {
@@ -72,6 +78,12 @@ glsl_get_struct_field_offset(const struct glsl_type *type,
    return type->fields.structure[index].offset;
 }
 
+const unsigned
+glsl_get_explicit_stride(const struct glsl_type *type)
+{
+   return type->explicit_stride;
+}
+
 const glsl_type *
 glsl_get_function_return_type(const glsl_type *type)
 {
@@ -234,6 +246,13 @@ glsl_type_is_matrix(const struct glsl_type *type)
    return type->is_matrix();
 }
 
+bool
+glsl_matrix_type_is_row_major(const struct glsl_type *type)
+{
+   assert(type->is_matrix() && type->explicit_stride);
+   return type->interface_row_major;
+}
+
 bool
 glsl_type_is_array(const struct glsl_type *type)
 {
@@ -432,9 +451,23 @@ glsl_matrix_type(enum glsl_base_type base_type, unsigned rows, unsigned columns)
 }
 
 const glsl_type *
-glsl_array_type(const glsl_type *base, unsigned elements)
+glsl_explicit_matrix_type(const glsl_type *mat,
+                          unsigned stride, bool row_major)
+{
+   assert(stride > 0);
+   const glsl_type *t = glsl_type::get_instance(mat->base_type,
+                                                mat->vector_elements,
+                                                mat->matrix_columns,
+                                                stride, row_major);
+   assert(t != glsl_type::error_type);
+   return t;
+}
+
+const glsl_type *
+glsl_array_type(const glsl_type *base, unsigned elements,
+                unsigned explicit_stride)
 {
-   return glsl_type::get_array_instance(base, elements);
+   return glsl_type::get_array_instance(base, elements, explicit_stride);
 }
 
 const glsl_type *
@@ -495,7 +528,8 @@ glsl_channel_type(const glsl_type *t)
 {
    switch (t->base_type) {
    case GLSL_TYPE_ARRAY:
-      return glsl_array_type(glsl_channel_type(t->fields.array), t->length);
+      return glsl_array_type(glsl_channel_type(t->fields.array), t->length,
+                             t->explicit_stride);
    case GLSL_TYPE_UINT:
    case GLSL_TYPE_INT:
    case GLSL_TYPE_FLOAT:
index 6e671b4cc71f32ba8ab18c25e2f13f2e78b62e3c..d17671b940000a8ff7ba0f79662cd9569dce396f 100644 (file)
@@ -49,9 +49,11 @@ const struct glsl_type *glsl_get_struct_field(const struct glsl_type *type,
 const int glsl_get_struct_field_offset(const struct glsl_type *type,
                                        unsigned index);
 
+const unsigned glsl_get_explicit_stride(const struct glsl_type *type);
 const struct glsl_type *glsl_get_array_element(const struct glsl_type *type);
 const struct glsl_type *glsl_without_array(const struct glsl_type *type);
 const struct glsl_type *glsl_without_array_or_matrix(const struct glsl_type *type);
+const struct glsl_type *glsl_get_bare_type(const struct glsl_type *type);
 
 const struct glsl_type *glsl_get_column_type(const struct glsl_type *type);
 
@@ -136,6 +138,7 @@ bool glsl_type_is_vector(const struct glsl_type *type);
 bool glsl_type_is_scalar(const struct glsl_type *type);
 bool glsl_type_is_vector_or_scalar(const struct glsl_type *type);
 bool glsl_type_is_matrix(const struct glsl_type *type);
+bool glsl_matrix_type_is_row_major(const struct glsl_type *type);
 bool glsl_type_is_array(const struct glsl_type *type);
 bool glsl_type_is_array_of_arrays(const struct glsl_type *type);
 bool glsl_type_is_array_or_matrix(const struct glsl_type *type);
@@ -173,8 +176,14 @@ const struct glsl_type *glsl_vector_type(enum glsl_base_type base_type,
                                          unsigned components);
 const struct glsl_type *glsl_matrix_type(enum glsl_base_type base_type,
                                          unsigned rows, unsigned columns);
+const struct glsl_type *glsl_explicit_matrix_type(const struct glsl_type *mat,
+                                                  unsigned stride,
+                                                  bool row_major);
+
 const struct glsl_type *glsl_array_type(const struct glsl_type *base,
-                                        unsigned elements);
+                                        unsigned elements,
+                                        unsigned explicit_stride);
+
 const struct glsl_type *glsl_struct_type(const struct glsl_struct_field *fields,
                                          unsigned num_fields, const char *name);
 const struct glsl_type *glsl_interface_type(const struct glsl_struct_field *fields,
index 341a1cb17ceda47142c888ea8e55a7b58ab8cb84..a9fd543e12f3129a6de5f942d8c50688c1bda058 100644 (file)
@@ -1145,7 +1145,7 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
       }
 
       val->type->base_type = vtn_base_type_array;
-      val->type->type = glsl_array_type(array_element->type, val->type->length);
+      val->type->type = glsl_array_type(array_element->type, val->type->length, 0);
       val->type->array_element = array_element;
       val->type->stride = 0;
       break;
index f33eb5509a0e2bfad59aa53aacb5810812aeef5e..fb497fc2d069e8617a1f0c901abb13cb8775aa2d 100644 (file)
@@ -389,7 +389,8 @@ repair_atomic_type(const struct glsl_type *type)
       const struct glsl_type *atomic =
          repair_atomic_type(glsl_get_array_element(type));
 
-      return glsl_array_type(atomic, glsl_get_length(type));
+      return glsl_array_type(atomic, glsl_get_length(type),
+                             glsl_get_explicit_stride(type));
    } else {
       return glsl_atomic_uint_type();
    }
index e1ef7bca7cccd8cdec7aa78a8dfc5e017026ddb6..0f365d9ebe0544ef437cb33cca84cb3fda365186 100644 (file)
@@ -181,7 +181,7 @@ ttn_emit_declaration(struct ttn_compile *c)
          /* for arrays, we create variables instead of registers: */
          nir_variable *var = rzalloc(b->shader, nir_variable);
 
-         var->type = glsl_array_type(glsl_vec4_type(), array_size);
+         var->type = glsl_array_type(glsl_vec4_type(), array_size, 0);
          var->data.mode = nir_var_global;
          var->name = ralloc_asprintf(var, "arr_%d", decl->Array.ArrayID);
 
@@ -265,7 +265,7 @@ ttn_emit_declaration(struct ttn_compile *c)
 
          var->type = glsl_vec4_type();
          if (is_array)
-            var->type = glsl_array_type(var->type, array_size);
+            var->type = glsl_array_type(var->type, array_size, 0);
 
          switch (file) {
          case TGSI_FILE_INPUT:
index 498be05b7ba7eefbc2e9e41378225d73f5800dbf..c42d9c2dfa2533264b1c283c8c39672b9c34199b 100644 (file)
@@ -125,7 +125,7 @@ build_view_index(struct lower_multiview_state *state)
          const struct glsl_type *type = glsl_int_type();
          if (b->shader->info.stage == MESA_SHADER_TESS_CTRL ||
              b->shader->info.stage == MESA_SHADER_GEOMETRY)
-            type = glsl_array_type(type, 1);
+            type = glsl_array_type(type, 1, 0);
 
          nir_variable *idx_var =
             nir_variable_create(b->shader, nir_var_shader_in,
index ee7d7d8f6d21900ae987885480b719d9fbaa20d5..10ba037d428c25ec2332afeb7d1aad19f5be1d60 100644 (file)
@@ -983,7 +983,7 @@ prog_to_nir(const struct gl_program *prog,
    if (prog->Parameters->NumParameters > 0) {
       c->parameters = rzalloc(s, nir_variable);
       c->parameters->type =
-         glsl_array_type(glsl_vec4_type(), prog->Parameters->NumParameters);
+         glsl_array_type(glsl_vec4_type(), prog->Parameters->NumParameters, 0);
       c->parameters->name = "parameters";
       c->parameters->data.read_only = true;
       c->parameters->data.mode = nir_var_uniform;