summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Berry <[email protected]>2013-09-27 20:53:33 -0700
committerPaul Berry <[email protected]>2013-10-10 14:27:33 -0700
commit1b4a7378e993bb00426c79e5b7433b48b50a9090 (patch)
tree1dbdb355b41e84a423fbaa13059b44b21d3b8320 /src
parent79f515251a765afd959d9260574fd855e1154afa (diff)
glsl: Support redeclaration of VS and GS gl_PerVertex output.
Fixes piglit tests: - spec/glsl-1.50/execution/redeclare-pervertex-out-subset-gs - spec/glsl-1.50/execution/redeclare-pervertex-subset-vs Reviewed-by: Ian Romanick <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/glsl/ast_to_hir.cpp62
1 files changed, 60 insertions, 2 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index eaaa7d92605..2e73c4f041d 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -2328,7 +2328,8 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
*/
static ir_variable *
get_variable_being_redeclared(ir_variable *var, YYLTYPE loc,
- struct _mesa_glsl_parse_state *state)
+ struct _mesa_glsl_parse_state *state,
+ bool allow_all_redeclarations)
{
/* Check if this declaration is actually a re-declaration, either to
* resize an array or add qualifiers to an existing variable.
@@ -2431,6 +2432,16 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc,
earlier->depth_layout = var->depth_layout;
+ } else if (allow_all_redeclarations) {
+ if (earlier->mode != var->mode) {
+ _mesa_glsl_error(&loc, state,
+ "redeclaration of `%s' with incorrect qualifiers",
+ var->name);
+ } else if (earlier->type != var->type) {
+ _mesa_glsl_error(&loc, state,
+ "redeclaration of `%s' has incorrect type",
+ var->name);
+ }
} else {
_mesa_glsl_error(&loc, state, "`%s' redeclared", var->name);
}
@@ -3220,7 +3231,8 @@ ast_declarator_list::hir(exec_list *instructions,
*/
exec_list initializer_instructions;
ir_variable *earlier =
- get_variable_being_redeclared(var, decl->get_location(), state);
+ get_variable_being_redeclared(var, decl->get_location(), state,
+ false /* allow_all_redeclarations */);
if (decl->initializer != NULL) {
result = process_initializer((earlier == NULL) ? var : earlier,
@@ -4816,6 +4828,20 @@ ast_interface_block::hir(exec_list *instructions,
var_mode);
var->init_interface_type(block_type);
+ if (redeclaring_per_vertex) {
+ ir_variable *earlier =
+ get_variable_being_redeclared(var, loc, state,
+ true /* allow_all_redeclarations */);
+ if (strncmp(var->name, "gl_", 3) != 0 || earlier == NULL) {
+ _mesa_glsl_error(&loc, state,
+ "redeclaration of gl_PerVertex can only "
+ "include built-in variables");
+ } else {
+ earlier->reinit_interface_type(block_type);
+ }
+ continue;
+ }
+
if (state->symbols->get_variable(var->name) != NULL)
_mesa_glsl_error(&loc, state, "`%s' redeclared", var->name);
@@ -4829,6 +4855,38 @@ ast_interface_block::hir(exec_list *instructions,
state->symbols->add_variable(var);
instructions->push_tail(var);
}
+
+ if (redeclaring_per_vertex && block_type != earlier_per_vertex) {
+ /* From section 7.1 ("Built-in Language Variables") of the GLSL 4.10 spec:
+ *
+ * It is also a compilation error ... to redeclare a built-in
+ * block and then use a member from that built-in block that was
+ * not included in the redeclaration.
+ *
+ * This appears to be a clarification to the behaviour established
+ * for gl_PerVertex by GLSL 1.50, therefore we implement this
+ * behaviour regardless of GLSL version.
+ *
+ * To prevent the shader from using a member that was not included in
+ * the redeclaration, we disable any ir_variables that are still
+ * associated with the old declaration of gl_PerVertex (since we've
+ * already updated all of the variables contained in the new
+ * gl_PerVertex to point to it).
+ *
+ * As a side effect this will prevent
+ * validate_intrastage_interface_blocks() from getting confused and
+ * thinking there are conflicting definitions of gl_PerVertex in the
+ * shader.
+ */
+ foreach_list_safe(node, instructions) {
+ ir_variable *const var = ((ir_instruction *) node)->as_variable();
+ if (var != NULL &&
+ var->get_interface_type() == earlier_per_vertex) {
+ state->symbols->disable_variable(var->name);
+ var->remove();
+ }
+ }
+ }
}
return NULL;