Advertisement Jump to content
Sign in to follow this  
Aqua Costa

DX11 [DX11] Constant buffers per material or per shader

This topic is 2685 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Most of my shaders have a constant buffer that holds material related constants.
Now I have two options:
-Create a constant buffer per shader, and update it using Map() every time I switch between materials.
-Create a constant buffer per material and only update it once when the material is loaded since the parameters of materials are constant, so when I change materials I only have to bind the current material constant buffer to the pipeline.

So basically I have to choose between updating a constant buffer multiple times between frames or use many constant buffers? Since constant buffers are small (less than 128-bytes per buffer) I don't think that I will run out of memory, on the other hand, since constant buffers are small mapping them is probably fast?

What's your opinion? And how do you do it?

Share this post

Link to post
Share on other sites
I'd go with creating one material-related cbuffer per material.

If cbuffers are implemented as a proper GPU resource, residing in GPU-RAM, then you really don't want to be mapping the same object more than once per frame.

Not specific to cbuffers here, but generally speaking about GPU-RAM allocated resources, let's say you've got the following situation:
1) Map Resource "A", write data [X] into it, Unmap it.
2) Issue some draw commands that require Resource A.
3) Map Resource "A", write data [Y] into it, Unmap it.
4) Issue some draw commands that require Resource A.

i.e. The draw commands at (2) require the data from (1)/[X], and the commands at (4) require the data from (3)/[Y].

By the time that you reach step (3), the GPU almost certainly hasn't yet finished step (2) -- the GPU could well still be processing the commands that you sent it last frame.
This means that the data [X] that you uploaded in (1) can't be overwritten yet, as the commands from step (2) that are dependant on that data are still pending.
So, during step (3), the driver has to allocate an eniterly new resource to store [Y], but it also pretend to you that it's actually the same "A" resource you've been using all along! i.e. The resource "A" is now managing two different RAM allocations: one containing [X] and one containing [Y], and as you map/unmap and as commands are completed by the GPU, the driver has to remember to free up these extra allocations.

These kinds of internal implementation details are optimised by choosing the correct "usage" flags. For example, if you did have a resource which you wanted to constantly update like this, you should mark it as "dynamic". Alternatively, if you've got data which you can set just once upon load, then you should mark it as static/immutable/CPU-write-only/GPU-read-only etc... These details will greatly help the driver in choosing the best allocation strategies for your resource.

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!