Abuse the immediate constant buffer!

Very often, I need to draw simple geometries, like cubes, and I want to do the minimal amount of graphics state setup. With this technique, you don’t have to set up a vertex buffer or input layout, which means, we don’t have to write the boilerplate resource creation code for them, and don’t have to call the binding code, which also lightens the API overhead.

An immediate constant buffer differs from a regular constant buffer in a few aspects:

  • There is a reserved constant buffer slot for them, and there can be only one of them at the same time.
  • They are created automatically from the static const variables in your hlsl code.
  • They can not be updated from the API.

So when I declare a vertex array inside a shader, for example, like this:

static const float4 CUBE[]={

float4(-1.0,1.0,1.0,1.0),

float4(-1.0,-1.0,1.0,1.0),

float4(-1.0,-1.0,-1.0,1.0),

float4(1.0,1.0,1.0,1.0),

float4(1.0,-1.0,1.0,1.0),

float4(-1.0,-1.0,1.0,1.0),

float4(1.0,1.0,-1.0,1.0),

float4(1.0,-1.0,-1.0,1.0),

float4(1.0,-1.0,1.0,1.0),

float4(-1.0,1.0,-1.0,1.0),

float4(-1.0,-1.0,-1.0,1.0),

float4(1.0,-1.0,-1.0,1.0),

float4(-1.0,-1.0,1.0,1.0),

float4(1.0,-1.0,1.0,1.0),

float4(1.0,-1.0,-1.0,1.0),

float4(1.0,1.0,1.0,1.0),

float4(-1.0,1.0,1.0,1.0),

float4(-1.0,1.0,-1.0,1.0),

float4(-1.0,1.0,-1.0,1.0),

float4(-1.0,1.0,1.0,1.0),

float4(-1.0,-1.0,-1.0,1.0),

float4(-1.0,1.0,1.0,1.0),

float4(1.0,1.0,1.0,1.0),

float4(-1.0,-1.0,1.0,1.0),

float4(1.0,1.0,1.0,1.0),

float4(1.0,1.0,-1.0,1.0),

float4(1.0,-1.0,1.0,1.0),

float4(1.0,1.0,-1.0,1.0),

float4(-1.0,1.0,-1.0,1.0),

float4(1.0,-1.0,-1.0,1.0),

float4(-1.0,-1.0,-1.0,1.0),

float4(-1.0,-1.0,1.0,1.0),

float4(1.0,-1.0,-1.0,1.0),

float4(1.0,1.0,-1.0,1.0),

float4(1.0,1.0,1.0,1.0),

float4(-1.0,1.0,-1.0,1.0),

};

…and if I want to draw this cube, then the simplest vertex shader should look like this:

float4 main(uint vID : SV_VERTEXID) : SV_Position

{

return mul(CUBE[vID], g_xTransform);

}

(where g_xTransform is the World*View*Projection matrix from a regular constant buffer)

I would then call the Draw from the DX11 API with a vertexcount of 36 because that is the array length of the CUBE vertex array. The shader automatically gets the SV_VERTEXID semantic from the input assembler, which directly indexes into the vertex array. I find this technique very clean both from the C++ side and the shader side, so I use it very frequently.

A few example use-cases:

  • Deferred light geometries
  • Light volume geometries
  • Occlusion culling occludees
  • Decals
  • Skybox/skysphere
  • Light probe debug geometries

If you need vertex arrays like this for some other simple meshes:

That’s it, cheers!

2 thoughts on “Abuse the immediate constant buffer!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s