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

折月煮酒 提交于 2019-12-06 06:48:27

问题


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.


回答1:


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)



回答2:


__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.




回答3:


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) {
}


来源:https://stackoverflow.com/questions/15245378/directxxmmatrix-declspecalign16-wont-be-aligned

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!