Fast shader switching

As a future feature for GLSL, we could have something like subshaders or lego-shaders.

Let’s assume we have multiple version of our base shader.

varying float LightIntensity;
varying vec3  MCposition;

uniform vec3  LightPosition;
uniform float Scale;

void main(void)
{
    vec4 ECposition = gl_ModelViewMatrix * gl_Vertex;
    MCposition      = vec3 (gl_Vertex) * Scale;
    vec3 tnorm      = normalize(vec3 (gl_NormalMatrix * gl_Normal));
    LightIntensity  = dot(normalize(LightPosition - vec3 (ECposition)), tnorm) * 1.5;
    gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Now the other version just add a few instructions to this, so why not have a label in there

varying float LightIntensity;
varying vec3  MCposition;

uniform vec3  LightPosition;
uniform float Scale;

void main(void)
{
    vec4 ECposition = gl_ModelViewMatrix * gl_Vertex;
    MCposition      = vec3 (gl_Vertex) * Scale;
    vec3 tnorm      = normalize(vec3 (gl_NormalMatrix * gl_Normal));
    LightIntensity  = dot(normalize(LightPosition - vec3 (ECposition)), tnorm) * 1.5;
    gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;

   gl_Label 0;  //<<<<<<<<<<<

}

and we upload a subshader

glUseProgramObjectARB(BaseShader);
glBindSubShader(SubShader, Label0Location, yes_put_it_in);

and we unload a subshader

glUseProgramObjectARB(BaseShader);
glBindSubShader(NULL, Label0Location, no_take_it_out);

Dumb idea or what?
If future shaders become very large, needing many uniforms and instructions, this could be a form of optimization.

/edit/small corrections

I see your point. This feature could definitely be useful. Well, i could think of using it as an optimization, by being able to en- or disable some feature (ie. parallax mapping) for surfaces, which don´t use an effect.

However, it would only be useful, if this “state-change” gets done a lot faster than an actual shader-change.

And the question is, if this is possible.

Maybe it would be easier the other way round: Defining the complete shader, with all its details, but also defining parts, which can be disabled. This way the whole shader could be in memory and the driver doesn´t has to bother about adding a subshader, but only about disabling it.

At the moment this is possible with dynamic branching, but this would be something between dynamic branching and static branching (where parts can get kicked out at compilation time).

I´d definitely like such a thing.

Jan.

We don’t really need any new API for this functionality. Just use a bool uniform:

varying float LightIntensity;
varying vec3  MCposition;

uniform vec3  LightPosition;
uniform float Scale;

uniform bool useSpecialEffect;

void main(void)
{
    vec4 ECposition = gl_ModelViewMatrix * gl_Vertex;
    MCposition      = vec3 (gl_Vertex) * Scale;
    vec3 tnorm      = normalize(vec3 (gl_NormalMatrix * gl_Normal));
    LightIntensity  = dot(normalize(LightPosition - vec3 (ECposition)), tnorm) * 1.5;
    gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;

  if (useSpecialEffect){
    // Do special stuff here

  }
}

The driver can then look at the useSpecialEffect variable and disable parts of the shader that’s being excluded with this change.

i think its better doing what i sujjested recently here and creating an ubershader, sure youre gonna have more shaders at the end (not a major issue though is it) but each is gonna be preciesly tailorer for what u want thus should go quicker, also theyre easier to debug. after each shader is compiled i output the vs+fs shader source into a single file, thus getting an overview of exactly what is getting executed in the shader, so i can see if theres any superfluous stuff

@Humus: I was asking myself, if this was already possible. I always thought a “static branch” was only possible, if the variable is a constant value (just like an #ifdef), and i thought this was not possible with uniforms.

But, well, if it works with uniforms, this would be absolutely great.

Too bad, i am forced to use fragment programs, at the moment, and cannot use glSlang.

Jan.

Yes, I guess using a uniform would suggest to the hardware/driver to do this kind of thing. I guess the only benifit left would be that this feature gives user control.

I’m pretty sure no one is doing this now.

Last time I tried some looping, branching on a ATI, it exceeded instruction count and ran in software. I estimated the i-count to be 256, as is the case of vs 2.0 hardware.

PS: I may use GLSL commercially soon. Depends on client.

Ok I’m not experienced with GLSlang yet, but from what I remember/read:

Static Branching = using an uniform in the condition test, so that the driver can modify the shader before sending it down the chip. (No hardware branching, it’s handled by the driver because the value is known before running the shader.)

Dynamic Branching = using a var you set during the shader life, so that cannot be known before hand, and such require the hardware to be capable of doing branching.

Ok I’m a little off topic, but is this correct ?

Yeah, that’s about right. However, static branching doesn’t have to mean the shader is modified. For instance in vs2.0 you have branching based on constants, including for-style loops. So it’s still dependent on values not know at compile time. You can however not use values from attributes or something else for branching in vs2.0 and I think nesting is not allowed.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.