Constant buffers and shader variables

Started by
2 comments, last by WhiskyJoe 9 years, 11 months ago

Hey guys,

Coming from an OpenGL background, I have recently been playing around with DirectX11 and so far it's going alright. I am however getting sort of stuck on how to properly make use of constant buffers and how to use them with different shaders in an efficient way.

As far as I understand, you need to make use of the constant buffers to pass variables from code to the shaders and ideally "sort" them by update execution for efficiency. It makes sense and I get that part, I'm a bit stuck however on when I need to work with multiple different shaders. As an example:

Let's say I have 2 shaders that have some variables that needs updating every frame. Shader 1 needs 1 float and shader 2 needs 2 floats to keep it simple.

Ideally I would use one constant buffer for both of them (I guess?) as they both need to update every frame. But when you create the buffer, you need to supply its bytewidth which is different for both the shaders. How would I handle a situation like that? Is there a way to update the constant buffer or is it a thing to make the constant buffer a "max" size or something?

I can't imagine it's efficient to make a constant buffer for every shader that has a different set of variables. Perhaps there is some other way? Any info is much appreciated! smile.png

Advertisement

It makes sense that different shaders have different constant buffers. One trick that you can do if you are trying to get some global variables is you can create a header file.


// MyGlobalShaderHeader.hlsli

cbuffer globalEveryFrame : register(b0)
{
     matrix viewMatrix;
     float4 elapsedTime; // size needs to be multiple of 16 anyways
} 

And lets say you are using this for vertex shader. Then you can set it once in the beginning of rendering


deviceContext->VSSetConstantBuffers(0, 1, &myBuffer);

Now you can use it for all the vertex shaders that include that header. Only thing you need to be careful about is you have to make sure that you don't change register 0 between shaders that need those global variables.

So if you are trying to create a global buffer you can use that trick. But if those variables are shader specific I think it is better idea to have different constant buffers for different shaders. It is much more manageable that way. So every material can know which buffers they are responsible from.

One side not though as I wrote in the comment above constant buffers are automatically become multiple of 16 bytes. So lets say you put 1 float2 and 1 float it occupies float4 space. So when you are setting your bytewidth it needs to be multiple of 16 bytes otherwise you will get an error.

I can't imagine it's efficient to make a constant buffer for every shader that has a different set of variables. Perhaps there is some other way? Any info is much appreciated!


You can still set variables the old-fashioned way. You can also use per-instance vertex attributes. Otherwise, though, it is indeed best to use multiple constant buffers per material interface (i.e. shader signature). It's not any different than using OpenGL's uniform buffers, if you're familiar with those.

A common approach is to use a "material" abstraction that contains a combination of the shader, constant buffers, and textures/samplers. This is then use by one (or preferably many) models, which are comprised of meshes and materials. More complex rendering pipelines and material systems become necessary as you ramp up to more intricate graphics, but the basic concept remains fairly similar.

Sean Middleditch – Game Systems Engineer – Join my team!

Hmm ok. I can see the benefits and how it makes sense, it's just that I was used with OpenGL that I could simply call glUniform3fv and all its variations and it would set the variable, but looking back at some of the old code, this was essentially also on a per material basis with the only difference that I didn't need to specify a buffer beforehand.

I have seen the light! Thanks a bunch guys! :)

This topic is closed to new replies.

Advertisement