glsl: Add support for default layout qualifiers for uniforms.
authorEric Anholt <eric@anholt.net>
Fri, 22 Jun 2012 20:36:35 +0000 (13:36 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 31 Jul 2012 19:06:20 +0000 (12:06 -0700)
I ended up having to add rallocing of the ast_type_qualifier in order
to avoid pulling in ast.h for glsl_parser_extras.h, because I wanted
to track an ast_type_qualifier in the state.

Fixes piglit ARB_uniform_buffer_object/row-major.

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

index de3f2df..5074782 100644 (file)
@@ -338,6 +338,25 @@ enum {
 };
 
 struct ast_type_qualifier {
+   /* Callers of this ralloc-based new need not call delete. It's
+    * easier to just ralloc_free 'ctx' (or any of its ancestors). */
+   static void* operator new(size_t size, void *ctx)
+   {
+      void *node;
+
+      node = rzalloc_size(ctx, size);
+      assert(node != NULL);
+
+      return node;
+   }
+
+   /* If the user *does* call delete, that's OK, we will just
+    * ralloc_free in that case. */
+   static void operator delete(void *table)
+   {
+      ralloc_free(table);
+   }
+
    union {
       struct {
         unsigned invariant:1;
@@ -424,6 +443,10 @@ struct ast_type_qualifier {
     * returned string is undefined but not null.
     */
    const char *interpolation_string() const;
+
+   bool merge_qualifier(YYLTYPE *loc,
+                       _mesa_glsl_parse_state *state,
+                       ast_type_qualifier q);
 };
 
 class ast_declarator_list;
index 6c44f8c..29493e2 100644 (file)
@@ -71,3 +71,48 @@ ast_type_qualifier::interpolation_string() const
    else
       return NULL;
 }
+
+bool
+ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
+                                   _mesa_glsl_parse_state *state,
+                                   ast_type_qualifier q)
+{
+   ast_type_qualifier ubo_mat_mask;
+   ubo_mat_mask.flags.i = 0;
+   ubo_mat_mask.flags.q.row_major = 1;
+   ubo_mat_mask.flags.q.column_major = 1;
+
+   ast_type_qualifier ubo_layout_mask;
+   ubo_layout_mask.flags.i = 0;
+   ubo_layout_mask.flags.q.std140 = 1;
+   ubo_layout_mask.flags.q.packed = 1;
+   ubo_layout_mask.flags.q.shared = 1;
+
+   /* Uniform block layout qualifiers get to overwrite each
+    * other (rightmost having priority), while all other
+    * qualifiers currently don't allow duplicates.
+    */
+
+   if ((this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i |
+                                     ubo_layout_mask.flags.i)) != 0) {
+      _mesa_glsl_error(loc, state,
+                      "duplicate layout qualifiers used\n");
+      return false;
+   }
+
+   if ((q.flags.i & ubo_mat_mask.flags.i) != 0)
+      this->flags.i &= ~ubo_mat_mask.flags.i;
+   if ((q.flags.i & ubo_layout_mask.flags.i) != 0)
+      this->flags.i &= ~ubo_layout_mask.flags.i;
+
+   this->flags.i |= q.flags.i;
+
+   if (q.flags.q.explicit_location)
+      this->location = q.location;
+
+   if (q.flags.q.explicit_index)
+      this->index = q.index;
+
+   return true;
+}
+
index ba21b54..04c64f0 100644 (file)
@@ -1113,42 +1113,10 @@ layout_qualifier_id_list:
        layout_qualifier_id
        | layout_qualifier_id_list ',' layout_qualifier_id
        {
-          ast_type_qualifier ubo_mat_mask;
-          ubo_mat_mask.flags.i = 0;
-          ubo_mat_mask.flags.q.row_major = 1;
-          ubo_mat_mask.flags.q.column_major = 1;
-
-          ast_type_qualifier ubo_layout_mask;
-          ubo_layout_mask.flags.i = 0;
-          ubo_layout_mask.flags.q.std140 = 1;
-          ubo_layout_mask.flags.q.packed = 1;
-          ubo_layout_mask.flags.q.shared = 1;
-
-          /* Uniform block layout qualifiers get to overwrite each
-           * other (rightmost having priority), while all other
-           * qualifiers currently don't allow duplicates.
-           */
-          if (($1.flags.i & $3.flags.i & ~(ubo_mat_mask.flags.i |
-                                           ubo_layout_mask.flags.i)) != 0) {
-             _mesa_glsl_error(& @3, state,
-                              "duplicate layout qualifiers used\n");
+          $$ = $1;
+          if (!$$.merge_qualifier(& @3, state, $3)) {
              YYERROR;
           }
-
-          $$ = $1;
-
-          if (($3.flags.i & ubo_mat_mask.flags.i) != 0)
-             $$.flags.i &= ~ubo_mat_mask.flags.i;
-          if (($3.flags.i & ubo_layout_mask.flags.i) != 0)
-             $$.flags.i &= ~ubo_layout_mask.flags.i;
-
-          $$.flags.i |= $3.flags.i;
-
-          if ($3.flags.q.explicit_location)
-             $$.location = $3.location;
-
-          if ($3.flags.q.explicit_index)
-             $$.index = $3.index;
        }
        ;
 
@@ -1938,6 +1906,7 @@ external_declaration:
        function_definition     { $$ = $1; }
        | declaration           { $$ = $1; }
        | pragma_statement      { $$ = NULL; }
+       | layout_defaults       { $$ = NULL; }
        ;
 
 function_definition:
@@ -1958,14 +1927,18 @@ 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);
+          $$ = new(ctx) ast_uniform_block(*state->default_uniform_qualifier,
+                                          $2, $4);
        }
        | layout_qualifier UNIFORM NEW_IDENTIFIER '{' member_list '}' ';'
        {
           void *ctx = state;
-          $$ = new(ctx) ast_uniform_block($1, $3, $5);
+
+          ast_type_qualifier qual = *state->default_uniform_qualifier;
+          if (!qual.merge_qualifier(& @1, state, $1)) {
+             YYERROR;
+          }
+          $$ = new(ctx) ast_uniform_block(qual, $3, $5);
        }
        ;
 
@@ -2019,3 +1992,12 @@ member_declaration:
           $$->declarations.push_degenerate_list_at_head(& $3->link);
        }
        ;
+
+layout_defaults:
+       layout_qualifier UNIFORM ';'
+       {
+          if (!state->default_uniform_qualifier->merge_qualifier(& @1, state,
+                                                                 $1)) {
+             YYERROR;
+          }
+       }
index 4e1f332..09e1e59 100644 (file)
@@ -107,6 +107,10 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
 
    if (ctx->Const.ForceGLSLExtensionsWarn)
       _mesa_glsl_process_extension("all", NULL, "warn", NULL, this);
+
+   this->default_uniform_qualifier = new(this) ast_type_qualifier();
+   this->default_uniform_qualifier->flags.q.shared = 1;
+   this->default_uniform_qualifier->flags.q.column_major = 1;
 }
 
 const char *
index bdb5b67..c0a96c7 100644 (file)
@@ -92,6 +92,13 @@ struct _mesa_glsl_parse_state {
    enum _mesa_glsl_parser_targets target;
 
    /**
+    * Default uniform layout qualifiers tracked during parsing.
+    * Currently affects uniform blocks and uniform buffer variables in
+    * those blocks.
+    */
+   class ast_type_qualifier *default_uniform_qualifier;
+
+   /**
     * Printable list of GLSL versions supported by the current context
     *
     * \note