Search code examples
c#directxpaddinghlslsharpdx

Does a float3 in a constant buffer secretly add padding?


I have a cbuffer in my shader.fx file, like so:

cbuffer lights : register (b1)
{
    float4 Light1Color;
    float3 Light1Direction;

    float4 Light2Color;
    float3 Light2Direction;

    float4 Light3Color;
    float3 Light3Direction;
}

I had some issues filling this cbuffer from my code, it ended up being an array of the following struct:

struct Light
    {
        public Color4 Color;
        public Vector3 Direction;
        //For whatever reason the constant buffer that we fill with this 
        //light must have a bytesize that is a multiple of 16, so we add a float (4 bytes)...
        public float padding;
        public static int SizeInBytes = (4 * 4) + Vector3.SizeInBytes + 4;
}

I wrote the array into the cbuffer by using a DataStream(SharpDX). This DataStream was NOT happy when I didn't have the padding in my struct, but this padding is not there in my shader.
The resulting lights are correct, which to me means that this padding float that has been written is either ignored, or secretly added in the shader.fx during compilation.

Which one of those is true? If any?


Solution

  • See: 'Packing Rules for Constant Variables' (https://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx)

    ... Additionally, HLSL packs data so that it does not cross a 16-byte boundary. Variables are packed into a given four-component vector until the variable will straddle a 4-vector boundary; the next variables will be bounced to the next four-component vector.

    You could pack some components into 'unused' space with the packoffset modifier. However, this doesn't fit your data structure very well. (https://msdn.microsoft.com/en-us/library/windows/desktop/dd607358(v=vs.85).aspx).