[Mesa-dev] [PATCH 7/9] glsl: Aggregate initializer support for arrays of array

Timothy Arceri t_arceri at yahoo.com.au
Wed Jan 15 22:27:28 PST 2014


Signed-off-by: Timothy Arceri <t_arceri at yahoo.com.au>
---
 src/glsl/ast.h                  | 19 +++++++++++-
 src/glsl/ast_function.cpp       | 15 +++++++--
 src/glsl/ast_to_hir.cpp         | 31 +++++++++++++++---
 src/glsl/glsl_parser.yy         | 36 ++++++++++++++++++++-
 src/glsl/glsl_parser_extras.cpp | 69 +++++++++++++++++++++++++++++++----------
 5 files changed, 144 insertions(+), 26 deletions(-)

diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index bbae9cd..3ec8b75 100644
--- a/src/glsl/ast.h
+++ b/src/glsl/ast.h
@@ -308,10 +308,16 @@ public:
       : ast_expression(ast_aggregate, NULL, NULL, NULL),
         constructor_type(NULL)
    {
-      /* empty */
+      array_dimension = 1;
+      is_array = false;
    }
 
    ast_type_specifier *constructor_type;
+   unsigned array_dimension;
+
+   ast_array_specifier *array_specifier;
+   bool is_array;
+
    virtual ir_rvalue *hir(exec_list *instructions,
                           struct _mesa_glsl_parse_state *state);
 };
@@ -587,6 +593,11 @@ public:
 				     struct _mesa_glsl_parse_state *state)
       const;
 
+   const struct glsl_type *glsl_type(const char **name,
+                                     struct _mesa_glsl_parse_state *state,
+                                     bool skip_outer_dimension)
+      const;
+
    virtual void print(void) const;
 
    ir_rvalue *hir(exec_list *, struct _mesa_glsl_parse_state *);
@@ -1004,4 +1015,10 @@ extern void
 check_builtin_array_max_size(const char *name, unsigned size,
                              YYLTYPE loc, struct _mesa_glsl_parse_state *state);
 
+extern const glsl_type *
+process_array_type_skip_dim(YYLTYPE *loc, const glsl_type *base,
+                            ast_array_specifier *array_specifier,
+		            struct _mesa_glsl_parse_state *state,
+                            bool skip_first_dim);
+
 #endif /* AST_H */
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 57aa45f..f60cd19 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -1731,8 +1731,19 @@ ast_aggregate_initializer::hir(exec_list *instructions,
       _mesa_glsl_error(&loc, state, "type of C-style initializer unknown");
       return ir_rvalue::error_value(ctx);
    }
