[Mesa-dev] [PATCH v3 (part2) 19/56] glsl: propagate std430 packing qualifier to struct's members and array of structs

Iago Toral Quiroga itoral at igalia.com
Tue Jul 14 00:46:21 PDT 2015


From: Samuel Iglesias Gonsalvez <siglesias at igalia.com>

When propagating std430 packing qualifier to the struct's members, new
glsl_types need to be created because the existing ones are const.
The new glsl_types are meant to replace the already defined one
taking into account that the field names cannot have different names
as it is the same struct definition but with different packing.

This patch is designed to keep previous default behavior (use std140 as
interface packing qualifier) when there is no std430 interface packing.

In order to facilitate the task, the glsl_type constructors for struct
and for interfaces are unified, as they had the same code but different
base_type.

Signed-off-by: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
---
 src/glsl/ast_to_hir.cpp    | 77 ++++++++++++++++++++++++++++++++++++++++++++--
 src/glsl/builtin_types.cpp |  3 +-
 src/glsl/glsl_types.cpp    | 64 +++++++++++++-------------------------
 src/glsl/glsl_types.h      | 17 +++++-----
 4 files changed, 108 insertions(+), 53 deletions(-)

diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 04f81aa..a814b8a 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -1942,6 +1942,62 @@ process_array_type(YYLTYPE *loc, const glsl_type *base,
    return array_type;
 }
 
+static const glsl_type *
+process_record_type(YYLTYPE *loc, const glsl_type *base,
+                    ast_array_specifier *array_specifier,
+                    struct _mesa_glsl_parse_state *state,
+                    enum glsl_interface_packing packing)
+{
+   const glsl_type *record = base;
+
+   /* Don't propagate interface packing if we are not in std430. Mesa works
+    * with std140 by default.
+    */
+   if (packing != GLSL_INTERFACE_PACKING_STD430)
+      return record;
+
+   glsl_struct_field *structure = ralloc_array(record->fields.structure,
+                                               glsl_struct_field,
+                                               record->length);
+
+   for (unsigned i = 0; i < record->length; i++) {
+      const glsl_type *field_type = record->fields.structure[i].type;
+
+      assert(field_type);
+      if (field_type->is_array()) {
+         if (field_type->fields.array->is_record()) {
+            /* Propagate interface packing information to arrays of struct */
+            const glsl_type *array_type = field_type->fields.array;
+            array_type = process_record_type(loc, array_type, array_specifier,
+                                             state, packing);
+            field_type = glsl_type::get_array_instance(array_type,
+                                                       field_type->length,
+                                                       packing);
+         } else {
+            field_type = glsl_type::get_array_instance(field_type->fields.array,
+                                                       field_type->length,
+                                                       packing);
+         }
+      }
+      if (field_type->is_record()) {
+         field_type = process_record_type(loc, field_type, array_specifier,
+                                          state, packing);
+      }
+      structure[i].type = field_type;
+      structure[i].name = ralloc_strdup(structure,
+                                       record->fields.structure[i].name);;
+      structure[i].location = record->fields.structure[i].location;
+      structure[i].interpolation = record->fields.structure[i].interpolation;
+      structure[i].centroid = record->fields.structure[i].centroid;
+      structure[i].sample = record->fields.structure[i].sample;
+      structure[i].matrix_layout = record->fields.structure[i].matrix_layout;
+   }
+
+   record = glsl_type::get_record_instance(structure,
+                                           record->length, packing, record->name);
+
+   return record;
+}
 
 const glsl_type *
 ast_type_specifier::glsl_type(const char **name,
@@ -1961,9 +2017,17 @@ ast_type_specifier::glsl_type(const char **name,
    *name = this->type_name;
 
    YYLTYPE loc = this->get_location();
-   type = process_array_type(&loc, type, this->array_specifier, state,
-                             packing);
 
+   if (type == NULL)
+      return type;
+
+   if (type->is_record()) {
+      type = process_record_type(&loc, type, this->array_specifier, state,
+                                 packing);
+   }
+
+   type = process_array_type(&loc, type, this->array_specifier, state,
+                                packing);
    return type;
 }
 
@@ -5453,6 +5517,15 @@ ast_process_structure_or_interface_block(exec_list *instructions,
                              "to struct or interface block members");
          }
 
