Using d3d11, I have two cbuffer in a vertex shader that's
cbuffer A{
float2
float2
float2
float2
};
cbuffer B {
uint2
uint2
float2
float2
float2
float2
};
Their buffers are created and run on my vertex shader successfully.
However when I add a bool to the second cbuffer:
(c++ side)
struct B {
uint32_t, uint32_t,
uint32_t, uint32_t,
float, float,
float, float,
float, float,
float, float,
uint32_t
};
(hlsl)
cbuffer B {
uint2
uint2
float2
float2
float2
float2
bool
};
CreateBuffer fails with an unhandled exception. The buffer packing all seems fine, the bool should be the first element in a new row after the 48th byte. Anyone know what the issue could be?
Directx 11 cbuffer
sizes must be a multiple of 16. Prior to adding the bool
the size was exactly 48 bytes, 3x16. Adding the bool puts it out-of-line with the required byte boundary. Add 3 floats (or 3 ints) to put it back on the 16-byte boundary:
cbuffer B {
uint2 var1
uint2 var2
float2 var3
float2 var4
float2 var5
float2 var6
float4 bool_padding3
};
IMO, to make it easier on myself I always pack my cbuffers
in float4
"chunks", that is, each member is exactly the size of a 16-byte row and I store multiple c++-side variables in each. In your case, I'd lay out your cbuffer
like so (names are purely for example):
cbuffer B {
float4 var1_var2
float4 var3_var4
float4 var5_var6
float4 var7_padding3
};
This way I'm guaranteed that the byte boundary is preserved.
Your C++-side struct would change accordingly:
(IntVector2/3/4 are structs that contain x/y/z/w int
members, likewise for Vector2/3/4 but with float
members)
struct B {
IntVector4
Vector4
Vector4
uint32_t //Uh-oh! outside the boundary. Convert.
};
As you can see, by adhering to the int4
/float4
requirement, you can more easily detect that your struct is out-of-boundary and the variable needs to be packed correctly, like so:
struct B {
IntVector4
Vector4
Vector4
IntVector4 //Corrected, guaranteed to be on a 16-byte boundary.
};