glsl: split default in layout qualifier merge
authorAndres Gomez <agomez@igalia.com>
Mon, 14 Nov 2016 15:46:05 +0000 (17:46 +0200)
committerAndres Gomez <agomez@igalia.com>
Fri, 25 Nov 2016 11:18:30 +0000 (13:18 +0200)
Currently, the default in 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 in qualifier.

Reviewed-by: Timothy Arceri <timothy.arceri@collabora.com>
Signed-off-by: Andres Gomez <agomez@igalia.com>
src/compiler/glsl/ast.h
src/compiler/glsl/ast_type.cpp
src/compiler/glsl/glsl_parser.yy

index 14936f1cebe334edb3bcdc066d0000a8741d681a..62ccb9d4d3424162994fdb7cfd0b91dbaf764ede 100644 (file)
@@ -768,10 +768,18 @@ struct ast_type_qualifier {
                                  _mesa_glsl_parse_state *state,
                                  ast_node* &node, bool create_node);
 
-   bool merge_in_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 in one.
+    */
+   bool validate_in_qualifier(YYLTYPE *loc,
+                              _mesa_glsl_parse_state *state);
+
+   /**
+    * Merge current qualifier into the global in one.
+    */
+   bool merge_into_in_qualifier(YYLTYPE *loc,
+                                _mesa_glsl_parse_state *state,
+                                ast_node* &node, bool create_node);
 
    bool validate_flags(YYLTYPE *loc,
                        _mesa_glsl_parse_state *state,
index b61e1a765a29fe3ef315d294ec23396b3cc529a9..65e4ca6c77916900502ba2d21f69e130b2db76cc 100644 (file)
@@ -462,27 +462,25 @@ ast_type_qualifier::merge_into_out_qualifier(YYLTYPE *loc,
    return r;
 }
 
-ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
-                                       _mesa_glsl_parse_state *state,
-                                       const ast_type_qualifier &q,
-                                       ast_node* &node, bool create_node)
+bool
+ast_type_qualifier::validate_in_qualifier(YYLTYPE *loc,
+                                          _mesa_glsl_parse_state *state)
 {
-   void *lin_ctx = state->linalloc;
-   bool create_gs_ast = false;
-   bool create_cs_ast = false;
+   bool r = true;
    ast_type_qualifier valid_in_mask;
    valid_in_mask.flags.i = 0;
 
    switch (state->stage) {
    case MESA_SHADER_TESS_EVAL:
-      if (q.flags.q.prim_type) {
+      if (this->flags.q.prim_type) {
          /* Make sure this is a valid input primitive type. */
-         switch (q.prim_type) {
+         switch (this->prim_type) {
          case GL_TRIANGLES:
          case GL_QUADS:
          case GL_ISOLINES:
             break;
          default:
+            r = false;
             _mesa_glsl_error(loc, state,
                              "invalid tessellation evaluation "
                              "shader input primitive type");
@@ -496,9 +494,9 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
       valid_in_mask.flags.q.point_mode = 1;
       break;
    case MESA_SHADER_GEOMETRY:
-      if (q.flags.q.prim_type) {
+      if (this->flags.q.prim_type) {
          /* Make sure this is a valid input primitive type. */
-         switch (q.prim_type) {
+         switch (this->prim_type) {
          case GL_POINTS:
          case GL_LINES:
          case GL_LINES_ADJACENCY:
@@ -506,16 +504,13 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
          case GL_TRIANGLES_ADJACENCY:
             break;
          default:
+            r = false;
             _mesa_glsl_error(loc, state,
                              "invalid geometry shader input primitive type");
             break;
          }
       }
 
-      create_gs_ast |=
-         q.flags.q.prim_type &&
-         !state->in_qualifier->flags.q.prim_type;
-
       valid_in_mask.flags.q.prim_type = 1;
       valid_in_mask.flags.q.invocations = 1;
       break;
@@ -523,97 +518,121 @@ ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
       valid_in_mask.flags.q.early_fragment_tests = 1;
       break;
    case MESA_SHADER_COMPUTE:
-      create_cs_ast |=
-         q.flags.q.local_size != 0 &&
-         state->in_qualifier->flags.q.local_size == 0;
-
       valid_in_mask.flags.q.local_size = 7;
       valid_in_mask.flags.q.local_size_variable = 1;
       break;
    default:
+      r = false;
       _mesa_glsl_error(loc, state,
                        "input layout qualifiers only valid in "
-                       "geometry, fragment and compute shaders");
+                       "geometry, tessellation, fragment and compute shaders");
       break;
    }
 
    /* Generate an error when invalid input layout qualifiers are used. */
-   if ((q.flags.i & ~valid_in_mask.flags.i) != 0) {
+   if ((this->flags.i & ~valid_in_mask.flags.i) != 0) {
+      r = false;
       _mesa_glsl_error(loc, state, "invalid input layout qualifiers used");
-      return false;
+   }
+
+   return r;
+}
+
+bool
+ast_type_qualifier::merge_into_in_qualifier(YYLTYPE *loc,
+                                            _mesa_glsl_parse_state *state,
+                                            ast_node* &node, bool create_node)
+{
+   void *lin_ctx = state->linalloc;
+   bool create_gs_ast = false;
+   bool create_cs_ast = false;
+
+   switch (state->stage) {
+   case MESA_SHADER_GEOMETRY:
+      create_gs_ast |=
+         this->flags.q.prim_type &&
+         !state->in_qualifier->flags.q.prim_type;
+      break;
+   case MESA_SHADER_COMPUTE:
+      create_cs_ast |=
+         this->flags.q.local_size != 0 &&
+         state->in_qualifier->flags.q.local_size == 0;
+      break;
+   default:
+      break;
    }
 
    /* Input layout qualifiers can be specified multiple
     * times in separate declarations, as long as they match.
     */
-   if (this->flags.q.prim_type) {
-      if (q.flags.q.prim_type &&
-          this->prim_type != q.prim_type) {
+   if (state->in_qualifier->flags.q.prim_type) {
+      if (this->flags.q.prim_type &&
+          state->in_qualifier->prim_type != this->prim_type) {
          _mesa_glsl_error(loc, state,
                           "conflicting input primitive %s specified",
                           state->stage == MESA_SHADER_GEOMETRY ?
                           "type" : "mode");
       }
-   } else if (q.flags.q.prim_type) {
+   } else if (this->flags.q.prim_type) {
       state->in_qualifier->flags.q.prim_type = 1;
-      state->in_qualifier->prim_type = q.prim_type;
+      state->in_qualifier->prim_type = this->prim_type;
    }
 
-   if (q.flags.q.invocations) {
-      this->flags.q.invocations = 1;
-      if (this->invocations) {
-         this->invocations->merge_qualifier(q.invocations);
+   if (this->flags.q.invocations) {
+      state->in_qualifier->flags.q.invocations = 1;
+      if (state->in_qualifier->invocations) {
+         state->in_qualifier->invocations->merge_qualifier(this->invocations);
       } else {
-         this->invocations = q.invocations;
+         state->in_qualifier->invocations = this->invocations;
       }
    }
 
-   if (q.flags.q.early_fragment_tests) {
+   if (this->flags.q.early_fragment_tests) {
       state->fs_early_fragment_tests = true;
    }
 
-   if (this->flags.q.vertex_spacing) {
-      if (q.flags.q.vertex_spacing &&
-          this->vertex_spacing != q.vertex_spacing) {
+   if (state->in_qualifier->flags.q.vertex_spacing) {
+      if (this->flags.q.vertex_spacing &&
+          state->in_qualifier->vertex_spacing != this->vertex_spacing) {
          _mesa_glsl_error(loc, state,
                           "conflicting vertex spacing specified");
       }
-   } else if (q.flags.q.vertex_spacing) {
-      this->flags.q.vertex_spacing = 1;
-      this->vertex_spacing = q.vertex_spacing;
+   } else if (this->flags.q.vertex_spacing) {
+      state->in_qualifier->flags.q.vertex_spacing = 1;
+      state->in_qualifier->vertex_spacing = this->vertex_spacing;
    }
 
-   if (this->flags.q.ordering) {
-      if (q.flags.q.ordering &&
-          this->ordering != q.ordering) {
+   if (state->in_qualifier->flags.q.ordering) {
+      if (this->flags.q.ordering &&
+          state->in_qualifier->ordering != this->ordering) {
          _mesa_glsl_error(loc, state,
                           "conflicting ordering specified");
       }
-   } else if (q.flags.q.ordering) {
-      this->flags.q.ordering = 1;
-      this->ordering = q.ordering;
+   } else if (this->flags.q.ordering) {
+      state->in_qualifier->flags.q.ordering = 1;
+      state->in_qualifier->ordering = this->ordering;
    }
 
-   if (this->flags.q.point_mode) {
-      if (q.flags.q.point_mode &&
-          this->point_mode != q.point_mode) {
+   if (state->in_qualifier->flags.q.point_mode) {
+      if (this->flags.q.point_mode &&
+          state->in_qualifier->point_mode != this->point_mode) {
          _mesa_glsl_error(loc, state,
                           "conflicting point mode specified");
       }
-   } else if (q.flags.q.point_mode) {
-      this->flags.q.point_mode = 1;
-      this->point_mode = q.point_mode;
+   } else if (this->flags.q.point_mode) {
+      state->in_qualifier->flags.q.point_mode = 1;
+      state->in_qualifier->point_mode = this->point_mode;
    }
 
-   if (q.flags.q.local_size_variable) {
+   if (this->flags.q.local_size_variable) {
       state->cs_input_local_size_variable_specified = true;
    }
 
    if (create_node) {
       if (create_gs_ast) {
-         node = new(lin_ctx) ast_gs_input_layout(*loc, q.prim_type);
+         node = new(lin_ctx) ast_gs_input_layout(*loc, this->prim_type);
       } else if (create_cs_ast) {
-         node = new(lin_ctx) ast_cs_input_layout(*loc, q.local_size);
+         node = new(lin_ctx) ast_cs_input_layout(*loc, this->local_size);
       }
    }
 
index a96989bee9b02ece9a5643812a980ed8cbe02542..82501af6456973593501056ccc18b2153d90aaf9 100644 (file)
@@ -2917,8 +2917,10 @@ layout_in_defaults:
          _mesa_glsl_error(&@1, state, "duplicate layout(...) qualifiers");
          YYERROR;
       } else {
-         if (!state->in_qualifier->
-                merge_in_qualifier(& @1, state, $1, $$, false)) {
+         if (!$1.validate_in_qualifier(& @1, state)) {
+            YYERROR;
+         }
+         if (!$1.merge_into_in_qualifier(& @1, state, $$, false)) {
             YYERROR;
          }
          $$ = $2;
@@ -2927,8 +2929,10 @@ layout_in_defaults:
    | layout_qualifier IN_TOK ';'
    {
       $$ = NULL;
-      if (!state->in_qualifier->
-             merge_in_qualifier(& @1, state, $1, $$, true)) {
+      if (!$1.validate_in_qualifier(& @1, state)) {
+         YYERROR;
+      }
+      if (!$1.merge_into_in_qualifier(& @1, state, $$, true)) {
          YYERROR;
       }
    }