glsl: allow multiple layout qualifiers for a single declaration
authorTimothy Arceri <timothy.arceri@collabora.com>
Fri, 15 Jan 2016 01:43:10 +0000 (12:43 +1100)
committerTimothy Arceri <timothy.arceri@collabora.com>
Tue, 19 Jan 2016 21:06:50 +0000 (08:06 +1100)
From the ARB_shading_language_420pack spec:

   "More than one layout qualifier may appear in a single
   declaration. If the same layout-qualifier-name occurs in
   multiple layout qualifiers for the same declaration, the
   last one overrides the former ones."

The parser was already failing correctly when the extension is
not available but testing for duplicates within a single layout
qualifier was still causing this to fail when available as both
cases share the same function for merging.

Here we add a parameter to differentiate between the two uses
and apply it to the duplicate test.

Acked-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Chris Forbes <chrisf@ijw.co.nz>
src/glsl/ast.h
src/glsl/ast_type.cpp
src/glsl/glsl_parser.yy

index 465166994eabcf06f285e67a8b47e62d9dd692a6..03df6c08b2bf1905abb67fa001c78660d55fcef8 100644 (file)
@@ -699,7 +699,8 @@ struct ast_type_qualifier {
 
    bool merge_qualifier(YYLTYPE *loc,
                        _mesa_glsl_parse_state *state,
-                       const ast_type_qualifier &q);
+                        const ast_type_qualifier &q,
+                        bool is_single_layout_merge);
 
    bool merge_out_qualifier(YYLTYPE *loc,
                            _mesa_glsl_parse_state *state,
index 32cb0a0319cd8822df80acb92fbd9e1a12030665..cf494d96724549d91b468c1f6f68293d8e04b767 100644 (file)
@@ -114,10 +114,16 @@ ast_type_qualifier::interpolation_string() const
       return NULL;
 }
 
+/**
+ * This function merges both duplicate identifies within a single layout and
+ * multiple layout qualifiers on a single variable declaration. The
+ * is_single_layout_merge param is used differentiate between the two.
+ */
 bool
 ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
                                    _mesa_glsl_parse_state *state,
-                                   const ast_type_qualifier &q)
+                                    const ast_type_qualifier &q,
+                                    bool is_single_layout_merge)
 {
    ast_type_qualifier ubo_mat_mask;
    ubo_mat_mask.flags.i = 0;
@@ -157,7 +163,7 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
       allowed_duplicates_mask.flags.i |=
          stream_layout_mask.flags.i;
 
-   if (!state->has_enhanced_layouts() &&
+   if (is_single_layout_merge && !state->has_enhanced_layouts() &&
        (this->flags.i & q.flags.i & ~allowed_duplicates_mask.flags.i) != 0) {
       _mesa_glsl_error(loc, state,
                       "duplicate layout qualifiers used");
@@ -294,7 +300,7 @@ ast_type_qualifier::merge_out_qualifier(YYLTYPE *loc,
                                         ast_node* &node, bool create_node)
 {
    void *mem_ctx = state;
-   const bool r = this->merge_qualifier(loc, state, q);
+   const bool r = this->merge_qualifier(loc, state, q, false);
 
    if (state->stage == MESA_SHADER_GEOMETRY) {
       if (q.flags.q.prim_type) {
index 6099aeb12cac11f599cb1ef068d8c6cba9649f6e..1019875894473db88e9ea3ca7fe628390fa04476 100644 (file)
@@ -957,7 +957,7 @@ parameter_qualifier:
                                       "or precise");
 
       $$ = $1;
-      $$.merge_qualifier(&@1, state, $2);
+      $$.merge_qualifier(&@1, state, $2, false);
    }
    | precision_qualifier parameter_qualifier
    {
@@ -974,7 +974,7 @@ parameter_qualifier:
    | memory_qualifier parameter_qualifier
    {
       $$ = $1;
-      $$.merge_qualifier(&@1, state, $2);
+      $$.merge_qualifier(&@1, state, $2, false);
    }
 
 parameter_direction_qualifier:
@@ -1153,7 +1153,7 @@ layout_qualifier_id_list:
    | layout_qualifier_id_list ',' layout_qualifier_id
    {
       $$ = $1;
-      if (!$$.merge_qualifier(& @3, state, $3)) {
+      if (!$$.merge_qualifier(& @3, state, $3, true)) {
          YYERROR;
       }
    }
@@ -1762,7 +1762,7 @@ type_qualifier:
       }
 
       $$ = $1;
-      $$.merge_qualifier(&@1, state, $2);
+      $$.merge_qualifier(&@1, state, $2, false);
    }
    | layout_qualifier type_qualifier
    {
@@ -1779,12 +1779,12 @@ type_qualifier:
          _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers");
 
       $$ = $1;
-      $$.merge_qualifier(&@1, state, $2);
+      $$.merge_qualifier(&@1, state, $2, false);
    }
    | subroutine_qualifier type_qualifier
    {
       $$ = $1;
-      $$.merge_qualifier(&@1, state, $2);
+      $$.merge_qualifier(&@1, state, $2, false);
    }
    | auxiliary_storage_qualifier type_qualifier
    {
@@ -1800,7 +1800,7 @@ type_qualifier:
                           "just before storage qualifiers");
       }
       $$ = $1;
-      $$.merge_qualifier(&@1, state, $2);
+      $$.merge_qualifier(&@1, state, $2, false);
    }
    | storage_qualifier type_qualifier
    {
@@ -1820,7 +1820,7 @@ type_qualifier:
       }
 
       $$ = $1;
-      $$.merge_qualifier(&@1, state, $2);
+      $$.merge_qualifier(&@1, state, $2, false);
    }
    | precision_qualifier type_qualifier
    {
@@ -1837,7 +1837,7 @@ type_qualifier:
    | memory_qualifier type_qualifier
    {
       $$ = $1;
-      $$.merge_qualifier(&@1, state, $2);
+      $$.merge_qualifier(&@1, state, $2, false);
    }
    ;
 
@@ -2589,7 +2589,7 @@ interface_block:
          YYERROR;
       }
 
-      if (!block->layout.merge_qualifier(& @1, state, $1)) {
+      if (!block->layout.merge_qualifier(& @1, state, $1, false)) {
          YYERROR;
       }
 
@@ -2606,7 +2606,7 @@ interface_block:
                              "memory qualifiers can only be used in the "
                              "declaration of shader storage blocks");
       }
-      if (!block->layout.merge_qualifier(& @1, state, $1)) {
+      if (!block->layout.merge_qualifier(& @1, state, $1, false)) {
          YYERROR;
       }
       $$ = block;
@@ -2750,14 +2750,15 @@ layout_uniform_defaults:
          YYERROR;
       } else {
          if (!state->default_uniform_qualifier->
-                merge_qualifier(& @1, state, $1)) {
+                merge_qualifier(& @1, state, $1, false)) {
             YYERROR;
          }
       }
    }
    | layout_qualifier UNIFORM ';'
    {
-      if (!state->default_uniform_qualifier->merge_qualifier(& @1, state, $1)) {
+      if (!state->default_uniform_qualifier->
+             merge_qualifier(& @1, state, $1, false)) {
          YYERROR;
       }
       $$ = NULL;
@@ -2773,14 +2774,15 @@ layout_buffer_defaults:
          YYERROR;
       } else {
          if (!state->default_shader_storage_qualifier->
-                merge_qualifier(& @1, state, $1)) {
+                merge_qualifier(& @1, state, $1, false)) {
             YYERROR;
          }
       }
    }
    | layout_qualifier BUFFER ';'
    {
-      if (!state->default_shader_storage_qualifier->merge_qualifier(& @1, state, $1)) {
+      if (!state->default_shader_storage_qualifier->
+             merge_qualifier(& @1, state, $1, false)) {
          YYERROR;
       }