[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