GLSL shader and subroutines

Hello,
I would like to ask if there is Panda3D (v. 1.10.3) native way to setup GLSL shader subroutine similar to OpenGL example below (I was not successful in finding any useful lead):

Shader:

subroutine vec3 shadeModelType(vec4 position, vec3 normal);
subroutine uniform shadeModelType shadeModel;
...

subroutine(shadeModelType)
vec3 phongModel(vec4 position, vec3 norm) {
    // The ADS shading calculations
}

subroutine(shadeModelType)
vec3 diffuseOnly(vec4 position, vec3 norm) {
    // The diffuse shading calculations
}

OpenGL application code:

GLuint adsIndex = glGetSubroutineIndex(programHandle, GL_VERTEX_SHADER,"phongModel");
GLuint diffuseIndex = glGetSubroutineIndex(programHandle, GL_VERTEX_SHADER, "diffuseOnly");
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &adsIndex);
glUniformSubroutinesuiv(GL_VERTEX_SHADER, 1, &diffuseIndex);

Following link contains more detailed description of the GLSL shader I’m trying to reproduce in Panda3D:

I’m afraid that GLSL subroutines are not currently supported in Panda.

If you wish, you could file a feature request on our GitHub issue tracker. However, given that Vulkan and SPIR-V never implemented subroutines, I get the impression that subroutines generally are no longer seen as a particularly relevant feature by graphics card producers. Given that our new shader pipeline will be based around SPIR-V, it’s likely that we will never support GLSL subroutines as-is.

However, you could implement this behaviour by using a switch statement that selects different branches based on the value of a uniform variable. This will give you the same effect as subroutines.

I see, thank you for a quick reply.
I understood that subroutines are useful because of performance reasons - there is no real condition inside of a shader itself. On the other hand you are probably right that switch could replace its functionality if I take in account that I’ve read somewhere that modern GPUs have hardware optimization for certain types of shader conditions which do not impact parallelization and I think that this one might be the case.

I do not know much about subroutines, but if I had to guess, I’d say that they should be no better in performance on modern hardware than a branch (eg. if) on a uniform variable (since the GPU knows all warps will take the same branch, so there’s no need to run all the branches).

Assuming that a subroutine behaves essentially like a function pointer, there is still the overhead from jumping to a different code instruction, which is also there with an if/switch. But, perhaps they are more efficient as the number of switch cases increases.

The fact that SPIR-V and Vulkan never implemented this suggests to me that IHVs and ISVs do not consider it worth it any more.

In the “Open GL 4.0 Shader Cookbook” from David Wolff is written about subroutines this:

…but I think you are right that it’s probably a bit outdated statement (published 2011).

Thank you for your input. I will solve it by if / switch and I will move to next shader example :wink: