Mesa (master): glsl linker: compare interface blocks during interstage linking

Jordan Justen jljusten at kemper.freedesktop.org
Thu May 23 18:23:43 UTC 2013


Module: Mesa
Branch: master
Commit: 3ddfccb303c571f83de7a0743021eda922c5c8a1
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=3ddfccb303c571f83de7a0743021eda922c5c8a1

Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Mon May 20 23:46:16 2013 -0700

glsl linker: compare interface blocks during interstage linking

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(+), 0 deletions(-)

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.




More information about the mesa-commit mailing list