+         if (decl_type->is_record()) {
+            /* Propagate packing information to struct members before
+             * processing an array of structs.
+             */
+            decl_type = process_record_type(&loc, decl_type,
+                                             decl->array_specifier, state,
+                                             packing);
+         }
+
          field_type = process_array_type(&loc, decl_type,
                                          decl->array_specifier, state,
                                          packing);
diff --git a/src/glsl/builtin_types.cpp b/src/glsl/builtin_types.cpp
index d92e2eb..f17ea96 100644
--- a/src/glsl/builtin_types.cpp
+++ b/src/glsl/builtin_types.cpp
@@ -49,7 +49,8 @@
 
 #define STRUCT_TYPE(NAME)                                       \
    const glsl_type glsl_type::_struct_##NAME##_type =           \
-      glsl_type(NAME##_fields, ARRAY_SIZE(NAME##_fields), #NAME); \
+      glsl_type(GLSL_TYPE_STRUCT, NAME##_fields, ARRAY_SIZE(NAME##_fields), \
+                GLSL_INTERFACE_PACKING_STD140, #NAME); \
    const glsl_type *const glsl_type::struct_##NAME##_type =     \
       &glsl_type::_struct_##NAME##_type;
 
diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
index 48d9ea5..7c3c20c 100644
--- a/src/glsl/glsl_types.cpp
+++ b/src/glsl/glsl_types.cpp
@@ -94,12 +94,14 @@ glsl_type::glsl_type(GLenum gl_type, glsl_base_type base_type,
    }
 }
 
-glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
+glsl_type::glsl_type(glsl_base_type base_type,
+                     const glsl_struct_field *fields,
+                     unsigned num_fields, enum glsl_interface_packing packing,
 		     const char *name) :
    gl_type(0),
-   base_type(GLSL_TYPE_STRUCT),
+   base_type(base_type),
    sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
-   sampler_type(0), interface_packing(0),
+   sampler_type(0), interface_packing(packing),
    vector_elements(0), matrix_columns(0),
    length(num_fields)
 {
@@ -127,38 +129,6 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
    mtx_unlock(&glsl_type::mutex);
 }
 
-glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
-		     enum glsl_interface_packing packing, const char *name) :
-   gl_type(0),
-   base_type(GLSL_TYPE_INTERFACE),
-   sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
-   sampler_type(0), interface_packing((unsigned) packing),
-   vector_elements(0), matrix_columns(0),
-   length(num_fields)
-{
-   unsigned int i;
-
-   mtx_lock(&glsl_type::mutex);
-
-   init_ralloc_type_ctx();
-   assert(name != NULL);
-   this->name = ralloc_strdup(this->mem_ctx, name);
-   this->fields.structure = ralloc_array(this->mem_ctx,
-					 glsl_struct_field, length);
-   for (i = 0; i < length; i++) {
-      this->fields.structure[i].type = fields[i].type;
-      this->fields.structure[i].name = ralloc_strdup(this->fields.structure,
-						     fields[i].name);
-      this->fields.structure[i].location = fields[i].location;
-      this->fields.structure[i].interpolation = fields[i].interpolation;
-      this->fields.structure[i].centroid = fields[i].centroid;
-      this->fields.structure[i].sample = fields[i].sample;
-      this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
-   }
-
-   mtx_unlock(&glsl_type::mutex);
-}
-
 
 bool
 glsl_type::contains_sampler() const
@@ -656,7 +626,7 @@ glsl_type::get_array_instance(const glsl_type *base, unsigned array_size,
     * named 'foo'.
     */
    char key[128];
-   snprintf(key, sizeof(key), "%p[%u]", (void *) base, array_size);
+   snprintf(key, sizeof(key), "%p[%u]_%d", (void *) base, array_size, packing);
 
    mtx_lock(&glsl_type::mutex);
 
@@ -769,13 +739,22 @@ glsl_type::record_key_hash(const void *a)
    return retval;
 }
 
