Whats the shader data a Material class holds?

Started by
21 comments, last by Weton 11 years ago

1) Are your binding commands immutable?
2) My difficult is managing the binding commands. Say I have 2 drawables with different materials, each material have different shaders with different cbuffers layout (consider different slots usage only..).
2.a) bind view projection cbuffer (needs current shader slot info)
2.b) bind textures (needs its shader slot info)
3) I cant hold binding commands for none of these groups (except the material group), because they change depending on the current shader/material bound.


1) Yes.


2) I choose to simply be explicit with my cbuffer slot assignments. e.g. across different shaders that will be used in the same stage in the same way (e.g. opaque/gbuffer rendering), I'll choose to assign their camera cbuffer always to slot #1. I do this by defining the camera cbuffer in a header (which contains the register HLSL keyword), which is included into the various shaders.


2.a) If you've got the ability to enforce that every 'camera' cbuffer contains the same layout across shaders, then you've also got the ability to enforce the same register numbering scheme across shaders.
2.b) The textures that need to be bound and the shader that will be used by a material are both known at data-build-time, so assuming that the material is immutable, then there's no issue there.

[edit] if it's a runtime generated texture, (for post processing, or a deferred shadow mask in a forward renderer, etc), then I do the same thing as (2.a) -- I enforce that every shader specifies this texture binding on the same slot/register number, so that the same binding command can be used across shaders [/edit]


3) If I were to support that case, then the cbuffer binding command would contain a string and a cbuffer data pointer, and the string would be converted to a slot# at draw-time. This is pretty inefficient though, so I don't do this and instead do the above.

Advertisement

My difficult is managing the binding commands. Say I have 2 drawables with different materials, each material have different shaders with different cbuffers layout (consider different slots usage only..).

(Are you using shader permutations? If not you should consider start using them.)

Different materials simply use different permutations of the same shader. So make the cbuffers layous the same in all permutations. (Check the 2nd paragraph of Hodgman reply to that topic).

Sure you'll be binding some data that is not needed in some cases, but you won't have to deal with the complexity that a more dynamic system would introduce. Plus number of bound constant buffers will be the same, so go with the "lame" approach and only try to optimize if you find that it's hurting performance.

I meant materials with completely different shader effects, not just different permutations for the same effect.

In my understanding, you`re not meant to use the same shader for all objects. Do you do something like different queues for different shaders?

This is an interesting thread - I'm getting to my material system very soon - you guys keep mentioning the 'cbuffer' - what exactly is that?

Apologies for piggy backing this one but it might help me and others to understand some of the terminology. Also, what's a 'state group'?

Thanks

This is an interesting thread - I'm getting to my material system very soon - you guys keep mentioning the 'cbuffer' - what exactly is that?

Apologies for piggy backing this one but it might help me and others to understand some of the terminology. Also, what's a 'state group'?

Thanks

cbuffer(constant buffer) is how hlsl shader language handles variables (the ones that will be constant during all vertex/pixel/any shader program processing, like world view projection matrices, color, anything you set for a specific vertex buffer and a draw call), theyr like a struct you create in your shader file, bind to a specific register "index". Check dx documentation for more details.

State group is specific to Hodgman rendering system, it refers to a list of "pipeline states setters", commands that set things like cbuffers, blend state, shaders, texture..etc.

check this post:

http://www.gamedev.net/topic/605065-renderqueue-design-theory-and-implementation/#entry4828468

One can gather a great amount of info by just following Hodgman footprints on these forums.

If you're in OpenGL land, cbuffers are called UBOs (a buffer object that holds uniforms).

State group is specific to Hodgman rendering system, it refers to a list of "pipeline states setters", commands that set things like cbuffers, blend state, shaders, texture..etc

Yeah I use the concept in my engine (described above), but I picked it up numerous other engines that also used the same idea.

Also, in D3D9/10, there are API level "state blocks", which are similar (a container for certain Set<State> commands), but I don't use these wink.png

Thanks guys..

cbuffer(constant buffer) is how hlsl shader language handles variables (the ones that will be constant during all vertex/pixel/any shader program processing, like world view projection matrices, color, anything you set for a specific vertex buffer and a draw call), theyr like a struct you create in your shader file, bind to a specific register "index". Check dx documentation for more details.

So where I just set things like worldviewmatrix and viewprojectionmatrix separately, a cbuffer means you can bundle all that up into one structure and send the whole thing to the shader - I see...

Also, in D3D9/10, there are API level "state blocks", which are similar (a container for certain Set<State> commands), but I don't use these

Thanks, got it now... back to the story, gents rolleyes.gif

Cbuffers are sm4.0+ only aren't they? Meaning DX10+?


Cbuffers are sm4.0+ only aren't they? Meaning DX10+?


Yes. On SM3, I emulate them, which is actually more efficient for me than using something like the Microsoft Effects framework to manage my constants...

But how do you update the cbuffers, if a object moves/is animated etc.?

I think the cbuffer could either be a part of the object, but this would force all types of objects to have a common layout.

Or do you have some kind of offset or pointer array from which you copy the data into the buffers, before you draw the objects? This would allow having different data layouts, but would cause lots of copying of data...

If data is being generated by the engine and then input into a shader, then yes, the shader and the engine need to agree upon the layout of that data.

For a simple object, this might be some standard cbuffer that just contains a 'world' matrix - this is basically the objects 'render transform component'. For an animated object it might be a cbuffer containing an array of bone matrices.

You might have another standardized cbuffer that contains the view-proj matrix that's owned by the camera, etc.

Not every cbuffer layout needs to be standardized like this, just ones that contain data that's generated by the engine, like matrices.

Often material settings (colours, texture scales, etc) can be set just once, by looking up a variables location within a cbuffer by name. In my engine, I build these kinds of material cbuffers offline using a tool (which reads the values from an artist's DAE file, and matches them up with the cbuffer layout written in the shader code), but you can also do this at runtime when necessary.

This topic is closed to new replies.

Advertisement