hlsl sm_5_0 cbuffer problem

5000fdaaeeeb9f038be93cf67eb3b130
0
David_Gallagher 102 Jan 25, 2012 at 22:47

I’m haveing a slight problem with my cbuffers in my shader, well the middle of the three being sent to the shader.

the one I’m having an issue with is when I send the point light buffer like this with a BufferSize of 240 (being things are sent in chucks of 16)

cbuffer PLightConstantBuffer : register(b1)
{
float4 PL_Pos[4];
float4 PL_Color[4];
float4 PL_Ambient[4];
float PL_Range[4];
float PL_Falloff[4];
int PL_ActiveLightCount;
};

it only reaches the ambient and nothing further is sent (register(b0) and register(b2) are fine though).

now if I change Range and Falloff to a float4 and with a buffer size of 336 like…

cbuffer PLightConstantBuffer : register(b1)
{
float4 PL_Pos[4];
float4 PL_Color[4];
float4 PL_Ambient[4];
float4 PL_Range[4];
float4 PL_Falloff[4];
int PL_ActiveLightCount;
};

everything is fine and all data can be accessed. is something not right about sending an array of floats in the first one(range and falloff)? I just want to understand why I can’t send an array of floats if that is the case but and array of float4’s isn’t a problem. thanks.

2 Replies

Please log in or register to post a reply.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Jan 25, 2012 at 23:09

I’m not completely sure, but I think the rule for arrays in HLSL is that each element is aligned on a 16-byte boundary, and this is true regardless of the base type…which seems kind of silly, but I think it has to be that way for the shader to address the elements, since at the hardware level, the array elements are stored into consecutive 16-byte registers. So a float[4] array won’t work because in C++ it doesn’t insert the padding, while a float4 array matches between C++ and HLSL.

You might try using an array-of-structs instead of struct-of-arrays layout, e.g.

struct Light
{
    float4 Pos;
    float4 Color;
    float4 Ambient;
    float Range;
    float Falloff;
};
cbuffer PLightConstantBuffer : register(b1)
{
Light PL_Light[4];
int PL_ActiveLightCount;
};

That should work, and give less overhead since each Light struct will be padded to 64 bytes; total size of the cbuffer is 260 bytes (272 with 16-byte alignment).

5000fdaaeeeb9f038be93cf67eb3b130
0
David_Gallagher 102 Jan 26, 2012 at 01:09

Thanks Reedbeta, appreciate the extra information. I just tried your described struct method and it produced the same results as my float [4] method but once i added some padding in the hlsl side and also from the c++ side also it worked, but if i have to pad the arrays I may aswell just use float4 and fill that. Thanks for the help in understanding this better, I thought I had it nailed down but there is always more to learn it seems :).