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 代码中轻松解决此问题。
我对 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 代码中轻松解决此问题。