From 0f4cacbb53c23e4fa027375c492edd17b40ae748 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Tue, 19 Nov 2013 17:48:02 -0800 Subject: glsl: Fix cross-version linking between VS and GS. Previously, when attempting to link a vertex shader and a geometry shader that use different GLSL versions, we would sometimes generate a link error due to the implicit declaration of gl_PerVertex being different between the two GLSL versions. This patch fixes that problem by only requiring interface block definitions to match when they are explicitly declared. Fixes piglit test "shaders/version-mixing vs-gs". Cc: "10.0" v2: In the interface_block_definition constructor, move the assignment to explicitly_declared after the existing if block. Reviewed-by: Ian Romanick --- src/glsl/link_interface_blocks.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'src/glsl') diff --git a/src/glsl/link_interface_blocks.cpp b/src/glsl/link_interface_blocks.cpp index a7fceb9bad6..528d4a1577e 100644 --- a/src/glsl/link_interface_blocks.cpp +++ b/src/glsl/link_interface_blocks.cpp @@ -60,6 +60,7 @@ struct interface_block_definition if (var->type->is_array()) array_size = var->type->length; } + explicitly_declared = (var->how_declared != ir_var_declared_implicitly); } /** @@ -77,6 +78,12 @@ struct interface_block_definition * Otherwise -1. */ int array_size; + + /** + * True if this interface block was explicitly declared in the shader; + * false if it was an implicitly declared built-in interface block. + */ + bool explicitly_declared; }; @@ -91,8 +98,14 @@ intrastage_match(interface_block_definition *a, ir_variable_mode mode) { /* Types must match. */ - if (a->type != b->type) - return false; + if (a->type != b->type) { + /* Exception: if both the interface blocks are implicitly declared, + * don't force their types to match. They might mismatch due to the two + * shaders using different GLSL versions, and that's ok. + */ + if (a->explicitly_declared || b->explicitly_declared) + return false; + } /* Presence/absence of interface names must match. */ if ((a->instance_name == NULL) != (b->instance_name == NULL)) @@ -144,8 +157,14 @@ interstage_match(const interface_block_definition *producer, assert(producer->array_size != 0); /* Types must match. */ - if (consumer->type != producer->type) - return false; + if (consumer->type != producer->type) { + /* Exception: if both the interface blocks are implicitly declared, + * don't force their types to match. They might mismatch due to the two + * shaders using different GLSL versions, and that's ok. + */ + if (consumer->explicitly_declared || producer->explicitly_declared) + return false; + } if (extra_array_level) { /* Consumer must be an array, and producer must not. */ if (consumer->array_size == -1) -- cgit v1.2.3