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

Reply via email to