glsl: Add parsing for GLSL uniform blocks.
authorEric Anholt <eric@anholt.net>
Wed, 18 Apr 2012 20:35:56 +0000 (13:35 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 9 Jul 2012 18:13:33 +0000 (11:13 -0700)
This doesn't do anything with the uniform block declarations yet, so
usage of those uniforms finds them to be undeclared.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/glsl/ast.h
src/glsl/ast_to_hir.cpp
src/glsl/glsl_lexer.ll
src/glsl/glsl_parser.yy

index 7538b58e4602aa5fe4a6abb11309df412e44973b..4438b85bbdafb6db037eaca4c4dd5396cc5895f0 100644 (file)
@@ -376,6 +376,15 @@ struct ast_type_qualifier {
          unsigned depth_less:1;
          unsigned depth_unchanged:1;
          /** \} */
+
+        /** \name Layout qualifiers for GL_ARB_uniform_buffer_object */
+        /** \{ */
+         unsigned std140:1;
+         unsigned shared:1;
+         unsigned packed:1;
+         unsigned column_major:1;
+         unsigned row_major:1;
+        /** \} */
       }
       /** \brief Set of flags, accessed by name. */
       q;
@@ -762,6 +771,25 @@ public:
    ast_function *prototype;
    ast_compound_statement *body;
 };
+
+class ast_uniform_block : public ast_node {
+public:
+   ast_uniform_block(ast_type_qualifier layout,
+                    const char *block_name,
+                    ast_declarator_list *member_list)
+   : layout(layout), block_name(block_name)
+   {
+      declarations.push_degenerate_list_at_head(&member_list->link);
+   }
+
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
+   ast_type_qualifier layout;
+   const char *block_name;
+   /** List of ast_declarator_list * */
+   exec_list declarations;
+};
 /*@}*/
 
 extern void
index 15aa88ea9ef2d1ac0d4fa03f7851f05069f425b8..bbe8f0596f957dbf5ee6bf69378a4445265e3c0f 100644 (file)
@@ -3989,6 +3989,17 @@ ast_struct_specifier::hir(exec_list *instructions,
    return NULL;
 }
 
+ir_rvalue *
+ast_uniform_block::hir(exec_list *instructions,
+                      struct _mesa_glsl_parse_state *state)
+{
+   /* The ast_uniform_block has a list of ast_declarator_lists.  We
+    * need to turn those into ir_variables with an association
+    * with this uniform block.
+    */
+   return NULL;
+}
+
 static void
 detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
                               exec_list *instructions)
index 2028d7f47683799b24390adb04219f79daa4814d..24cda0c45eae6242792474a6ce29ca7e1d9037d0 100644 (file)
@@ -312,6 +312,7 @@ layout              {
                      || yyextra->AMD_conservative_depth_enable
                      || yyextra->ARB_conservative_depth_enable
                      || yyextra->ARB_explicit_attrib_location_enable
+                     || yyextra->ARB_uniform_buffer_object_enable
                      || yyextra->ARB_fragment_coord_conventions_enable) {
                      return LAYOUT_TOK;
                   } else {
@@ -392,7 +393,7 @@ enum                KEYWORD(110 || ES, 999, ENUM);
 typedef                KEYWORD(110 || ES, 999, TYPEDEF);
 template       KEYWORD(110 || ES, 999, TEMPLATE);
 this           KEYWORD(110 || ES, 999, THIS);
-packed         KEYWORD(110 || ES, 999, PACKED_TOK);
+packed         KEYWORD(110 || ES, 140 || yyextra->ARB_uniform_buffer_object_enable, PACKED_TOK);
 goto           KEYWORD(110 || ES, 999, GOTO);
 switch         KEYWORD(110 || ES, 130, SWITCH);
 default                KEYWORD(110 || ES, 130, DEFAULT);
@@ -468,7 +469,7 @@ image2DArrayShadow KEYWORD(130, 999, IMAGE2DARRAYSHADOW);
 imageBuffer    KEYWORD(130, 999, IMAGEBUFFER);
 iimageBuffer   KEYWORD(130, 999, IIMAGEBUFFER);
 uimageBuffer   KEYWORD(130, 999, UIMAGEBUFFER);
-row_major      KEYWORD(130, 999, ROW_MAJOR);
+row_major      KEYWORD(130, 140 || yyextra->ARB_uniform_buffer_object_enable, ROW_MAJOR);
 
     /* Additional reserved words in GLSL 1.40 */
 isampler2DRect KEYWORD(140, 140, ISAMPLER2DRECT);
index 8759863271e14e2b00bee0e53ac0dd0e0a01363c..3373375911b76c3eb84a8ab147bfd449a7a37e74 100644 (file)
@@ -155,6 +155,7 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg)
 %type <type_qualifier> interpolation_qualifier
 %type <type_qualifier> layout_qualifier
 %type <type_qualifier> layout_qualifier_id_list layout_qualifier_id
+%type <type_qualifier> uniform_block_layout_qualifier
 %type <type_specifier> type_specifier
 %type <type_specifier> type_specifier_no_prec
 %type <type_specifier> type_specifier_nonarray
@@ -213,11 +214,14 @@ 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
 %type <struct_specifier> struct_specifier
 %type <declarator_list> struct_declaration_list
 %type <declarator_list> struct_declaration
 %type <declaration> struct_declarator
 %type <declaration> struct_declarator_list
+%type <declarator_list> member_list
+%type <declarator_list> member_declaration
 %type <node> selection_statement
 %type <selection_rest_statement> selection_rest_statement
 %type <node> switch_statement
@@ -800,6 +804,10 @@ declaration:
           $3->is_precision_statement = true;
           $$ = $3;
        }
+       | uniform_block
+       {
+          $$ = $1;
+       }
        ;
 
 function_prototype:
@@ -1157,6 +1165,23 @@ layout_qualifier_id:
              }
           }
 
+          /* See also uniform_block_layout_qualifier. */
+          if (!$$.flags.i && state->ARB_uniform_buffer_object_enable) {
+             if (strcmp($1, "std140") == 0) {
+                $$.flags.q.std140 = 1;
+             } else if (strcmp($1, "shared") == 0) {
+                $$.flags.q.shared = 1;
+             } else if (strcmp($1, "column_major") == 0) {
+                $$.flags.q.column_major = 1;
+             }
+
+             if ($$.flags.i && state->ARB_uniform_buffer_object_warn) {
+                _mesa_glsl_warning(& @1, state,
+                                   "#version 140 / GL_ARB_uniform_buffer_object "
+                                   "layout qualifier `%s' is used\n", $1);
+             }
+          }
+
           if (!$$.flags.i) {
              _mesa_glsl_error(& @1, state, "unrecognized layout identifier "
                               "`%s'\n", $1);
@@ -1209,6 +1234,38 @@ layout_qualifier_id:
                                 "identifier `%s' used\n", $1);
           }
        }
+       | uniform_block_layout_qualifier
+       {
+          $$ = $1;
+          /* Layout qualifiers for ARB_uniform_buffer_object. */
+          if (!state->ARB_uniform_buffer_object_enable) {
+             _mesa_glsl_error(& @1, state,
+                              "#version 140 / GL_ARB_uniform_buffer_object "
+                              "layout qualifier `%s' is used\n", $1);
+          } else if (state->ARB_uniform_buffer_object_warn) {
+             _mesa_glsl_warning(& @1, state,
+                                "#version 140 / GL_ARB_uniform_buffer_object "
+                                "layout qualifier `%s' is used\n", $1);
+          }
+       }
+       ;
+
+/* This is a separate language rule because we parse these as tokens
+ * (due to them being reserved keywords) instead of identifiers like
+ * most qualifiers.  See the any_identifier path of
+ * layout_qualifier_id for the others.
+ */
+uniform_block_layout_qualifier:
+       ROW_MAJOR
+       {
+          memset(& $$, 0, sizeof($$));
+          $$.flags.q.row_major = 1;
+       }
+       | PACKED_TOK
+       {
+          memset(& $$, 0, sizeof($$));
+          $$.flags.q.packed = 1;
+       }
        ;
 
 interpolation_qualifier:
@@ -1862,3 +1919,68 @@ function_definition:
           state->symbols->pop_scope();
        }
        ;
+
+/* layout_qualifieropt is packed into this rule */
+uniform_block:
+       UNIFORM NEW_IDENTIFIER '{' member_list '}' ';'
+       {
+          void *ctx = state;
+          ast_type_qualifier no_qual;
+          memset(&no_qual, 0, sizeof(no_qual));
+          $$ = new(ctx) ast_uniform_block(no_qual, $2, $4);
+       }
+       | layout_qualifier UNIFORM NEW_IDENTIFIER '{' member_list '}' ';'
+       {
+          void *ctx = state;
+          $$ = new(ctx) ast_uniform_block($1, $3, $5);
+       }
+       ;
+
+member_list:
+       member_declaration
+       {
+          $$ = $1;
+          $1->link.self_link();
+       }
+       | member_declaration member_list
+       {
+          $$ = $1;
+          $2->link.insert_before(& $$->link);
+       }
+       ;
+
+/* Specifying "uniform" inside of a uniform block is redundant. */
+uniformopt:
+       /* nothing */
+       | UNIFORM
+       ;
+
+member_declaration:
+       layout_qualifier uniformopt type_specifier struct_declarator_list ';'
+       {
+          void *ctx = state;
+          ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
+          type->set_location(yylloc);
+
+          type->qualifier = $1;
+          type->qualifier.flags.q.uniform = true;
+          type->specifier = $3;
+          $$ = new(ctx) ast_declarator_list(type);
+          $$->set_location(yylloc);
+
+          $$->declarations.push_degenerate_list_at_head(& $4->link);
+       }
+       | uniformopt type_specifier struct_declarator_list ';'
+       {
+          void *ctx = state;
+          ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
+          type->set_location(yylloc);
+
+          type->qualifier.flags.q.uniform = true;
+          type->specifier = $2;
+          $$ = new(ctx) ast_declarator_list(type);
+          $$->set_location(yylloc);
+
+          $$->declarations.push_degenerate_list_at_head(& $3->link);
+       }
+       ;