Using multiple shaders

Currently I have two shaders, they are almost the same and so use

uniforms that have the same name and values. The main difference is

that one shader uses discard for 1 bit alpha. When I change shaders I

have to upload uniforms that have changed since the shader was last

used and so there is code to keep track of the current uniform value so

if it has changed it can be sent again when the shader changes.

Is there away I can aviod all this extra ‘management’ work for the CPU?

In

DX shaders you can have a ‘pool’ of shared varibles (uniforms) that are

shared between shaders and so for example the projection matrix only

has to be uploaded once when it changes and not for every shader.

Anther

thing you can do in DX shaders is state the constant register a varible

(uniform) is using so you can get the same effect as the pool code.

Can we do either in GLES 2.0???

No, OpenGL ES 2.0 has no way of explicitly sharing uniform values between programs. It should be relatively easy to encapsulate pairs of programs like this in an object that keeps track of the uniform values, though. Alternatively you could simply set the uniform values on both programs at the same time. There is some overhead to this, but it might be insignificant.



I did have a thought, instead of doing code to manage this could I just use 'glGetUniform' on the uniforms they share to get the current values, activate the new program, then set the uniforms?

What is the cost of 'glGetUniform'?

Thanks,
Richard e Collins.

RichardUK2009-03-09 10:48:47

You could, but it seems to me this would require just as much code as storing the values yourself. The overhead would certainly be higher.

Is glGetUniform doing more than just returning a copy of a local store? As the API supports a ‘get’ on uniforms I had thought that it would be coming from an internal local store and not from the chip and so my code would only be unnessarily duplicating this.

Doing the code my side off the API means every time I set a uniform I need to record it and so increasing memory bandwidth usage. Something i’ve always tried to advoid on mobile chips.

Using the glGetUniform I only add ‘work’ for the CPU when the shader changes. Read current uniforms, change shader, set uniforms. (last stage has to be done with both methods)

But if glGetUniform has to do more than just reading a local store then yes not a good idea. In DX using a “Get” function is not a good idea and so i’ve always tried to advoid it with all 3D api’s including GL.

Seems the lack of shared uniforms in the shader language is bit of an oversight, it’s causing extra work for the CPU.



glGetUniform needs to at least perform error and type checking, context and program lookup, so that is an overhead comparing to accessing a local variable. But I really think you’re worrying too much about micro-optimizations. The bandwidth required for storing uniforms should be negligible, and putting a wrapper class around your shader pair that keeps those values should require only a few lines of code.

That is true. The killer here is the use of discard and so splitting the shader is the bottom line, only want discard in a shader if it’s going to be used.

I’ve done the code and there is not much to it. I guess coming from the old 8bit days when writing 16 dwords was a big deal I do fall into that trap from time to time. :wink: