Search code examples
c++hlsl

HLSL Alignment issues


I have issues with HLSL Buffer alignment. I have a light struct in an array of size 48 (i.e. a shader is meant to hold atmost 48 lights). (Divisiors are markers of 16 byte boundaries)

struct RendererLight {
    float4 Position;
    //---//
    float4 Color;
    //---//
    float4 Direction;
    //---//
    float Intensity;
    float In;
    float Out;
    float Range;
    //---//
    int bakedLight;
    int dynamicLight;
    //---//
};


cbuffer LightsBuffer : register(b1)
{
    RendererLight Lights[48];
    //---//
    int NumLights;
    //---//
};

for some reason, the sizes differ from the c++ side of the structs.

struct ShaderLight {
    Vector4 Position;
    Vector4 Color;
    Vector4 Direction;
    float Intensity;
    float In;
    float Out;
    float Range;
    int baked;
    int dynamic;
    int pad[2];
};

constexpr auto of5 = offsetof(ShaderLight, dynamic); //68 - correct
constexpr auto sz1 = sizeof(ShaderLight); // 80 - i think correct?

struct CLightBuffer {
    ShaderLight Lights[NUM_LIGHTS_PER_BUFFER];
    int NumLights;
    int pad[3];
};


constexpr auto sz = sizeof(CLightBuffer::Lights); // 3840 - incorrect; hlsl assembly says wants 3832 - 8 byte less
constexpr auto sz2 = sizeof(CLightBuffer); // 3844 - incorrect; 
constexpr auto of = offsetof(CLightBuffer, NumLights); // 3840  - incorrect; hlsl assembly wants 3832

Here is the assembly of the buffer:

// cbuffer LightsBuffer
// {
//
//   struct
//   {
//       
//       float4 Position;               // Offset:    0
//       float4 Color;                  // Offset:   16
//       float4 Direction;              // Offset:   32
//       float Intensity;               // Offset:   48
//       float In;                      // Offset:   52
//       float Out;                     // Offset:   56
//       float Range;                   // Offset:   60
//       int bakedLight;                // Offset:   64
//       int dynamicLight;              // Offset:   68
//
//   } Lights[48];                      // Offset:    0 Size:  3832
//   int NumLights;                     // Offset: 3832 Size:     4
//
// }

i don't quite understand how the HLSL array has a size of 3832. 3832 / 48 is not 80 but 79.83 - how is that possible?


Solution

  • As you've correctly noted on the C++ side, your ShaderLight data just contains 72 Bytes of 'used' data and has therefore 8 bytes of padding at the end. However, on the HLSL side, these 8 padding bytes are not needed for the last element in your array, as the follow-up element (the NumLight integer) can be packed inside these padding bytes.

    You could fix this easily by specifying the int pad[2]; not just on the C++ side, but also in your HLSL code.