Jump to content
  • Advertisement
Sign in to follow this  
indiocolifa

Comments about HLSL array packing policy

This topic is 918 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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: 

 

f56Te.png

 

 I observe the following behavior when accessing e.g: light[0] from shader:

0SwQR.png

 

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.!

Edited by indiocolifa

Share this post


Link to post
Share on other sites
Advertisement

Putting everything into a float4 in C++ is quite legit. 
 

 

I think for my current purposes, which are *far* from a crazily tuned, high-end, high-performance engine, using float4s seems to be a good compromise.  I'm also using DirectXMath which includes types/operations nicely mapped to SSE/ARM Neon SIMD registers, so that's another reason for keeping 16-byte sized members for good.

 

Thank you very much. 

Share this post


Link to post
Share on other sites
Have you tried to move the intensity right after the pos, so that all your 3-component vectors are aligned again ? pos.x,pos.y,pos.z, intensity,col.r,col.g,col.b,is_on

Share this post


Link to post
Share on other sites

Have you tried to move the intensity right after the pos, so that all your 3-component vectors are aligned again ? pos.x,pos.y,pos.z, intensity,col.r,col.g,col.b,is_on

 

I "solved" it now with float4s in both sides tongue.png , but your idea should work since pos.rgb and intensity is 16-bytes wide, the same as col.rgb plus is_on.  Thanks, may be i'll try that next since I need to add attenuation parameters. wink.png

Edited by indiocolifa

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!