summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Berry <stereotype441@gmail.com>2013-10-01 15:48:07 -0700
committerPaul Berry <stereotype441@gmail.com>2013-10-10 14:27:40 -0700
commit8cb9cce0400362e913ad89f4ae981b8baf86bb57 (patch)
tree53abbad7646ead1a555018e4fdd3d78e81752f82
parent84b9fa83a07552ff0c0f7b2ea6386377334289ef (diff)
glsl: Don't allow gl_PerVertex to be redeclared after it's been used.
Fixes piglit tests: - spec/glsl-1.50/compiler/gs-redeclares-pervertex-in-after-other-usage.geom - spec/glsl-1.50/compiler/gs-redeclares-pervertex-out-after-other-usage.geom - spec/glsl-1.50/compiler/gs-redeclares-pervertex-out-after-usage.geom - spec/glsl-1.50/compiler/vs-redeclares-pervertex-out-after-other-usage.vert - spec/glsl-1.50/compiler/vs-redeclares-pervertex-out-after-usage.vert Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
-rw-r--r--src/glsl/ast_to_hir.cpp53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index d64d5480bf..dfa32d9200 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -4611,6 +4611,39 @@ ast_struct_specifier::hir(exec_list *instructions,
return NULL;
}
+
+/**
+ * Visitor class which detects whether a given interface block has been used.
+ */
+class interface_block_usage_visitor : public ir_hierarchical_visitor
+{
+public:
+ interface_block_usage_visitor(ir_variable_mode mode, const glsl_type *block)
+ : mode(mode), block(block), found(false)
+ {
+ }
+
+ virtual ir_visitor_status visit(ir_dereference_variable *ir)
+ {
+ if (ir->var->mode == mode && ir->var->get_interface_type() == block) {
+ found = true;
+ return visit_stop;
+ }
+ return visit_continue;
+ }
+
+ bool usage_found() const
+ {
+ return this->found;
+ }
+
+private:
+ ir_variable_mode mode;
+ const glsl_type *block;
+ bool found;
+};
+
+
ir_rvalue *
ast_interface_block::hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
@@ -4737,6 +4770,26 @@ ast_interface_block::hir(exec_list *instructions,
earlier_per_vertex->fields.structure[j].location;
}
}
+
+ /* From section 7.1 ("Built-in Language Variables") of the GLSL 4.10
+ * spec:
+ *
+ * If a built-in interface block is redeclared, it must appear in
+ * the shader before any use of any member included in the built-in
+ * declaration, or a compilation error will result.
+ *
+ * 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.
+ */
+ interface_block_usage_visitor v(var_mode, earlier_per_vertex);
+ v.run(instructions);
+ if (v.usage_found()) {
+ _mesa_glsl_error(&loc, state,
+ "redeclaration of a built-in interface block must "
+ "appear before any use of any member of the "
+ "interface block");
+ }
}
const glsl_type *block_type =