Recommended Posts

I tried to find some information about how I should create constant buffers. I know that I should create constant buffers per frame or per object...

But every tutorials which I found, use Effects for rendering(which are deprecated, I'm try to move on new approach) Nvidia SDK, DirectX SDK even Books.They create one huge buffer and used it throughout all shaders in Effect(I don't know if this is good approach, but what I read -> it isn't).

I insert every shader into its own file. My question is, should I create constant buffer for every shader, for example: I used in VS ViewProj and CameraPosition, but in DS I used CameraPosition too and I don't know, maybe TextureTilingFactor (both Buffers are updated per Frame). I Should create one CB for VS and one for DS, or should I create one buffer which has this three elements and follows this approach as shaders will be more and more?

My second question is about shaders. Now I'm using small numbers of shaders(max 8) but if I want to create a game(in the future) and this shaders I'll have about 100(I don't know how many shaders uses game) which approach is good to manage them, some flexible and powerful solution?

Thanks for answers.

0

Share this post

Link to post

Share on other sites

Here's what I've done in the past which seemed to work fairly well (disclaimer: the technique I'm about to describe was never used in a shipped title, so it may not hold up under the stress of a full game, but it worked well enough during the early stages of development)

Any resource (constant buffer, texture, sampler) that the shader had access to I split into two categories: "system" resources and "material" resources. System resources were things that the game engine would create, manage and provide to the shader, and material resources were things that the material would provide (a material, in case you're wondering, is essentially just a collection of constant buffers/textures and GPU state settings, it's authored by an artist and stored on disk as data). For example, a system constant buffer might contain the model, view and projection matrices, whereas a material constant buffer might contain a specular power field, model diffuse color, or some other constant, artist authored value.

I denoted any system resource by naming it with a special prefix ("sys" in my case). So the constant buffer that contains the transformation matrices might look like this:

I would put the system constant buffer declarations in a header file, and any shader that wanted that particular system constant buffer's data could include the header file to get that constant buffer. Then, when I loaded the shader at runtime, I would look through all the constant buffers used in the shader and determine which ones were system constant buffers (by seeing if they had the "sys" prefix) and keep track of which system constant buffers the shader used. When I bound the shader to the pipeline, I would make sure the system constant buffers that shader used were up to date and bound to the correct location. That way any shader could use any "system" constant buffer and no programmer would have to worry about getting the correct constants bound to the pipeline, it would all happen automatically.

I could have as many shaders as I wanted in the game, and it wouldn't require me to duplicate constant buffers. I would only have one copy of each system constant buffer, and it would get bound whenever a shader that used it got bound.

The other category of constant buffers is the material constant buffers. They are much simpler. When our data got built, the material builder would build these constant buffers directly into the material file. Then at runtime when the material was loaded, that data would be used to create a constant buffer, and when the material was selected the constant buffers it contained would get bound as well.

I've glossed over some stuff because this post is feeling kinda long, but if you want me to explain anything in more detail just let me know

Share this post

Link to post

Share on other sites

My primary question was: Should I create two buffers for this example or should I insert this variables inside one big CB?

Sorry, didn't quite understand your first question originally. I've got it now, though. I would have one CB for the gViewProj and gCameraPosition which gets bound in the VS and wherever else it's needed, then I would put the tessellation stuff in a separate CB that only gets bound to the tessellation stages. In addition to being a conceptually separate set of parameters, the tessellation factors seem like something that would probably get updated more frequently than the view/proj matrices, so it would be best to put them in their own CB.

If you have two shaders headers files and insert both of them inside one shader, how do you handle this:

My setup will actually let the compiler put the constant buffers wherever it wants, and the runtime will make sure everything is bound to the correct location. This is a tiny bit complicated, and it might actually be better to do it the way you suggested, with system buffers using bind points 0-7 and material buffers using 8-15. But either way works!
Edited December 7, 2013 by Samith