[Mesa-dev] [PATCH v5 17/17] glsl linker: compare interface blocks during interstage linking
Kenneth Graunke
kenneth at whitecape.org
Wed May 22 11:02:30 PDT 2013
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: Kenneth Graunke <kenneth at whitecape.org>
Signed-off-by: Jordan Justen <jordan.l.justen at intel.com>
---
src/glsl/link_interface_blocks.cpp | 39 ++++++++++++++++++++++++++++++++++++++
src/glsl/linker.cpp | 6 ++++++
src/glsl/linker.h | 4 ++++
3 files changed, 49 insertions(+)
diff --git a/src/glsl/link_interface_blocks.cpp b/src/glsl/link_interface_blocks.cpp
index 4a4c5a1..b91860d 100644
--- a/src/glsl/link_interface_blocks.cpp
+++ b/src/glsl/link_interface_blocks.cpp
@@ -69,3 +69,42 @@ validate_intrastage_interface_blocks(const gl_shader **shader_list,
return true;
}
+
+bool
+validate_interstage_interface_blocks(const gl_shader *producer,
+ const gl_shader *consumer)
+{
+ glsl_symbol_table interfaces;
+
+ /* Add non-output interfaces from the consumer to the symbol table. */
+ foreach_list(node, consumer->ir) {
+ ir_variable *var = ((ir_instruction *) node)->as_variable();
+ if (!var || !var->interface_type || var->mode == ir_var_shader_out)
+ continue;
+
+ interfaces.add_interface(var->interface_type->name,
+ var->interface_type,
+ (enum ir_variable_mode) var->mode);
+ }
+
+ /* Verify that the producer's interfaces match. */
+ foreach_list(node, producer->ir) {
+ ir_variable *var = ((ir_instruction *) node)->as_variable();
+ if (!var || !var->interface_type || var->mode == ir_var_shader_in)
+ continue;
+
+ enum ir_variable_mode consumer_mode =
+ var->mode == ir_var_uniform ? ir_var_uniform : ir_var_shader_in;
+ const glsl_type *expected_type =
+ interfaces.get_interface(var->interface_type->name, consumer_mode);
+
+ /* The consumer doesn't use this output block. Ignore it. */
+ if (expected_type == NULL)
+ continue;
+
+ if (var->interface_type != expected_type)
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 9a2243a..982fe46 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1728,6 +1728,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]))
diff --git a/src/glsl/linker.h b/src/glsl/linker.h
index 936a143..2fe2410 100644
--- a/src/glsl/linker.h
+++ b/src/glsl/linker.h
@@ -64,6 +64,10 @@ 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);
+
/**
* Class for processing all of the leaf fields of a variable that corresponds
* to a program resource.
--
1.8.2.3
More information about the mesa-dev
mailing list