-   const glsl_type *const constructor_type =
-      this->constructor_type->glsl_type(&name, state);
+   const glsl_type *constructor_type =
+      this->constructor_type->glsl_type(&name, state,
+                                        this->array_dimension > 1 && !this->is_array);
+
+   /* This only handles "vec4 foo[..]".  The earlier constructor_type->glsl_type(...)
+    * call already handled the "vec4[..] foo" case.
+    */
+   if (this->is_array) {
+      constructor_type =
+         process_array_type_skip_dim(&loc, constructor_type,
+                                     this->array_specifier, state,
+                                     this->array_dimension > 1);
+   }
 
    if (!state->ARB_shading_language_420pack_enable) {
       _mesa_glsl_error(&loc, state, "C-style initialization requires the "
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 359a0b8..3054b9c 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -1817,10 +1817,11 @@ process_array_size(exec_node *node,
    return result;
 }
 
-static const glsl_type *
-process_array_type(YYLTYPE *loc, const glsl_type *base,
-                   ast_array_specifier *array_specifier,
-                   struct _mesa_glsl_parse_state *state)
+const glsl_type *
+process_array_type_skip_dim(YYLTYPE *loc, const glsl_type *base,
+                            ast_array_specifier *array_specifier,
+                            struct _mesa_glsl_parse_state *state,
+                            bool skip_first_dim)
 {
    const glsl_type *array_type = NULL;
    const glsl_type *element_type = base;
@@ -1871,6 +1872,8 @@ process_array_type(YYLTYPE *loc, const glsl_type *base,
 
       unsigned array_size;
       for (/* nothing */; !node->is_head_sentinel(); node = node->prev) {
+         if (skip_first_dim && node->prev->is_head_sentinel())
+            break;
          array_size = process_array_size(node, state);
          array_type_temp = glsl_type::get_array_instance(array_type_temp,
                                                          array_size,
@@ -1898,10 +1901,27 @@ process_array_type(YYLTYPE *loc, const glsl_type *base,
    return array_type != NULL ? array_type : glsl_type::error_type;
 }
 
+static const glsl_type *
+process_array_type(YYLTYPE *loc, const glsl_type *base,
+                   ast_array_specifier *array_specifier,
+                   struct _mesa_glsl_parse_state *state)
+{
+   return process_array_type_skip_dim(loc, base, array_specifier,
+                                      state, false);
+}
+
 const glsl_type *
 ast_type_specifier::glsl_type(const char **name,
 			      struct _mesa_glsl_parse_state *state) const
 {
+   return this->glsl_type(name, state, false);
+}
+
+const glsl_type *
+ast_type_specifier::glsl_type(const char **name,
+			      struct _mesa_glsl_parse_state *state,
+                              bool skip_outer_dim) const
+{
    const struct glsl_type *type;
 
    type = state->symbols->get_type(this->type_name);
@@ -1909,7 +1929,8 @@ ast_type_specifier::glsl_type(const char **name,
 
    if (this->is_array) {
       YYLTYPE loc = this->get_location();
-      type = process_array_type(&loc, type, this->array_specifier, state);
+      type = process_array_type_skip_dim(&loc, type, this->array_specifier,
+                                         state, skip_outer_dim);
    }
 
    return type;
diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
index 6d63668..9461e73 100644
--- a/src/glsl/glsl_parser.yy
+++ b/src/glsl/glsl_parser.yy
@@ -1007,6 +1007,23 @@ init_declarator_list:
       if ($6->oper == ast_aggregate) {
          ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$6;
          ast_type_specifier *type = new(ctx) ast_type_specifier($1->type->specifier, true, $4);
+         if ($1->type->specifier->array_specifier != NULL) {
+            ai->array_specifier = $4;
+            ai->is_array = true;
+
+            type =
+             new(ctx) ast_type_specifier($1->type->specifier,
+                                         $1->type->specifier->is_array,
+                                         $1->type->specifier->array_specifier);
+         } else {
+            ai->array_specifier = NULL;
+            ai->is_array = false;
+
+            type =
+             new(ctx) ast_type_specifier($1->type->specifier,
+                                         true,
+                                         $4);
+         }
          _mesa_ast_set_aggregate_type(type, ai, state);
       }
    }
@@ -1063,7 +1080,24 @@ single_declaration:
       $$->declarations.push_tail(&decl->link);
       if ($5->oper == ast_aggregate) {
          ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$5;
-         ast_type_specifier *type = new(ctx) ast_type_specifier($1->specifier, true, $3);
+         ast_type_specifier *type;
+         if ($1->specifier->array_specifier != NULL) {
+            ai->array_specifier = $3;
+            ai->is_array = true;
+
+            type =
+             new(ctx) ast_type_specifier($1->specifier,
+                                         $1->specifier->is_array,
+                                         $1->specifier->array_specifier);
+         } else {
+            ai->array_specifier = NULL;
+            ai->is_array = false;
+
+            type =
+             new(ctx) ast_type_specifier($1->specifier,
+                                         true,
+                                         $3);
+         }
          _mesa_ast_set_aggregate_type(type, ai, state);
       }
    }
diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
index 92076b5..0ea8f62 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -720,16 +720,26 @@ _mesa_ast_set_aggregate_type(const ast_type_specifier *type,
 
    /* If the aggregate is an array, recursively set its elements' types. */
    if (type->is_array) {
-      /* We want to set the element type which is not an array itself, so make
-       * a copy of the array type and set its is_array field to false.
-       *
-       * E.g., if <type> if struct S[2] we want to set each element's type to
-       * struct S.
-       *
-       * FINISHME: Update when ARB_array_of_arrays is supported.
-       */
-      const ast_type_specifier *non_array_type =
-         new(ctx) ast_type_specifier(type, false, NULL);
+
+      const ast_type_specifier *element_type;
+      unsigned dimension_count = type->array_specifier->dimension_count;
+
+      if (ai->is_array)
+         dimension_count += ai->array_specifier->dimension_count;
+
+      if (dimension_count == ai->array_dimension ||
+          !state->ARB_arrays_of_arrays_enable) {
+
+         /* We want to set the element type which is not an array itself, so make
+          * a copy of the array type and set its is_array field to false.
+          *
+          * E.g., if <type> if struct S[2] we want to set each element's type to
+          * struct S.
+          */
+         element_type = new(ctx) ast_type_specifier(type, false, NULL);
+      } else {
+         element_type = type;
+      }
 
       for (exec_node *expr_node = ai->expressions.head;
            !expr_node->is_tail_sentinel();
@@ -737,8 +747,23 @@ _mesa_ast_set_aggregate_type(const ast_type_specifier *type,
          ast_expression *expr = exec_node_data(ast_expression, expr_node,
                                                link);
 
-         if (expr->oper == ast_aggregate)
-            _mesa_ast_set_aggregate_type(non_array_type, expr, state);
+         if (expr->oper == ast_aggregate) {
+            /* copy some values needed to process initialization of
+             * arrays of arrays e.g
+             * vec4[2] a[2] = {
+             *    { vec4(1.0), vec4(1.0) },
+             *    { vec4(1.0), vec4(1.0) }};
+             */
+            ast_aggregate_initializer *sub_ai = (ast_aggregate_initializer *)expr;
+            if (ai->array_dimension != dimension_count) {
+               sub_ai->array_dimension = ai->array_dimension + 1;
+               if (ai->is_array) {
+                  sub_ai->is_array = ai->is_array;
+                  sub_ai->array_specifier = ai->array_specifier;
+               }
+            }
+            _mesa_ast_set_aggregate_type(element_type, (ast_expression *)sub_ai, state);
+         }
       }
 
    /* If the aggregate is a struct, recursively set its fields' types. */
@@ -770,6 +795,7 @@ _mesa_ast_set_aggregate_type(const ast_type_specifier *type,
                                                   link);
 
             bool is_array = decl_list->type->specifier->is_array;
+            bool set_aggr_array = false;
             ast_array_specifier *array_specifier = decl_list->type->specifier->array_specifier;
 
             /* Recognize variable declarations with the bracketed size attached
@@ -778,12 +804,16 @@ _mesa_ast_set_aggregate_type(const ast_type_specifier *type,
              *     float a[2];
              *     float[2] b;
              *
-             * are both arrays, but <a>'s array_specifier is decl->array_specifier, while
-             * <b>'s array_specifier is decl_list->type->specifier->array_specifier.
+             * are both arrays, but <a>'s array_specifier is
+             * decl->array_specifier, while <b>'s array_specifier is
+             * decl_list->type->specifier->array_specifier.
              */
             if (!is_array) {
                is_array = decl->is_array;
                array_specifier = decl->array_specifier;
+            } else if (decl_list->type->specifier->is_array &&
+                       state->ARB_arrays_of_arrays_enable) {
+               set_aggr_array = true;
             }
 
             /* Declaration shadows the <type> parameter. */
@@ -791,8 +821,14 @@ _mesa_ast_set_aggregate_type(const ast_type_specifier *type,
                new(ctx) ast_type_specifier(decl_list->type->specifier,
                                            is_array, array_specifier);
 
-            if (expr->oper == ast_aggregate)
-               _mesa_ast_set_aggregate_type(type, expr, state);
+            if (expr->oper == ast_aggregate) {
+               ast_aggregate_initializer *sub_ai = (ast_aggregate_initializer *)expr;
+               if (set_aggr_array) {
+                  sub_ai->is_array = decl->is_array;
+                  sub_ai->array_specifier = decl->array_specifier;
+               }
+               _mesa_ast_set_aggregate_type(type, (ast_expression *)sub_ai, state);
+            }
          }
       }
    } else {
@@ -819,7 +855,6 @@ _mesa_ast_set_aggregate_type(const ast_type_specifier *type,
    }
 }
 
-
 void
 _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
 {
-- 
1.8.3.1



More information about the mesa-dev mailing list