Sign in to follow this  
n00body

Material Shader Instances

Recommended Posts

n00body    345
I had an idea recently, and just wanted to ask a few questions about its feasibility. Though it has probably been done before, I thought I should ask to make sure. Concept: The concept is targeted at pre-SM4.0 hardware, where I don't have access to uniform buffers. Here, material is defined as a unique combination of a shader, parameters, and textures. Loading:
  1. Determine shader needed by material, loading it or finding handle.
  2. Copy shader and assign a unique instance to the material.
  3. Look-up shader instance's uniforms' handles to set per-material values.
  4. Look-up and store shader instance's uniforms' handles for per-frame values.
Rendering:
  1. Set material's shader instance to effectively set material-specific parameters.
  2. Use stored uniform handles to set per-frame parameters.
  3. Render objects with material.
The whole point here is that I want to set per-material parameters exactly once, and never worry about them again. This way, I can avoid the need to store the per-material parameter values & uniform handles. Thus, I only need to store a known set of material-agnostic per-frame uniform handles. Questions:
  1. Is it more expensive to set a new shader, or to set several shader parameters in succession?
  2. Do shaders retain the value of a parameter when we set another shader?
  3. Will it eat up a lot of memory if I give every material its own copy of a shader?
  4. Has anyone else tried this kind of system? How was your experience when using it?
Thanks for any help you can provide.

Share this post


Link to post
Share on other sites
MJP    19787
I can't comment on anything OpenGL-related, but I can tell you how things work in D3D9.

Shaders in D3D9 don't carry any register state with them. The device exposes a flat set of float, bool, and int registers (for constants, static branching, and loop control respectively) that you manipulate with the IDirect3DDevice9::SetVertexShaderConstant* and IDirect3DDevice9::SetPixelShaderConstant*. Once you set the value of a register, it is part of the device state and will stay the same even if you switch shaders. Creating many instances of the same shader won't gain you anything in this regard, instead it will just increase CPU overhead and waste memory.

In your case you would need to either store material-specific parameters as part of the material and set them when the material is going to be used, or create/use some sort of framework that abstracts away shader constants. The D3DX Effects framework is an example of this sort of framework, since each Effect instance can store a unique state for all shaders parameters used by the Effect. Then when you apply the Effect, it sets all of these parameters onto the device along with the shaders. Effect's also support creating a "Clone", where clones internally have a reference to the same instance of all shaders but maintain a unique set of shader parameters.

Share this post


Link to post
Share on other sites
Hodgman    51336
Quote:
Original post by n00body
Do shaders retain the value of a parameter when we set another shader?
I don't think so, which means this wont work.
AFAIK, when you change shaders, all the existing uniform values will still be set (it won't revert to the uniforms that were set last time this particular shader was used). I could be wrong though, I'd have to go check the GL spec...

Setting a uniform is basically just pushing a value into a GPU register - I don't think each shader carries around a backup of these registers, they just use whatever values are in them at the time.

Share this post


Link to post
Share on other sites
karwosts    840
I think you are incorrect Hodgman.

From the orange book:

"One advantage of the default uniform block is that the uniform storage is associated with the program object... Their values can be modified only when the program object is part of current rendering state, but the values of uniform variables are preserved as the program object is swapped in and out of current state."

Also saw this which may be of interest to the OP:

"One disadvantage of the default uniform block is that changing a uniform value is relatively expensive, so uniforms in the default uniform block are best reserved for infrequently changing uniform values."

You can guess for yourself what "relatively expensive" means.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this