Hi all! I want to know if I'm correct about HLSL array behavior.
I'm working with a standard lighting vertex shader, HLSL plus C++, DirectX11.1 API. For storing my light data I've setup a simple declaration, padded accordingly to match the packing requirements of constant buffers:
#define MAX_LIGHTS 16
// C++ side
struct LightBase {
DirectX::XMFLOAT3 pos;
DirectX::XMFLOAT3 color;
float intensity;
float isOn;
};
struct CBUFFER_LIGHT {
LightBase light[MAX_LIGHTS];
float numActiveLights;
float _padding[3];
};
The shader declares a "matching" cbuffer as:
// HLSL vertex shader
#define MAX_LIGHTS 16
struct LightBase {
float3 pos;
float3 color;
float intensity;
float isOn;
};
cbuffer lights : register (b3) {
LightBase light[MAX_LIGHTS];
float numActiveLights;
}
Now, as I expected, it didn't work due to the HLSL memory organization policy regarding arrays. e.g; if I set the buffer from C++ with the following data:
I observe the following behavior when accessing e.g: light[0] from shader:
See how light[0].color and other struct members got displaced? Seems that HLSL will organize your arrays in Vector4 elements regardless of the real type of the array element.
So I think the array data passed from C++ { -7, -1, -100, 0.44, 0.66, 0.88, 1.0, 1.0 } will be organized by HLSL in the following layout;
A[0] = { -7, -1, -100, 0.44 }
A[1] = { 0.66, 0.88, 1.0, 1.0 }
A[2] = { ...}
So A[0] contains .xyz for position and .x for color struct member; A[1] contains .gb for color member, intensity and .isOn members.
But for example, calling light[0].color from the shader seems to still address &light + sizeof(float3)+sizeof(float3) following the declaration of the cbuffer! This unexpected result is due to array layout by HLSL.
If HLSL and DirectX are so fond of FLOAT4 values, it's not better to use all float4 variables in GPU-CPU exchange through cbuffers and access members (.xyzw) as needed? e.g: do you need a boolean? Use a float4 and fill the first member (or the four members and access any of them).
Any policy or good practice you can recommend regarding cbuffer arrays?
Thanks.!