+const glsl_type *
+glsl_type::get_record_instance(const glsl_struct_field *fields,
+                               unsigned num_fields,
+                               const char *name)
+{
+   return get_record_instance(fields, num_fields,
+                              GLSL_INTERFACE_PACKING_STD140, name);
+}
 
 const glsl_type *
 glsl_type::get_record_instance(const glsl_struct_field *fields,
-			       unsigned num_fields,
+			       const unsigned num_fields,
+                               enum glsl_interface_packing packing,
 			       const char *name)
 {
-   const glsl_type key(fields, num_fields, name);
+   const glsl_type key(GLSL_TYPE_STRUCT, fields, num_fields, packing, name);
 
    mtx_lock(&glsl_type::mutex);
 
@@ -788,7 +767,8 @@ glsl_type::get_record_instance(const glsl_struct_field *fields,
                                                             &key);
    if (entry == NULL) {
       mtx_unlock(&glsl_type::mutex);
-      const glsl_type *t = new glsl_type(fields, num_fields, name);
+      const glsl_type *t = new glsl_type(GLSL_TYPE_STRUCT, fields, num_fields,
+                                         packing, name);
       mtx_lock(&glsl_type::mutex);
 
       entry = _mesa_hash_table_insert(record_types, t, (void *) t);
@@ -810,7 +790,7 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields,
 				  enum glsl_interface_packing packing,
 				  const char *block_name)
 {
-   const glsl_type key(fields, num_fields, packing, block_name);
+   const glsl_type key(GLSL_TYPE_INTERFACE, fields, num_fields, packing, block_name);
 
    mtx_lock(&glsl_type::mutex);
 
@@ -823,8 +803,8 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields,
                                                             &key);
    if (entry == NULL) {
       mtx_unlock(&glsl_type::mutex);
-      const glsl_type *t = new glsl_type(fields, num_fields,
-                                         packing, block_name);
+      const glsl_type *t = new glsl_type(GLSL_TYPE_INTERFACE, fields,
+                                         num_fields, packing, block_name);
       mtx_lock(&glsl_type::mutex);
 
       entry = _mesa_hash_table_insert(interface_types, t, (void *) t);
diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h
index 0d7126e..72b8f1e 100644
--- a/src/glsl/glsl_types.h
+++ b/src/glsl/glsl_types.h
@@ -249,7 +249,7 @@ struct glsl_type {
    static const glsl_type *get_array_instance(const glsl_type *base,
                                               unsigned elements);
    static const glsl_type *get_array_instance(const glsl_type *base,
-					      unsigned elements,
+                                              unsigned elements,
                                               enum glsl_interface_packing packing);
 
    /**
@@ -258,6 +258,10 @@ struct glsl_type {
    static const glsl_type *get_record_instance(const glsl_struct_field *fields,
 					       unsigned num_fields,
 					       const char *name);
+   static const glsl_type *get_record_instance(const glsl_struct_field *fields,
+                                               const unsigned num_fields,
+                                               enum glsl_interface_packing packing,
+                                               const char *name);
 
    /**
     * Get the instance of an interface block type
@@ -684,13 +688,10 @@ private:
 	     enum glsl_sampler_dim dim, bool shadow, bool array,
 	     unsigned type, const char *name);
 
-   /** Constructor for record types */
-   glsl_type(const glsl_struct_field *fields, unsigned num_fields,
-	     const char *name);
-
-   /** Constructor for interface types */
-   glsl_type(const glsl_struct_field *fields, unsigned num_fields,
-	     enum glsl_interface_packing packing, const char *name);
+   /** Constructor for interface and record types */
+   glsl_type(glsl_base_type base_type, const glsl_struct_field *fields,
+             unsigned num_fields, enum glsl_interface_packing packing,
+             const char *name);
 
    /** Constructor for array types */
    glsl_type(const glsl_type *array, unsigned length,
-- 
1.9.1



More information about the mesa-dev mailing list