Verify that interface blocks match when linking separate shader stages into a program.
Fixes piglit glsl-1.50 tests: * linker/interface-blocks-vs-fs-member-count-mismatch.shader_test * linker/interface-blocks-vs-fs-member-order-mismatch.shader_test Signed-off-by: Jordan Justen <jordan.l.jus...@intel.com> --- src/glsl/interface_blocks.cpp | 47 +++++++++++++++++++++++++++++++++++++++-- src/glsl/interface_blocks.h | 4 ++++ src/glsl/linker.cpp | 6 ++++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/glsl/interface_blocks.cpp b/src/glsl/interface_blocks.cpp index 6dfd0c4..b458b59 100644 --- a/src/glsl/interface_blocks.cpp +++ b/src/glsl/interface_blocks.cpp @@ -30,14 +30,21 @@ #include "glsl_symbol_table.h" #include "main/macros.h" #include "program/hash_table.h" +#include "linker.h" static bool cross_validate_interface_blocks(const gl_shader **shader_list, - unsigned num_shaders) + unsigned num_shaders, + bool interstage) { bool ok = true; glsl_symbol_table interfaces; + /* Interstage linking checks assume 2 shaders. First the producer, and + * then the consumer. + */ + assert(!interstage || num_shaders == 2); + for (unsigned int i = 0; ok && i < num_shaders; i++) { if (shader_list[i] == NULL) continue; @@ -52,6 +59,18 @@ cross_validate_interface_blocks(const gl_shader **shader_list, if (iface_type == NULL) continue; + /* If we are checking interstage linking then we assume: + * * The first shader (producer) has i == 0, and for the + * producer we don't need to check input interfaces. + * * The second shader (consumer) has i == 1, and for the + * consumer we don't need to check output interfaces. + */ + if (interstage && + ((var->mode == ir_var_shader_in && i == 0) || + (var->mode == ir_var_shader_out && i == 1)) + ) + continue; + const char *iface_name = iface_type->name; const glsl_type *old_iface_type = @@ -70,6 +89,18 @@ cross_validate_interface_blocks(const gl_shader **shader_list, ok &= old_iface_type == iface_type; if (!ok) break; + + /* For interstage linking, if the interface is an input, then + * we need to verify that its type matches a previously declared + * output type. + */ + if (interstage && var->mode == ir_var_shader_in) { + old_iface_type = + interfaces.get_interface(iface_name, ir_var_shader_out); + ok &= old_iface_type == iface_type; + if (!ok) + break; + } } } @@ -81,6 +112,18 @@ validate_intrastage_interface_blocks(const gl_shader **shader_list, unsigned num_shaders) { return cross_validate_interface_blocks(shader_list, - num_shaders); + num_shaders, + false); +} + +bool +validate_interstage_interface_blocks(const gl_shader *producer, + const gl_shader *consumer) +{ + const gl_shader *shader_list[] = { producer, consumer }; + + return cross_validate_interface_blocks((const gl_shader **) shader_list, + ARRAY_SIZE(shader_list), + true); } diff --git a/src/glsl/interface_blocks.h b/src/glsl/interface_blocks.h index 4c37c02..58c847c 100644 --- a/src/glsl/interface_blocks.h +++ b/src/glsl/interface_blocks.h @@ -29,4 +29,8 @@ bool validate_intrastage_interface_blocks(const gl_shader **shader_list, unsigned num_shaders); +bool +validate_interstage_interface_blocks(const gl_shader *producer, + const gl_shader *consumer); + #endif /* GLSL_INTERFACE_BLOCKS_H */ diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 187bc4b..7d13a5e 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1729,6 +1729,12 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) if (prog->_LinkedShaders[i] == NULL) continue; + if (!validate_interstage_interface_blocks(prog->_LinkedShaders[prev], + prog->_LinkedShaders[i])) { + linker_error(prog, "interface block mismatch between shader stages\n"); + goto done; + } + if (!cross_validate_outputs_to_inputs(prog, prog->_LinkedShaders[prev], prog->_LinkedShaders[i])) -- 1.7.10.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev