Edward Fitz Abucay
Edward Fitz Abucay

Reputation: 483

DirectX::XMMATRIX __declspec(align('16')) won't be aligned

I am using DirectXMath in building my 3D simulation project

   void SetConstantBuffer(ID3D11DeviceContext*_device_context, DirectX::XMMATRIX _world, DirectX::XMMATRIX _view, DirectX::XMMATRIX _projection)
   {
       ConstantBuffer const_buffer;
       const_buffer.View = DirectX::XMMatrixTranspose(_world);
       const_buffer.World = DirectX::XMMatrixTranspose(_view);
         const_buffer.Projection = DirectX::XMMatrixTranspose(_projection);
       _device_context->UpdateSubresource(m_const_buffer, 0, NULL, &const_buffer, 0, 0);
   }

I get these kind of compiler errors probably on SIMD flag inside DirectXMath:

error C2719: '_world': formal parameter with __declspec(align('16')) won't be aligned
error C2719: '_view': formal parameter with __declspec(align('16')) won't be aligned
error C2719: '_projection': formal parameter with __declspec(align('16')) won't be aligned

Is there any other way without converting it to DirectX::XMFLOAT4X4?
By the way I'm using an x86 machine and compiling on Visual Studio 2012 Express.

Upvotes: 3

Views: 7972

Answers (3)

Matthias
Matthias

Reputation: 4677

MSDN: DirectXMath Library Internals:

The FXMMATRIX and CXMMATRIX aliases help support taking advantage of the HVA argument passing with __vectorcall.

Use the FXMMATRIX alias to pass the first XMMATRIX as an argument to the function. This assumes you don't have more than two FXMVECTOR arguments or more than two float, double, or FXMVECTOR arguments to the ‘right’ of the matrix. For info about additional considerations, see the __vectorcall documentation.

Use the CXMMATRIX alias otherwise.

DirectXMath Code

// Fix-up for (1st) XMMATRIX parameter to pass in-register for ARM64 and vector call; by reference otherwise
#if ( defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || _XM_VECTORCALL_ ) && !defined(_XM_NO_INTRINSICS_)
typedef const XMMATRIX FXMMATRIX;
#else
typedef const XMMATRIX& FXMMATRIX;
#endif

// Fix-up for (2nd+) XMMATRIX parameters to pass by reference
typedef const XMMATRIX& CXMMATRIX;

Solution

If you want to support a wider range of processor architectures, you better use the XM_CALLCONV macro for specifying the calling convention instead of hard coding __vectorcall:

void XM_CALLCONV SetConstantBuffer(
    FXMMATRIX _world, 
    CXMMATRIX _view, 
    CXMMATRIX _projection, 
    ID3D11DeviceContext *_device_context) {
}

Upvotes: 0

Brad
Brad

Reputation: 21

__declspec(align(16)) does not apply to stack variables according to Microsoft: MSDN Align. My testing indicates that this also applies to #pragma pack(16)

Consequently, stack variables need be stored as XMFLOAT4X4 and converted to and from XMMATRIX using XMLoadFloat4x4 and XMStoreFloat4x4 (what you were trying to avoid).

Fortunately, most of the processing in Direct3D is performed in the video card. An occasional, unnecessary 64 byte copy because of a poor design decision from Microsoft should be imperceptible.

Upvotes: 1

user1157123
user1157123

Reputation:

Pass the values by const reference instead of by value.

void SetConstantBuffer(
    ID3D11DeviceContext*_device_context,
    const DirectX::XMMATRIX &_world,
    const DirectX::XMMATRIX &_view,
    const DirectX::XMMATRIX &_projection)

Upvotes: 5

Related Questions