Structured Buffers vs. Constant Buffers?

Started by
2 comments, last by MJP 11 years, 11 months ago
What're the differences between structured buffers and constant buffers? From their name alone I'd assume you want to set up your constant buffers at the start of execution to hold your constant values, but I've seen guides (even on MSDN) showing how to update them every frame, which I would hardly call constant.

Whereas I can't find all that much information on structured buffers, just the odd forum post here and there. I can't even see a single thing on the MSDN about it, but I know they can be used to pass data from the CPU to the GPU.

So let's say I have three scenarios:

1) I have a depth of field shader, but I allow the user to specify the size of the blurring kernel at run time. I then build an array of length kernelsize*2 of Vector3s for sampling offsets and weightings combined. I want to pass this to the shader, but I only want to do it when the user changes the blur kernel size, not every frame.

2) I have a view matrix and a projection matrix, I want to send the view matrix to my shaders every time the viewpoint moves, however I only want to send the projection matrix at the start of the program, as I assume it will never change.

2) I have a list of lights in the scene, every frame I calculate which lights are near the player and send their positions and colors to the GPU in order to build a light map.

Which method would be best for which scenario and are there any other ways of sending data to the GPU (I'm using SlimDX - but C++ examples should be translatable)?

I realize this is quite basic, but I just can't find any good resources on, well, shader resources.
Sole Creator of Pigment - a procedural, block-base space trading sim.

PhD student working on medical imaging at the University of Southampton.

Enjoyer of games, films, books and cider.
Advertisement
Hi!

As you probably have noticed, from a programmer perspective structured and constant buffers are used quite similar, though there are some major differences between them.

Firstly their memory access work differently.
A constant buffer is extremely fast if all threads in a warp access the same value. But, if all threads read from different spots the reads are serialized – a phenomenon called constant waterfalling, which makes the reading slow (causes headache for people doing bone animations). In all the scenarios you described above, every threads reads from the same address, so I’d go with constant buffers, except maybe for the third scenario (in case you have many, many lights).
Structured buffers on the other hand utilize the unified cache architecture, which means the first read is slow, but all subsequent reads are very fast (if the requested data is already in the cache).

Secondly, their usage is limited.
Constant buffers are so fast, because they are in special registers (constant registers) of which we don’t have much (about 64KB). Structured buffers are not placed in constant registers, which means we generally have more space available. Thus, if the data you want to read gets big, you have to move from constant buffers to structured buffers (e.g. for accessing a huge light list).
Structured buffers can’t be bound to any point in the pipeline, which means not as a vertex buffer etc. They were introduced for DirectCompute on Dx10 hardware, since Dx10 hardware doesn’t allow random-access writes on typed resources (textures, vertex buffers etc). Though, you can read from them in every shader stage.
A structured buffer has some really nice candy. It can have a “hidden counter”, which can be accessed by multiple threads (even from different thread groups) to count things. Curiously this counter is a little bit faster than using an interlockedAdd on a byte address buffer (another untyped resource with much more applications, since it can be bound everywhere, unlike structured buffers.)

Cheers!
Thanks for the update, that's a really in-depth and helpful response. I think I'll go with StructuredBuffers when I eventually get around to lighting my engine, because I really can't be sure how many lights I'll need.

Thanks very much :)
Sole Creator of Pigment - a procedural, block-base space trading sim.

PhD student working on medical imaging at the University of Southampton.

Enjoyer of games, films, books and cider.
The word "constant" refers to the fact that the values are constant during the execution of a shader program, and doesn't imply that the values can't be changed by CPU. The term comes from the pre-DX10 days when you just had a handful of constant values defined in a shader, which were referred to as "shader constants".

The intended use case for constant buffers is small amounts of heterogeneous values that you want to be directly accessible by name within your shader. So your example of having a view and projection matrix is perfect for a constant buffer. A structured buffer is essentially an array of homogeneous structures, just like an array of structs. So if you have a lot of elements that you want to be indexable in the shader, then you want to use a structured buffer. Your example of a list of lights is a good candidate for a structured buffer.

For your DOF shader you could do either, although it will be a bit more expensive if your shader contains an actual loop with an indexed read from a buffer. In the case of an indexed read all threads will repeat the memory access, while for a static constant buffer read it will be more optimized. To get a static read you need to ensure that the loop is unrolled, which may require different permutations of the shader for different loop iterations.

At any rate, modern GPU hardware is pretty generic and there isn't always going to a big difference between different abstractions provided by the API. Things are much different than the older days of GPU's from DX9 and earlier, when the hardware was less flexible. And of course when it comes to performance, you should be sure to profile if you want to know for sure what approach is faster.

This topic is closed to new replies.

Advertisement