summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;
}
}