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\$

1 Answer 1

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, 2020 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, 2020 at 17:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .