1
\$\begingroup\$

I have issues with constant buffer member alignments. I have the following C++ struct:

namespace Renderer {
    using DirectX::SimpleMath::Matrix;
    using DirectX::SimpleMath::Vector3;
    using DirectX::SimpleMath::Vector2;
    struct alignas(16) CCameraMatrixBuffer
    {
        Matrix ViewProjection;
        //--
        Matrix View;
        //--
        Matrix Projection;
        //--
        Vector3 CamPositionWS;
        int CameraUnderwater;
        //--
        Vector3 CamDirectionWS;
        unsigned int RoomNumber;
        //--
        Vector2 ViewSize;
        Vector2 InvViewSize;
        //--
        unsigned int Frame;
        //--
        
    };
}

and this HLSL counterpart:

    cbuffer CameraMatrixBuffer : register(b0)
{
    float4x4 ViewProjection;
    float4x4 View;
    float4x4 Projection;
    float3 CamPositionWS;
    int CameraUnderwater;
    float3 CamDirectionWS;
    unsigned int RoomNumber;
    float2 ViewSize;
    float2 InvViewSize;
    unsigned int Frame;
};

however, when i debug the shader, CamDirectionWS shows the following:

enter image description here

The 1024.000f is part of the ViewSize (the resolution). Can someone tell me whats wrong with it?

\$\endgroup\$
2
\$\begingroup\$

Review the HLSL cbuffer packing rules here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules

HLSL packing rules are similar to performing a #pragma pack 4 with Visual Studio, which packs data into 4-byte boundaries. Additionally, HLSL packs data so that it does not cross a 16-byte boundary. Variables are packed into a given four-component vector until the variable will straddle a 4-vector boundary; the next variables will be bounced to the next four-component vector.

Each structure forces the next variable to start on the next four-component vector. This sometimes generates padding for arrays of structures. The resulting size of any structure will always be evenly divisible by sizeof(four-component vector).

So, for example, your float3s are actually being padded-out to float4 size in your HLSL.

To resolve, either pad out your C++ struct to match, or use packoffset in your HLSL.

An example of using packoffset:

cbuffer test0 {
    float3 this : packoffset(c0.x);
    float that: packoffset(c0.w);
};

This will pack the cbuffer as you probably expect.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks, but I still have this issue, even after specifying the packoffsets manually :/ pastebin.com/TXxBjS4J \$\endgroup\$ – Raildex Jul 1 '20 at 17:24
  • \$\begingroup\$ Can you also explain why the float3s are padded out? They start on a new boundary and the unsigned int should fit into it? \$\endgroup\$ – Raildex Jul 1 '20 at 17:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.