It's a good idea to combine single and instanced drawing in the same shader?

#1

Hello, I have an aplication where I have two different shaders, one for normal ( single ) draw calls and other one for instanced draw calls, the effect of the shader is the same, the different between both is that while in the normal draw shader I stored the model matrix in a mat4 uniform, in the instanced shader I have the model matrix for each instance in a vertex attribute using AttribDivisior.

So now I am considering combine both shaders in only one, in order to achieve it, I plan to declare my model matrix uniform as an array of mat4, the normal draw call would use only the index 0 while the instanced would use one index for each instance.

Then the main difference is that in instaced mode the model matrix would be an unifrom array instead of an attribtute.

I have no idea about if in terms on perfomance this change is noticiable.

So what is your opinion?

PD: In my instanced draw call I have arround 250 instanced primitives.

#2

Do you need both? That is, have you considered eliminating the former and just using the latter (with instance count = 1)? If you do need both for some reason…

Since you have your instance shader pulling in the value via vertex attributes, why not do the same for the “normal draw” case? That is, feed it in via the same vertex attributes. Then you’ve still got both permutations but can use the same shader. Failing this…

You could push this out to uniforms as you suggest. But whether or not it’s more efficient is going to depend on what you’re bottlenecked on now and the details of your graphics driver/GPU/system. If your instances have very few verts for instance, you might very well be bottlenecked on that and not pulling in instance transforms.

#3

Thanks one more time for your response Dark Photon,

The two shaders ( instanced and not instanced ) do the same light calculation , I don’t know If I need both, this depend if using an uniform array instead of a vertex attribute per instance have good perfomance. I want to combine these two shaders and others becuase every time that I create a new shader I have to write two versions: one for instanced and another one for not instanced.

The problem of this is that the instanced primitives are static objects, but the not instanced primitives it is possible that they are dynamic. Then using the instanced style shader with count 1 for a dynamic primitive I would have to update the VBO each time that the primitive have changed its transform, which is a quite expensive operation according to my experience. That’s why I prefer to use an array of uniform for both.

#4

Then make it not be “a quite expensive operation”. Persistent mapping with multiple buffering is generally a win performance-wise. Individual changes to a shader might be it in the short term, but if you’re rendering lots of dynamic geometry, a sequence of writes to mapped buffers may win in the long term.