[Mesa-dev] [PATCH 03/13] glsl: Split default out layout qualifier merge

Andres Gomez agomez at igalia.com
Mon Nov 14 17:15:04 UTC 2016


Currently, the default out layout qualifier merge performs specific
validation and merge.

We want to split out the validation from the merge so they can be done
independently.

Additionally, for simplification, the direction of the validation and
merge is changed so the ast_type_qualifier calling the method is the
one validated and merged against the default out qualifier.

Signed-off-by: Andres Gomez <agomez at igalia.com>
---
 src/compiler/glsl/ast.h          | 16 ++++++--
 src/compiler/glsl/ast_type.cpp   | 79 +++++++++++++++++++++++++---------------
 src/compiler/glsl/glsl_parser.yy | 13 +++++--
 3 files changed, 71 insertions(+), 37 deletions(-)

diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h
index e7c3aff..14936f1 100644
--- a/src/compiler/glsl/ast.h
+++ b/src/compiler/glsl/ast.h
@@ -755,10 +755,18 @@ struct ast_type_qualifier {
                         const ast_type_qualifier &q,
                         bool is_single_layout_merge);
 
-   bool merge_out_qualifier(YYLTYPE *loc,
-                           _mesa_glsl_parse_state *state,
-                           const ast_type_qualifier &q,
-                           ast_node* &node, bool create_node);
+   /**
+    * Validate current qualifier against the global out one.
+    */
+   bool validate_out_qualifier(YYLTYPE *loc,
+                               _mesa_glsl_parse_state *state);
+
+   /**
+    * Merge current qualifier into the global out one.
+    */
+   bool merge_into_out_qualifier(YYLTYPE *loc,
+                                 _mesa_glsl_parse_state *state,
+                                 ast_node* &node, bool create_node);
 
    bool merge_in_qualifier(YYLTYPE *loc,
                            _mesa_glsl_parse_state *state,
diff --git a/src/compiler/glsl/ast_type.cpp b/src/compiler/glsl/ast_type.cpp
index 48afe09..aaf7838 100644
--- a/src/compiler/glsl/ast_type.cpp
+++ b/src/compiler/glsl/ast_type.cpp
@@ -368,33 +368,30 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
 }
 
 bool
