[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