[Mesa-dev] [PATCH 04/13] glsl: Split default in layout qualifier merge

Timothy Arceri timothy.arceri at collabora.com
Thu Nov 17 05:56:22 UTC 2016


On Mon, 2016-11-14 at 19:15 +0200, Andres Gomez wrote:
> 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.
> 
> Signed-off-by: Andres Gomez <agomez at igalia.com>
> ---
>  src/compiler/glsl/ast.h          |  16 +++--
>  src/compiler/glsl/ast_type.cpp   | 127 ++++++++++++++++++++++-------
> ----------
>  src/compiler/glsl/glsl_parser.yy |  12 ++--
>  3 files changed, 93 insertions(+), 62 deletions(-)
> 
> diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h
> index 14936f1..62ccb9d 100644
> --- a/src/compiler/glsl/ast.h
> +++ b/src/compiler/glsl/ast.h
> @@ -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,
> diff --git a/src/compiler/glsl/ast_type.cpp
> b/src/compiler/glsl/ast_type.cpp
> index aaf7838..803d952 100644
> --- a/src/compiler/glsl/ast_type.cpp
> +++ b/src/compiler/glsl/ast_type.cpp
> @@ -461,27 +461,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");
> @@ -495,9 +493,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:
> @@ -505,16 +503,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;
> @@ -522,97 +517,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);
>        }
>     }
>  
> diff --git a/src/compiler/glsl/glsl_parser.yy
> b/src/compiler/glsl/glsl_parser.yy
> index 50f7097..9f18c15 100644
> --- a/src/compiler/glsl/glsl_parser.yy
> +++ b/src/compiler/glsl/glsl_parser.yy
> @@ -2913,8 +2913,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;
>           }

To avoid regressions between patches the order should be merge then
validate right?



>           $$ = $2;
> @@ -2923,8 +2925,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;
>        }
>     }


More information about the mesa-dev mailing list