Note 1: both are vertex shaders as I don’t need fragment/geometry processing here, using Transform Feedback.
Note 2: AMD customer support is currently not available
Note 3-historical: it definitely worked on Catalyst 9.10. Then my shaders (not exactly these) started to crash on linking on 9.11. I gave up that time waiting for the 9.12. And now it just fails with no reason…
Implement your own #include-type mechanism. It doesn’t have to be literally #include. It can be something where you always build a shader by concatenating the same N shader files. E.g.: defines.glsl, state.glsl, shared.glsl, guts.glsl.
You could stick your types in that shared section, so they’re effectively only included once.
I wasn’t aware of that. At any rate, compiles here with no warnings on NVidia (Cg 2.2.6). Doesn’t help you on ATI though.
In any case, a crash isn’t acceptable. I’d file a bug.
I’m not declaring it twice in a single object. I’m declaring it in each shader object that uses the definition (like in C). I’m not aware of any other way of sharing struct definitions across multiple shader objects.
As I wrote before, AMD developer relations is on holidays until 4th January. I guess all I need is to wait for another driver version (10.1?).
Oh, sorry. Like count0 I misunderstood. Given that, I have no idea why these shouldn’t link. Though I confess to have never driven the fixed-function pipe with GLSL, only Cg.
Maybe it has something to do with the lack of a frag shader. Might try linking it with a pass-through fragment shader and see if that suppresses the driver bug.
It does look a linking bug. The shaders should work and don’t violate the spec as far as I can tell. I’ve forwarded your issue to our compiler team and they’re going to try to reproduce it.
Thank you, Graham!
I’ve almost lost the hope.
It’s good to have ATI presence on this forum now: the support gets better and I hope to hear less complains about it (and experience less problems myself, of course) in a near future.
While it’s still obvious to me that it’s a bug, I’ve got an official answer from AMD that the driver team doesn’t recognize a bug here. They are just going to report a proper error message instead of fixing the bug itself, pointing me to the spec and NV implementation. Well, both (AMD & NV) are wrong then…
Moreover, I tried to argue about that and didn’t receive any answer. If you think I’m wrong and it’s not really a bug, then tell me why, please. Or better - tell me how to access uniform structs from different shaders in the current AMD/NV implementation.
Catalyst 10.1 changed nothing in this case.
Graham, It would be nice to hear your opinion especially.
Update.
Catalyst 10.2 - no changes with the issue.
As those uniform struct names make a collision, I tried to name them differently in different objects (Spatial,Spatial2,Spatial3). The compiler should be happy as well as the linker, which examines (in theory) just contents of the structure, but not the names. Unfortunately, this workaround doesn’t work:
Fragment shader(s) linked, vertex shader(s) failed to link.
Vertex Shader not supported by HW
Now I know that my 2400 HD radeon suddenly dropped vertex shader support…
If you have any idea about other possible workarounds - please, tell me.
The compiler should be happy as well as the linker, which examines (in theory) just contents of the structure, but not the names.
Why would it? They’re different types; that’s what having different names mean. C/C++ compilers don’t let you pass a Struct1 to a function taking a Struct2 even if Struct1 and Struct2 just so happen to be identical definitions.
If you have any idea about other possible workarounds - please, tell me.
Stop using shader objects like that. Put everything in one string and compile it into one shader object, and use one shader object per shader stage.
I know the spec says you’re supposed to be able to and everything, but obviously ATI has a few loose ends to tie up with this regard. And since virtually nobody does it this way, it equally obviously isn’t something they test for.
Well, it’s not C/C++ even though the syntax is similar.
When you call glGetUniformLocation, you are not specifying a type. Instead, you are providing a path to a basetype through your structures (like bone[1].pos, where bone is an array of structures).
This makes me feel that GLSL linker doesn’t care about the type name and cares only about the type content (well, it does care about uniform names anyway, so let’s apply this sentence to the shared functions arguments at least).
Stop using shader objects like that. Put everything in one string and compile it into one shader object, and use one shader object per shader stage.
I can’t do it without a major restructurization of the shader system. Just joining the shader sources will invoke name collisions.
I’m using shader objects for the polymorphism implementation: each little shader implements a particular piece of work, then for each ‘virtual bind point’ (function) a proper shader is attached. This provides me with a great shading granularity.
As for my case, what you suggest is to write my own shader preprocessor/compiler between the existing functionality and driver calls. Possible, but it’s a huge amount of work that will not be needed eventually (I hope).
When you call glGetUniformLocation, you are not specifying a type. Instead, you are providing a path to a basetype through your structures (like bone[1].pos, where bone is an array of structures).
True, but:
uniform StructA varName;
uniform StructB varName;
is simply not legitimate code, whether in one file or in several. When the linker goes to put all of the uniforms together, and finds a uniform defined with different types but the same names, it’s going to fail. The GLSL spec requires it; you cannot have the same uniform defined in two different shader objects with different types.
This will fail in C++. If the same source file uses both headers, it will be a compiler error. If two source files include one and the other, it will be a linker error. But it is an error either way.
glGetUniformLocation is irrelevant to this requirement; this is a basic linking issue.
I can’t do it without a major restructurization of the shader system. Just joining the shader sources will invoke name collisions.
It’s up to you. You can rely on functionality that ATI clearly isn’t interested in making work (even if they fix it in 10.3, will they test it extensively in every driver version? Or will a new revision come out that regresses). Or you can do it in a way that you know will actually work.
How much “restructurization” is functioning code worth to you?
Well, I understand clearly that the uniform namespace is per program and we can’t use different type names for the same uniform value.
However, your comparison with C/C++ does not make sense here. The linkers behave differently. For example, in GLSL the following objects link together with no problems:
It’s not correct in C/C++, but OK for GLSL. As I said before, it doesn’t care much about user type names.
That example was tested with Catalyst 10.2. So maybe I can go around with a little blood drop:
I can use external functions in separate shader objects (yeeehaa!)
I can use basic type uniform across different shader objects.
But I can not use my uniform structures across different objects.
So the workaround may be the following: pass uniform structures as arguments for those external functions - not a big deal actually
Anyway, thanks for your cooperation, Alfonse!
Dmitry
No, it’s not. Apparently, the driver in question handles it, but the language says that it shouldn’t. This is simply another place where ATI isn’t following the spec.
I am actually not sure that the shader above should really link, although the type have the same layout, they are different types and the link should report that you have an undefined myFunc(Spatial)
on the original thread, I believe that:
in the same shader object, you can’t redeclare the struct
in separate objects, you can redeclare the struct. the two don’t have to match unless you have extern declaration