-ast_type_qualifier::merge_out_qualifier(YYLTYPE *loc,
-                                        _mesa_glsl_parse_state *state,
-                                        const ast_type_qualifier &q,
-                                        ast_node* &node, bool create_node)
+ast_type_qualifier::validate_out_qualifier(YYLTYPE *loc,
+                                           _mesa_glsl_parse_state *state)
 {
-   const bool r = this->merge_qualifier(loc, state, q, false);
+   bool r = true;
    ast_type_qualifier valid_out_mask;
    valid_out_mask.flags.i = 0;
 
-   if (state->stage == MESA_SHADER_GEOMETRY) {
-      if (q.flags.q.prim_type) {
+   switch (state->stage) {
+   case MESA_SHADER_GEOMETRY:
+      if (this->flags.q.prim_type) {
          /* Make sure this is a valid output primitive type. */
-         switch (q.prim_type) {
+         switch (this->prim_type) {
          case GL_POINTS:
          case GL_LINE_STRIP:
          case GL_TRIANGLE_STRIP:
             break;
          default:
+            r = false;
             _mesa_glsl_error(loc, state, "invalid geometry shader output "
                              "primitive type");
             break;
          }
       }
 
-      /* Allow future assigments of global out's stream id value */
-      this->flags.q.explicit_stream = 0;
-
       valid_out_mask.flags.q.stream = 1;
       valid_out_mask.flags.q.explicit_stream = 1;
       valid_out_mask.flags.q.explicit_xfb_buffer = 1;
@@ -403,43 +400,67 @@ ast_type_qualifier::merge_out_qualifier(YYLTYPE *loc,
       valid_out_mask.flags.q.xfb_stride = 1;
       valid_out_mask.flags.q.max_vertices = 1;
       valid_out_mask.flags.q.prim_type = 1;
-   } else if (state->stage == MESA_SHADER_TESS_CTRL) {
-      if (create_node) {
-         node = new(state->linalloc) ast_tcs_output_layout(*loc);
-      }
+      break;
+   case MESA_SHADER_TESS_CTRL:
       valid_out_mask.flags.q.vertices = 1;
       valid_out_mask.flags.q.explicit_xfb_buffer = 1;
       valid_out_mask.flags.q.xfb_buffer = 1;
       valid_out_mask.flags.q.explicit_xfb_stride = 1;
       valid_out_mask.flags.q.xfb_stride = 1;
-   } else if (state->stage == MESA_SHADER_TESS_EVAL ||
-              state->stage == MESA_SHADER_VERTEX) {
+      break;
+   case MESA_SHADER_TESS_EVAL:
+   case MESA_SHADER_VERTEX:
       valid_out_mask.flags.q.explicit_xfb_buffer = 1;
       valid_out_mask.flags.q.xfb_buffer = 1;
       valid_out_mask.flags.q.explicit_xfb_stride = 1;
       valid_out_mask.flags.q.xfb_stride = 1;
-   } else if (state->stage == MESA_SHADER_FRAGMENT) {
+      break;
+   case MESA_SHADER_FRAGMENT:
       valid_out_mask.flags.q.blend_support = 1;
-   } else {
-      _mesa_glsl_error(loc, state, "out layout qualifiers only valid in "
-                       "geometry, tessellation and vertex shaders");
-      return false;
+      break;
+   default:
+      r = false;
+      _mesa_glsl_error(loc, state,
+                       "out layout qualifiers only valid in "
+                       "geometry, tessellation, vertex and fragment shaders");
    }
 
-   /* Allow future assigments of global out's */
-   this->flags.q.explicit_xfb_buffer = 0;
-   this->flags.q.explicit_xfb_stride = 0;
-
-   /* Generate an error when invalid input layout qualifiers are used. */
-   if ((q.flags.i & ~valid_out_mask.flags.i) != 0) {
+   /* Generate an error when invalid output layout qualifiers are used. */
+   if ((this->flags.i & ~valid_out_mask.flags.i) != 0) {
+      r = false;
       _mesa_glsl_error(loc, state, "invalid output layout qualifiers used");
-      return false;
    }
 
    return r;
 }
 
 bool
+ast_type_qualifier::merge_into_out_qualifier(YYLTYPE *loc,
+                                             _mesa_glsl_parse_state *state,
+                                             ast_node* &node, bool create_node)
+{
+   const bool r = state->out_qualifier->merge_qualifier(loc, state, *this, false);
+
+   switch (state->stage) {
+   case MESA_SHADER_GEOMETRY:
+      /* Allow future assignments of global out's stream id value */
+      state->out_qualifier->flags.q.explicit_stream = 0;
+      break;
+   case MESA_SHADER_TESS_CTRL:
+      if (create_node)
+         node = new(state->linalloc) ast_tcs_output_layout(*loc);
+      break;
+   default:
+      break;
+   }
+
+   /* Allow future assignments of global out's */
+   state->out_qualifier->flags.q.explicit_xfb_buffer = 0;
+   state->out_qualifier->flags.q.explicit_xfb_stride = 0;
+
+   return r;
+}
+
 ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
                                        _mesa_glsl_parse_state *state,
                                        const ast_type_qualifier &q,
diff --git a/src/compiler/glsl/glsl_parser.yy b/src/compiler/glsl/glsl_parser.yy
index 49574c4..50f7097 100644
--- a/src/compiler/glsl/glsl_parser.yy
+++ b/src/compiler/glsl/glsl_parser.yy
@@ -2938,8 +2938,10 @@ layout_out_defaults:
          _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers");
          YYERROR;
       } else {
-         if (!state->out_qualifier->
-                merge_out_qualifier(& @1, state, $1, $$, false)) {
+         if (!$1.validate_out_qualifier(& @1, state)) {
+            YYERROR;
+         }
+         if (!$1.merge_into_out_qualifier(& @1, state, $$, false)) {
             YYERROR;
          }
          $$ = $2;
@@ -2948,9 +2950,12 @@ layout_out_defaults:
    | layout_qualifier OUT_TOK ';'
    {
       $$ = NULL;
-      if (!state->out_qualifier->
-             merge_out_qualifier(& @1, state, $1, $$, true))
+      if (!$1.validate_out_qualifier(& @1, state)) {
          YYERROR;
+      }
+      if (!$1.merge_into_out_qualifier(& @1, state, $$, true)) {
+         YYERROR;
+      }
    }
    ;
 
-- 
2.9.3



More information about the mesa-dev mailing list