Jump to content
  • Advertisement
Sign in to follow this  
pnt1614

How to use a big constant buffer in DirectX 11.1?

This topic is 741 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

Among some DirectX 11.1 features, there is one feature about binding a big constant buffer and specify a range in this buffer for updating at each stage. But I cannot find any examples how to configure and use this feature, is there anyone knowing how to do it? Please help me.

Share this post


Link to post
Share on other sites
Advertisement

Just curious, in which scenarios or stages in the rendering pipeline would it be preferable to use a large CB over several smaller ones?

Edited by KaiserJohan

Share this post


Link to post
Share on other sites

Just curious, in which scenarios or stages in the rendering pipeline would it be preferable to use a large CB over several smaller ones?

This technique (*SSetConstantBuffers1) doesn't have too much benefit outside of simplifying resource management for the driver (a potential reduction of CPU overhead). You can create one buffer resource instead of many (less things for the driver to track), and you can update/map that big buffer in one go instead of having to do many smaller update/map operations. This is especially useful if your engine is structured in such a way where you're able to update the constants for many objects at a single point in the frame (after updating the game logic for all of them, but before drawing any of them).

 

In the general case, you should generally use as few buffers per draw as possible, as every resource binding incurs CPU overhead... However, if you take that advice to the extreme, ever draw call would use a single cbuffer containing every constant/uniform variable that it requires, which creates a different problem: now the CPU is doing a lot of CBuffer updates -- one very large update per draw... So you also want to use as many buffers per draw as possible in order to reduce the number of cbuffer updates required. Yes, that's two opposite rules of thumb :lol:

This sweet spot in the middle of those two bits of advice generally means separating constants by update frequency -- so a draw might have a cbuffer for things that change once per frame (camera matrices, etc), things that change once per material (colours, scales, etc), and things that change once per mesh (world matrix, etc)...

Share this post


Link to post
Share on other sites

The main difference is rather in the amount of maps you have to do.

 

In D3D11, if you have to draw 100 objects each with individual settings you have to options (let's suppose you only want to send a float4):

  1. Create one Const Buffer of 16 bytes. Map it 100 times with MAP_DISCARD.
  2. Create 64 Const Buffer of 16 bytes each. Map each once (still 100 times total). Probably use MAP_DISCARD.
  3. Create one large const buffer (i.e. 64kb); map it once and use baseInstance to index into an array. In shader you would do value[baseInstance]. This adds some GPU overhead (shader now needs to perform an indirection, baseInstance requires a vertex buffer dedicated to instancing because SV_InstanceID always starts from 0); but now you only map once.

Regarding options 1 vs 2; Fabian Giesen had its experience where option 1 beats 2.

 

D3D11.1 added a 4th option:

  • Create a very large buffer (virtually no upper limit); map it entirely once. When you're done with it; you can bind the particular region you've written to.

This combines the goodies of both worlds: No GPU overhead from option 3 and no CPU overhead from mapping 100 times. You only need to map once. Granted, you now need to bind the buffer 100 times. But in terms of driver overhead, mapping is very expensive and binding a sub region is cheap.

(note that in some cases option 3 may still beat option 4; GPUs are complex parallel machines. However you can now perform option 3 without being restricted to 64kb limit and can use SV_InstanceID now that you can specify where the const buffer starts while binding)

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!