0
votes

So hi guys,

right now I'm just trying to pass a value to the hlsl shader. Now heres the constant buffer in the shader:

cbuffer ConstantBuffer
{
    float4x4 final;
    float4x4 rotation;    // the rotation matrix
    float4 lightvec;      // the light's vector
    float4 lightcol;      // the light's color
    float4 ambientcol;    // the ambient light's color
    float3 SPACE;
    float alpha;  // <-- Variable trying to recieve, the first 5 works!
}

And in c++:

struct CBUFFER
{
    public:
        D3DXMATRIX Final;
        D3DXMATRIX Rotation;
        D3DXVECTOR4 LightVector;
        D3DXCOLOR LightColor;
        D3DXCOLOR AmbientColor;
        D3DXVECTOR3 SPACE;
        float Alpha;
};

So I've tried to align the variables to be able to send them in packs of 16 bits. But for some reason, it isn't working, because the variable alpha in the shader isn't set.

So what did i do wrong? (PS. I set the bufferwidth in the initialization of the shader to: 192)

Thank You

2
Read this: blog.signalsondisplay.com/?p=244 (it says about 16 bytes blocks, not bits) I think in your case u can wrap your c++ struct with #pragma pack( push, 16 ) struct CBUFFER ... #pragma pack( pop )Dave

2 Answers

1
votes

Problem here is that bufferwidth should be 208 instead of 192. In this case, the sum to calculate cbuffer size is:

64 (float4x4 final) + 64 (float4x4 rotation) + 16 (float4 lightvec)+ 16 (float4 lightcol) + 16 (float4 ambientcol) + 16 (float3 SPACE) + 16 (float alpha) = 208 bytes

Variables of a cbuffer are grouped in packs of 16 bytes, this means that the minimum size of a variable is 16 bytes. Thats why 'float3 SPACE' and 'float alpha' represent 16 bytes each.

"ConstantBuffer" occupies 13 packs of 16 bytes (13 * 16 = 208).


Variables can be packed. The keyword "packoffset" allows you to pack 2, 3 or 4 variables in one 16 bytes pack. In this case, packing 'float3 SPACE' and 'float alpha' reduce the cbuffer size to 192:

cbuffer ConstantBuffer
{
    float4x4 final : packoffset(c0);
    float4x4 rotation : packoffset(c4);
    float4 lightvec : packoffset(c8);
    float4 lightcol : packoffset(c9);
    float4 ambientcol : packoffset(c10);
    float3 SPACE : packoffset(c11); // 'SPACE' is mapped to the first 12 bytes of the 12th pack.
    float alpha : packoffset(c11.w); // 'alpha' is mapped to the last 4 bytes of the 12th pack.
}

now the sum to calculate cbuffer size is:

64 (float4x4 final) + 64 (float4x4 rotation) + 16 (float4 lightvec)+ 16 (float4 lightcol) + 16 (float4 ambientcol) + 12 (float3 SPACE) + 4 (float alpha) = 192 bytes

and "ConstantBuffer" occupies 12 packs of 16 bytes (12 * 16 = 192).

Finally the struct "CBUFFER" should be modified:

struct CBUFFER
{
    public:
        D3DXMATRIX Final;
        D3DXMATRIX Rotation;
        D3DXVECTOR4 LightVector;
        D3DXCOLOR LightColor;
        D3DXCOLOR AmbientColor;
        D3DXVECTOR4 SPACE_and_alpha; // SPACE_and_alpha.xyz = SPACE, SPACE_and_alpha.w = alpha

};

more packing info: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx

0
votes

check de Dave awnser, is possible that the compiler created a offset in variables of struct to make all more fast to use in CPU fetch. If pragma not works check if you are using the alpha value direct in pixel shader stage and set the correctly constant buffer (constant buffer set in vertex shader is not shared in Pixel shader if you aren't using effects).