From: Paul Berry Date: Tue, 1 Oct 2013 22:48:07 +0000 (-0700) Subject: glsl: Don't allow gl_PerVertex to be redeclared after it's been used. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8cb9cce0400362e913ad89f4ae981b8baf86bb57;p=mesa.git 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 --- diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index d64d5480bfe..dfa32d9200c 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 =