0
\$\begingroup\$

So I recently had this error: Cbuffer Padding Error

Which has led me to ask this question. Can somebody explain packing/padding in a Buffer for DirectX? I cannot get my head around it, rather than doing this manually there has to be some easier way right?

\$\endgroup\$
7
  • \$\begingroup\$ Have you reviewed the documentation & are there any specific areas you have trouble with? This may make it easier to get answers. \$\endgroup\$ Oct 10, 2016 at 16:01
  • \$\begingroup\$ I have reviewed the documentation but I just cannot figure it out. There's too much Jargon in there for a beginner to understand like 16 byte alignment \$\endgroup\$ Oct 10, 2016 at 16:06
  • \$\begingroup\$ It might help if you think of a cbuffer being composed of float4s rather than floats. Each float4 is 16 bytes. \$\endgroup\$ Oct 10, 2016 at 16:13
  • \$\begingroup\$ Okay thinking of it like that kinda helped. So if I have 1 float4 and 2 float2's does that mean right now the order of bytes (hope that makes sense) is 16, 12, 12? Which will give an error but to fix this I add a float like this float4 xyz; float2 zyx; float pad; float2 zxy; Which means the order of bytes is 16, 12, 4, 12? \$\endgroup\$ Oct 10, 2016 at 16:21
  • \$\begingroup\$ Do you mean 1 float4 and 2 float3s? If so, that's it! \$\endgroup\$ Oct 10, 2016 at 16:26

1 Answer 1

1
\$\begingroup\$

Basically, computers typically like (and sometimes require) data to be aligned on certain byte 'boundaries'. DirectX 11 requires 16 byte alignment and DirectX 12 is 256 byte. You can read about why alignment is good/required on the internet elsewhere. But the short of it is that computers will read multiple values at the same time, in sizes that are powers of 2 (Usually a minimum of 4 bytes at a time).

When things are unaligned, to read a single value, the computer may be required to read multiple regions to fetch the data (or worst case, read single bytes at a time) [..==|==..] (both the first and second slots would have to be read to read the value in the middle, whereas, if correctly aligned, [====|....] could read just the first. (This also has storage implications).

This also means, that when reading a single value that is multiple bytes (say a float4, you may want to align it on its own 16 byte boundary)

You can find sizes of the data types here: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509646(v=vs.85).aspx

Remember that one byte is 8 bits. So, a float is 32 bits, which is 32 / 8 == 4 bytes.

Vectors are just multiples of the scalar (so if float is 4 bytes, float4 is 4 * 4 == 16 bytes).

So, in a constant buffer, you want your values to align to those 16/256 byte boundaries (and will be required to fill up to the next 16/256 bytes).

cbuffer {
    float2 position; //offset = 0, size = 8
    float2 texcoord; //offset = 8, size = 8
    //16 byte boundary
    float3 normal;   //offset = 16, size = 12
    float  padding;  //offset = 28, size = 4
    //16 byte boundary
    float4 tangent;  //offset = 32, size = 16
    //16 byte boundary
};
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .