summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorAndres Gomez <[email protected]>2016-11-14 17:46:05 +0200
committerAndres Gomez <[email protected]>2016-11-25 13:18:30 +0200
commit65df02c00287449efedc4ec3d57ceee38abaacdb (patch)
tree3bfe9e92d40b45b1c975075bc30c373e630981b0 /src/compiler
parentfe5c522edd2e809adc46d44d73a49574fc686929 (diff)
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 <[email protected]> Signed-off-by: Andres Gomez <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/glsl/ast.h16
-rw-r--r--src/compiler/glsl/ast_type.cpp127
-rw-r--r--src/compiler/glsl/glsl_parser.yy12
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;
}
}