Regarding use of Multiple Shaders

Hello everyone,

I have a bunch of animations done in a scene. These animation effects are achieved in different shaders. This is how I’m using multiple shaders.


void renderScene(void)
{
      draw.init();
 
      shaderList[0]->attachShader(programObj);
      render object 1

      shaderList[1]->attachShader(programObj);
      render object 2

      ...
      // This is done in a loop.	
 
      draw.SwapBuffers();
}

Now, is there a better way to achieve this? Or is this fine?

PS: All initialisation(reading and compiling) of shaders is done just once at the beginning.

Thanks!

Why wouldn’t it be? If you deem the cost or shader complexity resulting from dynamic branching inside the shader to be unbearable then using multiple shader for different objects is your only option. If not, then you’ll want to pass the shader some information as to which animation code path to use depending on the object. This will of course incur costs for setting uniforms but has the benefit of a unified shader for different approaches.

Still, as long as you sort objects by shader and thus minimize program switches you should be fine. In any case, the effect of any code reorganization can only be objectively determined by measuring the actual impact.

Thanks for the reply Thokra

What is the general approach followed? In case of games they have so many complex animation effects. They would be using mutiple shaders right? Having multiple effects in one shader and then deciding the effect based on a Uniform would be a little complex right?

I don’t believe there is a general approach to this as it depends on the number of shaders, their complexity, targeted hardware, scene complexity and so on.

What I remember from reading some Crytek presentation a while ago is that for handling a huge number of shaders they employed a dedicated shader compiling framework tasked with creating multiple permutations of a shader depending on the concrete usage. Still, they used HLSL and the D3D compiler allows to influence the shader compilation using flags and so on. All the stuff we don’t have with GLSL.

I think it is best to determine if multiple effects have enough similarities to be packed into a single shader and branch dynamically. Otherwise I’d suggest using dedicated shaders for each task.

Thanks for the suggestion thokra!

Do you always change program for each object that you draw? In which order you render your objects?

You can improve performance by reducing the number of times you change the program. Sorting objects by program, where possible, can improve performance. So if you have programs A and B, rendering A A A A B B B B can be faster than A B A B A B A B.

Forgive me for hijacking this topic to add another related concern that perhaps the OP will find interesting too:

Is it sensible to assume that the driver will cache program loads?
In your example of an ordered AAAABBBB, would a client cache system be needed to stop program A from being loaded multiple times or would it be sensible to consider the driver will handle this?

Personaly, I’ve implemented a local way of to make sure I don’t do multiple calls to load the same program, but it’s something I’ve been wondering for a while if it was needed and the question fits with this topic.

I’m pretty sure the driver does not anticipate any concrete order of shader usage. Furthermore I believe it is impossible to predict which programs could and should be cached. Especially in dynamic, interactive scenarios.

NVIDIA and AMD don’t suggest sorting by material/shader for nothing. :slight_smile: