glsl: Parse interface array size
authorIan Romanick <ian.d.romanick@intel.com>
Tue, 11 Dec 2012 20:13:30 +0000 (12:13 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 25 Jan 2013 14:07:33 +0000 (09:07 -0500)
The size is parsed and stored in the AST, but it is not used yet.
Processing of the array size is added in the patch "glsl: Handle
instance array declarations"

v2: Update the commit message (suggested by Carl Worth).  Add a comment
to ast_uniform_block::array_size (suggested by Paul Berry).

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Chad Versace <chad.versace@linux.intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/glsl/ast.h
src/glsl/glsl_parser.yy

index 7d7f72d..1a28963 100644 (file)
@@ -804,12 +804,12 @@ public:
 class ast_uniform_block : public ast_node {
 public:
    ast_uniform_block(ast_type_qualifier layout,
-                    const char *block_name,
-                    ast_declarator_list *member_list,
-                     const char *instance_name)
-   : layout(layout), block_name(block_name), instance_name(instance_name)
+                     const char *instance_name,
+                    ast_expression *array_size)
+   : layout(layout), block_name(NULL), instance_name(instance_name),
+     array_size(array_size)
    {
-      declarations.push_degenerate_list_at_head(&member_list->link);
+      /* empty */
    }
 
    virtual ir_rvalue *hir(exec_list *instructions,
@@ -828,6 +828,17 @@ public:
 
    /** List of ast_declarator_list * */
    exec_list declarations;
+
+   /**
+    * Declared array size of the block instance
+    *
+    * If the block is not declared as an array, this field will be \c NULL.
+    *
+    * \note
+    * A block can only be an array if it also has an instance name.  If this
+    * field is not \c NULL, ::instance_name must also not be \c NULL.
+    */
+   ast_expression *array_size;
 };
 /*@}*/
 
index 81ae5d5..154ce2d 100644 (file)
@@ -79,6 +79,7 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg)
    ast_case_label_list *case_label_list;
    ast_case_statement *case_statement;
    ast_case_statement_list *case_statement_list;
+   ast_uniform_block *uniform_block;
 
    struct {
       ast_node *cond;
@@ -112,7 +113,7 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg)
 %token STRUCT VOID_TOK WHILE
 %token <identifier> IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER
 %type <identifier> any_identifier
-%type <identifier> instance_name_opt
+%type <uniform_block> instance_name_opt
 %token <real> FLOATCONSTANT
 %token <n> INTCONSTANT UINTCONSTANT BOOLCONSTANT
 %token <identifier> FIELD_SELECTION
@@ -221,7 +222,8 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg)
 %type <node> declaration
 %type <node> declaration_statement
 %type <node> jump_statement
-%type <node> uniform_block basic_uniform_block
+%type <node> uniform_block
+%type <uniform_block> basic_uniform_block
 %type <struct_specifier> struct_specifier
 %type <declarator_list> struct_declaration_list
 %type <declarator_list> struct_declaration
@@ -1891,7 +1893,7 @@ uniform_block:
        }
        | layout_qualifier basic_uniform_block
        {
-          ast_uniform_block *block = (ast_uniform_block *) $2;
+          ast_uniform_block *block = $2;
           if (!block->layout.merge_qualifier(& @1, state, $1)) {
              YYERROR;
           }
@@ -1902,9 +1904,10 @@ uniform_block:
 basic_uniform_block:
        UNIFORM NEW_IDENTIFIER '{' member_list '}' instance_name_opt ';'
        {
-          void *ctx = state;
-          $$ = new(ctx) ast_uniform_block(*state->default_uniform_qualifier,
-                                          $2, $4, $6);
+          ast_uniform_block *const block = $6;
+
+          block->block_name = $2;
+          block->declarations.push_degenerate_list_at_head(& $4->link);
 
           if (!state->ARB_uniform_buffer_object_enable) {
              _mesa_glsl_error(& @1, state,
@@ -1915,21 +1918,49 @@ basic_uniform_block:
                                 "#version 140 / GL_ARB_uniform_buffer_object "
                                 "required for defining uniform blocks\n");
           }
+
+          /* Since block arrays require names, and both features are added in
+           * the same language versions, we don't have to explicitly
+           * version-check both things.
+           */
+          if (block->instance_name != NULL
+              && !(state->language_version == 300 && state->es_shader)) {
+             _mesa_glsl_error(& @1, state,
+                              "#version 300 es required for using uniform "
+                              "blocks with an instance name\n");
+          }
+
+          $$ = block;
        }
        ;
 
 instance_name_opt:
        /* empty */
        {
-          $$ = NULL;
+          $$ = new(state) ast_uniform_block(*state->default_uniform_qualifier,
+                                            NULL,
+                                            NULL);
        }
        | NEW_IDENTIFIER
        {
-          if (!(state->language_version == 300 && state->es_shader)) {
-             _mesa_glsl_error(& @1, state,
-                              "#version 300 es required for using uniform "
-                              "blocks with an instance name\n");
-          }
+          $$ = new(state) ast_uniform_block(*state->default_uniform_qualifier,
+                                            $1,
+                                            NULL);
+       }
+       | NEW_IDENTIFIER '[' constant_expression ']'
+       {
+          $$ = new(state) ast_uniform_block(*state->default_uniform_qualifier,
+                                            $1,
+                                            $3);
+       }
+       | NEW_IDENTIFIER '[' ']'
+       {
+          _mesa_glsl_error(& @1, state,
+                           "instance block arrays must be explicitly sized\n");
+
+          $$ = new(state) ast_uniform_block(*state->default_uniform_qualifier,
+                                            $1,
+                                            NULL);
        }
        ;