HLSL 对齐问题

HLSL Alignment issues

我对 HLSL 缓冲区对齐有疑问。 我有一个大小为 48 的数组的灯光结构(即着色器最多可容纳 48 盏灯)。 (除数是16字节边界的标记)

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;
    //---//
};

出于某种原因,结构的大小与 C++ 端不同。

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

这里是缓冲区的集合:

// 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
//
// }

我不太明白HLSL数组的大小是3832。 3832 / 48 不是 80 而是 79.83 - 这怎么可能?

正如您在 C++ 方面正确指出的那样,您的 ShaderLight 数据仅包含 72 字节的 'used' 数据,因此末尾有 8 字节的填充。但是,在 HLSL 端,数组中的最后一个元素不需要这 8 个填充字节,因为可以将后续元素(NumLight 整数)打包在这些填充字节中。

您可以通过指定 int pad[2]; 不仅在 C++ 端,而且在您的 HLSL 代码中轻松解决此问题。