I have a GLSL program that contains 3 fragment shader sources that would get linked together, like this:
1.
#version 460 core
void RunA();
void RunB();
void main() {
RunA();
RunB();
}
#version 460 core
layout(location=0) in float inValue;
layout(location=0) out float outValue;
void RunA() {
outValue = inValue;
}
#version 460 core
layout(location=1) in float inValue;
layout(location=1) out float outValue;
void RunB() {
outValue = inValue;
}
In the real codebase fragment shaders 2 and 3 are generated from the same source, with different #defines
inserted for the function name and location indices.
It fails because they share the name inValue
and outValue
.
Is it possible to define them such that they are only local to that shader source, and don't conflict with declarations in other fragment shaders of the same program?
(Similar to a static
declaration in C)
Is it possible to define them such that they are only local to that shader source, and don't conflict with declarations in other fragment shaders of the same program?
Yes: give them different names.
These names represent inherently global concepts; making them static
makes no sense. Also, OpenGL's API uses the name of these global concept in order to talk about the resource, so it requires that those names be unique within the program.
The only theoretical way to avoid this is to use SPIR-V through OpenGL. That is, compile your GLSL shaders into SPIR-V, then upload those SPIR-V binaries into OpenGL shader objects. SPIR-V doesn't care about the names of things, and using SPIR-V binaries causes OpenGL's name-based introspection API to stop working.
However, that wouldn't work if you try to use it directly. Unlike with GLSL, OpenGL doesn't support linking multiple SPIR-V modules into the same shader stage. Each SPIR-V module must completely define a single stage.
So what you would need to do is take all of your SPIR-V modules for a stage and manually link them together into a single module. There may be tools that can handle that automatically.