[Mesa-dev] [PATCH 12/28] glsl_types/nir: add explicit_array_stride plus nir wrapper helpers

Alejandro PiƱeiro apinheiro at igalia.com
Mon Oct 22 12:24:34 UTC 2018


>From ARB_gl_spirv:
    "Mapping of layouts

      std140/std430  ->  explicit *Offset*, *ArrayStride*, and *MatrixStride*
                         Decoration on struct members"

That means that we would not have available any kind of layout info,
and we should use explicit array strides.

This commit adds explicit_array_stride. The default value is -1
meaning that it is not set (as with offset). That should be the
default value for GLSL.

In general, the default constructor is ok. We just need to be careful
with some array lowerings, as it should try to get the explicit array
stride when creating new types.

Note that this means that for the ARB_gl_spirv case
std430_array_stride, std140_size etc are meaningless (unless you guess
the layout, something that you shouldn't).

v2: add missing glsl_full_array_type call, found while testing
    ARB_gl_spirv with borrowed tests (Alejandro)
---
 src/compiler/glsl/gl_nir_lower_samplers_as_deref.c |  2 +-
 src/compiler/glsl_types.cpp                        | 28 +++++++++++++---------
 src/compiler/glsl_types.h                          | 13 +++++++---
 src/compiler/nir/nir_lower_io_arrays_to_elements.c |  3 ++-
 src/compiler/nir/nir_split_per_member_structs.c    |  3 ++-
 src/compiler/nir/nir_split_vars.c                  |  7 ++++--
 src/compiler/nir_types.cpp                         | 20 +++++++++++++---
 src/compiler/nir_types.h                           | 10 +++++++-
 src/compiler/spirv/vtn_variables.c                 |  3 ++-
 9 files changed, 65 insertions(+), 24 deletions(-)

diff --git a/src/compiler/glsl/gl_nir_lower_samplers_as_deref.c b/src/compiler/glsl/gl_nir_lower_samplers_as_deref.c
index 9ff5708f503..9716ac4562a 100644
--- a/src/compiler/glsl/gl_nir_lower_samplers_as_deref.c
+++ b/src/compiler/glsl/gl_nir_lower_samplers_as_deref.c
@@ -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_get_array_instance(*type, length);
+      *type = glsl_get_array_instance(*type, length, glsl_get_explicit_array_stride(cur->type));
       break;
    }
 
diff --git a/src/compiler/glsl_types.cpp b/src/compiler/glsl_types.cpp
index 104a5104aaa..ef3058a3911 100644
--- a/src/compiler/glsl_types.cpp
+++ b/src/compiler/glsl_types.cpp
@@ -44,7 +44,7 @@ glsl_type::glsl_type(GLenum gl_type,
    sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
    interface_packing(0), interface_row_major(0),
    vector_elements(vector_elements), matrix_columns(matrix_columns),
-   length(0)
+   length(0), explicit_array_stride(-1)
 {
    /* Values of these types must fit in the two bits of
     * glsl_type::sampled_type.
@@ -77,7 +77,7 @@ 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_array_stride(-1)
 {
    this->mem_ctx = ralloc_context(NULL);
    assert(this->mem_ctx != NULL);
@@ -97,7 +97,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_array_stride(-1)
 {
    unsigned int i;
 
@@ -127,7 +127,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_array_stride(-1)
 {
    unsigned int i;
 
@@ -152,7 +152,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_array_stride(-1)
 {
    unsigned int i;
 
@@ -181,7 +181,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_array_stride(-1)
 {
    this->mem_ctx = ralloc_context(NULL);
    assert(this->mem_ctx != NULL);
@@ -434,12 +434,12 @@ _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, int explicit_array_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_array_stride(explicit_array_stride)
 {
    this->fields.array = array;
    /* Inherit the gl type of the base. The GL type is used for
@@ -846,7 +846,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,
+                              int explicit_array_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 +856,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]%u", (void *) base, array_size,
+                 explicit_array_stride);
 
    mtx_lock(&glsl_type::hash_mutex);
 
@@ -865,7 +868,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_array_stride);
 
       entry = _mesa_hash_table_insert(array_types,
                                       strdup(key),
@@ -894,6 +897,9 @@ glsl_type::record_compare(const glsl_type *b, bool match_locations) const
    if (this->interface_row_major != b->interface_row_major)
       return false;
 
+   if (this->explicit_array_stride != b->explicit_array_stride)
+      return false;
+
    /* From the GLSL 4.20 specification (Sec 4.2):
     *
     *     "Structures must have the same name, sequence of type names, and
diff --git a/src/compiler/glsl_types.h b/src/compiler/glsl_types.h
index 9e8332e6cbf..968372ba4cf 100644
--- a/src/compiler/glsl_types.h
+++ b/src/compiler/glsl_types.h
@@ -209,6 +209,12 @@ public:
     */
    const char *name;
 
+   /**
+    * Explicit array stride. Since ARB_gl_spirv, it is possible to set it
+    * explicitly. Only for SPIR-V, should be -1 if not set (so always on GLSL)
+    */
+   int explicit_array_stride;
+
    /**
     * Subtype of composite data types.
     */
@@ -292,7 +298,8 @@ public:
     * Get the instance of an array type
     */
    static const glsl_type *get_array_instance(const glsl_type *base,
-					      unsigned elements);
+                                              unsigned elements,
+                                              int explicit_array_stride = -1);
 
    /**
     * Get the instance of a record type
@@ -899,8 +906,8 @@ 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, int explicit_array_stride = -1);
 
    /** Constructor for subroutine types */
    glsl_type(const char *name);
diff --git a/src/compiler/nir/nir_lower_io_arrays_to_elements.c b/src/compiler/nir/nir_lower_io_arrays_to_elements.c
index af33d153ea5..8d598401ae4 100644
--- a/src/compiler/nir/nir_lower_io_arrays_to_elements.c
+++ b/src/compiler/nir/nir_lower_io_arrays_to_elements.c
@@ -135,7 +135,8 @@ lower_array(nir_builder *b, nir_intrinsic_instr *intr, nir_variable *var,
 
          if (nir_is_per_vertex_io(var, b->shader->info.stage)) {
             type = glsl_get_array_instance(type,
-                                           glsl_get_length(element->type));
+                                           glsl_get_length(element->type),
+                                           glsl_get_explicit_array_stride(element->type));
          }
 
          element->type = type;
diff --git a/src/compiler/nir/nir_split_per_member_structs.c b/src/compiler/nir/nir_split_per_member_structs.c
index 9bad3512863..9f08b143ba7 100644
--- a/src/compiler/nir/nir_split_per_member_structs.c
+++ b/src/compiler/nir/nir_split_per_member_structs.c
@@ -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_get_array_instance(elem, glsl_get_length(type));
+      return glsl_get_array_instance(elem, glsl_get_length(type),
+                                     glsl_get_explicit_array_stride(type));
    } else {
       assert(glsl_type_is_struct(type));
       assert(index < glsl_get_length(type));
diff --git a/src/compiler/nir/nir_split_vars.c b/src/compiler/nir/nir_split_vars.c
index 02aef2a9b47..c2e46b35772 100644
--- a/src/compiler/nir/nir_split_vars.c
+++ b/src/compiler/nir/nir_split_vars.c
@@ -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));
+   return glsl_full_array_type(elem_type, glsl_get_length(array_type),
+                               glsl_get_explicit_array_stride(array_type));
 }
 
 static int
@@ -506,7 +507,9 @@ 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_full_array_type(split_type,
+                                              info->levels[i].array_len,
+                                              glsl_get_explicit_array_stride(var->type));
          }
       }
 
diff --git a/src/compiler/nir_types.cpp b/src/compiler/nir_types.cpp
index b2a5da1dc6c..c46037cc013 100644
--- a/src/compiler/nir_types.cpp
+++ b/src/compiler/nir_types.cpp
@@ -61,9 +61,10 @@ glsl_without_array_or_matrix(const glsl_type *type)
 
 const glsl_type *
 glsl_get_array_instance(const glsl_type *type,
-                        unsigned array_size)
+                        unsigned array_size,
+                        int explicit_array_stride)
 {
-   return glsl_type::get_array_instance(type, array_size);
+   return glsl_type::get_array_instance(type, array_size, explicit_array_stride);
 }
 
 const glsl_type *
@@ -93,6 +94,12 @@ glsl_get_struct_field_explicit_matrix_stride(const struct glsl_type *type,
    return type->fields.structure[index].explicit_matrix_stride;
 }
 
+const unsigned
+glsl_get_explicit_array_stride(const struct glsl_type *type)
+{
+   return type->explicit_array_stride;
+}
+
 const glsl_type *
 glsl_get_function_return_type(const glsl_type *type)
 {
@@ -453,6 +460,13 @@ glsl_array_type(const glsl_type *base, unsigned elements)
    return glsl_type::get_array_instance(base, elements);
 }
 
+const glsl_type *
+glsl_full_array_type(const glsl_type *base, unsigned elements,
+                     int explicit_array_stride)
+{
+   return glsl_type::get_array_instance(base, elements, explicit_array_stride);
+}
+
 const glsl_type *
 glsl_struct_type(const glsl_struct_field *fields,
                  unsigned num_fields, const char *name)
@@ -512,7 +526,7 @@ glsl_channel_type(const glsl_type *t)
    switch (glsl_get_base_type(t)) {
    case GLSL_TYPE_ARRAY: {
       const glsl_type *base = glsl_channel_type(glsl_get_array_element(t));
-      return glsl_array_type(base, glsl_get_length(t));
+      return glsl_full_array_type(base, glsl_get_length(t), glsl_get_explicit_array_stride(t));
    }
    case GLSL_TYPE_UINT:
       return glsl_uint_type();
diff --git a/src/compiler/nir_types.h b/src/compiler/nir_types.h
index d3c00ca5e1a..1988184b331 100644
--- a/src/compiler/nir_types.h
+++ b/src/compiler/nir_types.h
@@ -53,11 +53,13 @@ const unsigned glsl_get_struct_field_matrix_layout(const struct glsl_type *type,
                                                    unsigned index);
 const int glsl_get_struct_field_explicit_matrix_stride(const struct glsl_type *type,
                                                        unsigned index);
+const unsigned glsl_get_explicit_array_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_array_instance(const struct glsl_type *type,
-                                                unsigned array_size);
+                                                unsigned array_size,
+                                                int explicit_array_stride);
 
 const struct glsl_type *glsl_get_column_type(const struct glsl_type *type);
 
@@ -179,8 +181,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_array_type(const struct glsl_type *base,
                                         unsigned elements);
+
+const struct glsl_type *glsl_full_array_type(const struct glsl_type *base,
+                                             unsigned elements,
+                                             int explicit_array_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,
diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c
index 2a7a5b4947c..a88904531cb 100644
--- a/src/compiler/spirv/vtn_variables.c
+++ b/src/compiler/spirv/vtn_variables.c
@@ -400,7 +400,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_full_array_type(atomic, glsl_get_length(type),
+                                  glsl_get_explicit_array_stride(type));
    } else {
       return glsl_atomic_uint_type();
    }
-- 
2.14.1



More information about the mesa-dev mailing list