GLSL: variable telling which shader stage is compiled

I’m really looking forward for a way to know inside a shader at compile time which shader stage is compiled.

For example, I’m usually writing all my pipeline in an unique file like that:


#version 430 core

// common uniforms, functions, struct, ...

uniform ...;
uniform ...;

// ..

#ifdef VERTEX_SHADER
// code for VERTEX_SHADER
in vec3 attrib0;
...

void main()
{

}
#endif

#ifdef FRAGMENT_SHADER
// code for FRAGMENT_SHADER

...

#endif

A lot of people are doing this stuff, it helps to reduce code duplication of functions/uniforms/… But to get this to work, you need to insert a #define XXX_SHADER at compile time + a #LINE to keep correct debugging information, and because this is not standardized, everybody are using different constants name, hence it is not easy to create tools on top of it.

So why not defining constants such as VERTEX, FRAGMENT, __COMPUTE, EVALUATION, CONTROLE and GEOMETRY when a different shader stage is compiled?

A lot of people are doing this stuff

Evidence, please.

it helps to reduce code duplication of functions/uniforms/…

So does taking advantage of the ability to use multiple strings when you compile a shader. Which also happens to work when you want separate programs, so that the myriad combinations of vertex-to-geometry, vertex-to-tessellation, and so forth don’t explode on you.

Also, how many uniforms are you sharing between your vertex and fragment stages? It can’t be that many. Between vertex and geometry, you might share some, but generally, they need their own parameters.

But to get this to work, you need to insert a #define XXX_SHADER at compile time + a #LINE to keep correct debugging information

No you don’t. Again, take advantage of the fact that you can use multiple strings. Just create a simple header string for all of your shaders and stick it into the first slot in your string array. Your actual shader goes in the second.

Note: I have heard that NVIDIA has an issue with line-numbers on multi-string shaders. If that’s the case, then go bug them to fix their drivers.

because this is not standardized, everybody are using different constants name, hence it is not easy to create tools on top of it.

We did not wait eight years for the ARB to finally give us ARB_separate_shader_objects just so that we could build tools around not using it. Or, to put it another way, tools should not encourage misuse of OpenGL. And putting all of your program code in one file is not good use of the API.

At least, not for anything more than the simplest of cases.

So why not defining constants such as VERTEX, FRAGMENT, __COMPUTE, EVALUATION, CONTROLE and GEOMETRY when a different shader stage is compiled?

Because, as you pointed out, you can do it yourself. And the only downside besides an NVIDIA driver bug is that tools that are promoting API misuse aren’t quite as easy to make.

Personally, I can live with that.

You are right in every points you wrote and yes I did not think about using the multiple strings when compiling.

My proposition was only as a matter of convenience for simple programs.

Thank you for you answer, I pretty like the rough answering style :wink:

Previous flames aside, I actually like this proposal. No sense in having to split a program source up which has mated vtx/frag/etc. shaders within it if you don’t otherwise need to. Currently, I #define symbols like this to be able to pull in the right main() function for a shader compile.

Beyond this, provide the ability to set shader “constants” from the API (did I miss this? – e.g. const int NUM_LIGHTS ) without sprintfing them into a piece of the source code, and I can get out of the business of having to manually implement a preprocessor for GLSL shaders in C++ source code to efficiently use ubershaders in GLSL.