diff options
author | Paul Berry <[email protected]> | 2013-10-02 11:21:04 -0700 |
---|---|---|
committer | Paul Berry <[email protected]> | 2013-10-10 14:27:31 -0700 |
commit | 79f515251a765afd959d9260574fd855e1154afa (patch) | |
tree | c228a055ff373520cf380dca3153c469412a1f97 /src/glsl | |
parent | 3c83c96dcd1be26e24c07a3dff5df1ef84974901 (diff) |
glsl: Error check redeclarations of gl_PerVertex.
This patch verifies that:
- The gl_PerVertex input interface block may only be redeclared in a
geometry shader, and that it may only be redeclared as gl_in[].
- The gl_PerVertex output interface block may only be redeclared in a
vertex or geometry shader, and that it may only be redeclared as a
non-array without an interface name.
- gl_PerVertex may not be redeclared as any other type of interface
block (i.e. as a uniform interface block).
As a side-effect, the code now keeps track of what the previous
declaration of gl_PerVertex was--this will be needed in future
patches.
Fixes piglit tests:
- spec/glsl-1.50/compiler/gs-redeclares-pervertex-in-with-incorrect-name.geom
- spec/glsl-1.50/compiler/gs-redeclares-pervertex-out-as-array.geom
- spec/glsl-1.50/compiler/gs-redeclares-pervertex-out-with-instance-name.geom
Reviewed-by: Ian Romanick <[email protected]>
Diffstat (limited to 'src/glsl')
-rw-r--r-- | src/glsl/ast_to_hir.cpp | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index b1bfa062a36..eaaa7d92605 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -4654,6 +4654,66 @@ ast_interface_block::hir(exec_list *instructions, if (!redeclaring_per_vertex) validate_identifier(this->block_name, loc, state); + const glsl_type *earlier_per_vertex = NULL; + if (redeclaring_per_vertex) { + /* Find the previous declaration of gl_PerVertex. If we're redeclaring + * the named interface block gl_in, we can find it by looking at the + * previous declaration of gl_in. Otherwise we can find it by looking + * at the previous decalartion of any of the built-in outputs, + * e.g. gl_Position. + * + * Also check that the instance name and array-ness of the redeclaration + * are correct. + */ + switch (var_mode) { + case ir_var_shader_in: + if (ir_variable *earlier_gl_in = + state->symbols->get_variable("gl_in")) { + earlier_per_vertex = earlier_gl_in->get_interface_type(); + } else { + _mesa_glsl_error(&loc, state, + "redeclaration of gl_PerVertex input not allowed " + "in the %s shader", + _mesa_glsl_shader_target_name(state->target)); + } + if (this->instance_name == NULL || + strcmp(this->instance_name, "gl_in") != 0 || !this->is_array) { + _mesa_glsl_error(&loc, state, + "gl_PerVertex input must be redeclared as " + "gl_in[]"); + } + break; + case ir_var_shader_out: + if (ir_variable *earlier_gl_Position = + state->symbols->get_variable("gl_Position")) { + earlier_per_vertex = earlier_gl_Position->get_interface_type(); + } else { + _mesa_glsl_error(&loc, state, + "redeclaration of gl_PerVertex output not " + "allowed in the %s shader", + _mesa_glsl_shader_target_name(state->target)); + } + if (this->instance_name != NULL) { + _mesa_glsl_error(&loc, state, + "gl_PerVertex input may not be redeclared with " + "an instance name"); + } + break; + default: + _mesa_glsl_error(&loc, state, + "gl_PerVertex must be declared as an input or an " + "output"); + break; + } + + if (earlier_per_vertex == NULL) { + /* An error has already been reported. Bail out to avoid null + * dereferences later in this function. + */ + return NULL; + } + } + const glsl_type *block_type = glsl_type::get_interface_instance(fields, num_variables, |