On 21.11.2013 21:50, f.jo...@email.cz wrote:
The problem is, that each anonymous structure gets its own unique type, without checking if such type already exists. It seems to me, that such code is somewhat in the gray area - the rest of OpenGL implementations doesn't seem to have a problem with this code (Intel on Win, OSX, Nvidia and AMD drivers in Win, OSX and Linux), which of course doesn't mean such a behavior is correct.
This should be allowed, according to GLSL (3.3) spec and grammar. It's just a bug/oversight in the linker, I guess. The GLSL linker already includes some special handling to match array types between stages. I added something similar for structs, see the attached patch. It's probably not the nicest approach (it duplicates some code from glsl_types.cpp), but seems to work fine. I don't really know the GLSL compiler/linker code, so YMMV. :)
Best regards Grigori
>From 386dc4f201a65a2a8740c8c9f4a039d5c8209a9c Mon Sep 17 00:00:00 2001 From: Grigori Goronzy <g...@chown.ath.cx> Date: Sun, 24 Nov 2013 20:24:58 +0100 Subject: [PATCH] WIP: fix unnamed struct type conflicts If two shader stages define the same unnamed struct type, they will conflict. Compare struct types in this case, similar to how it is done with arrays. --- src/glsl/linker.cpp | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 1d53b65..7ca7bb9 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -556,6 +556,37 @@ validate_geometry_shader_executable(struct gl_shader_program *prog, prog->Geom.UsesEndPrimitive = end_primitive.end_primitive_found(); } +static bool +compare_record_types(const glsl_type *key1, const glsl_type *key2) +{ + if (key1->length != key2->length) + return false; + + if (key1->interface_packing != key2->interface_packing) + return false; + + for (unsigned i = 0; i < key1->length; i++) { + if (key1->fields.structure[i].type != key2->fields.structure[i].type) + return false; + if (strcmp(key1->fields.structure[i].name, + key2->fields.structure[i].name) != 0) + return false; + if (key1->fields.structure[i].row_major + != key2->fields.structure[i].row_major) + return false; + if (key1->fields.structure[i].location + != key2->fields.structure[i].location) + return false; + if (key1->fields.structure[i].interpolation + != key2->fields.structure[i].interpolation) + return false; + if (key1->fields.structure[i].centroid + != key2->fields.structure[i].centroid) + return false; + } + + return true; +} /** * Perform validation of global variables used across multiple shaders @@ -609,6 +640,10 @@ cross_validate_globals(struct gl_shader_program *prog, if (var->type->length != 0) { existing->type = var->type; } + } else if (var->type->is_record() + && existing->type->is_record() + && compare_record_types(existing->type, var->type)) { + existing->type = var->type; } else { linker_error(prog, "%s `%s' declared as type " "`%s' and type `%s'\n", -- 1.8.1.2
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev