From 65df02c00287449efedc4ec3d57ceee38abaacdb Mon Sep 17 00:00:00 2001 From: Andres Gomez Date: Mon, 14 Nov 2016 17:46:05 +0200 Subject: [PATCH] glsl: split default in layout qualifier merge 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 Signed-off-by: Andres Gomez --- 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 14936f1cebe..62ccb9d4d34 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 b61e1a765a2..65e4ca6c779 100644 --- a/src/compiler/glsl/ast_type.cpp +++ b/src/compiler/glsl/ast_type.cpp @@ -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); } } diff --git a/src/compiler/glsl/glsl_parser.yy b/src/compiler/glsl/glsl_parser.yy index a96989bee9b..82501af6456 100644 --- a/src/compiler/glsl/glsl_parser.yy +++ b/src/compiler/glsl/glsl_parser.yy @@ -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; } } -- 2.30.2