DirectX::XMMATRIX error C2719: __declspec(align(&#

2019-05-29 04:36发布

问题:

Ok so im working on my own DirectX framework all tutorials about making a DirectX framework are old and use deprecated stuff so i just made my own one , though i took somethings from the old tutorials and updated them to work with the new Windows 8.1 SDK and here comes The problem , i get errors with XMMATRIX the original code uses D3DXMATRIX

(33): error C2719: 'unnamed-parameter': formal parameter with __declspec(align('16')) won't be aligned
(40): error C2719: 'unnamed-parameter': formal parameter with __declspec(align('16')) won't be aligned
(42): error C2719: 'worldMatrix': formal parameter with __declspec(align('16')) won't be aligned
(42): error C2719: 'viewMatrix': formal parameter with __declspec(align('16')) won't be aligned
(42): error C2719: 'projectionMatrix': formal parameter with __declspec(align('16')) won't be aligned

this is Line 33 from S_SHADER.h :

bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX);

this is line 40 from S_SHADER.h :

bool SetSHaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX);

and this is line 42 from S_SHADER.cpp :

41 - bool S_SHADER::Render(ID3D11DeviceContext* deviceContext, int indexCount, DirectX::XMMATRIX worldMatrix,  DirectX::XMMATRIX viewMatrix, DirectX::XMMATRIX projectionMatrix)
42 - {

actually 41 has all the code and 42 has only the open brackets , anyways what am i doing wrong ?

EDIT : dont think this will help but i have a windows 7 64 bit computer with visual studio 2013

回答1:

This turns out to be rather complicated, and is covered on MSDN.

The short answer is you need to use calling-convention friendly typedefs that work with the various combinations of x86 __fastcall, x64 __fastcall, ARM __fastcall, and the new VS 2013 x86/x64 __vectorcall.

The 'ideal' solution is:

bool XM_CALLCONV Render(ID3D11DeviceContext*, int, FXMMATRIX, CXMMATRIX, CXMMATRIX);

bool XM_CALLCONV SetSHaderParameters(ID3D11DeviceContext*, FXMMATRIX, CXMMATRIX, CXMMATRIX);

Your original version would actually compile for x64 native, but each XMMATRIX is pushed onto the stack and is not passed "in-register". x64 native guarantees 16-byte alignment for stack variables. Win32 and ARM do not.

For x86 and x64, VS 2013 supports a new calling convention "__vectorcall" which can pass the first six (6) __m128 values in register including Heterogeneous Vector Aggregates (HVAs) like XMMATRIX. However, anything that doesn't fit into register should be passed by 'const reference' rather than by 'value'.

For VS 2012 and below, x86 __fastcall passes the first three (3) __m128 values in register, but cannot pass HVAs in register. The remainder have to be passed by 'const reference' rather than by 'value' due to the natural alignment of stack variables.

For VS 2012 and below, x64 __fastcall never passes __m128 values in register. While the natural alignment of the stack allows XMVECTOR and XMMATRIX to be passed by 'value' as a copy on the stack, it's likely more efficient to pass by 'const reference' instead.

For ARM, __fastcall passes the first four (4) __n128 values in register, and supports HVA. In this case, that would be one XMMATRIX.

Hence DirectXMath's conventions of using FXMVECTOR, GXMVECTOR, HXMVECTOR, CXMVECTOR, FXMMATRIX, and CXMMATRIX for parameters rather than using XMVECTOR or XMMATRIX directly. This can be a little complicated at first, but since the compiler complains as you've seen with Win32, you can work out unusual or complicated cases with a little trial and (compiler) error.

Alternately, you can not worry about 'optimal' register passing behavior of vector and matrix values, and just opt for something simple like:

bool Render(ID3D11DeviceContext*, int, const XMMATRIX&, const XMMATRIX&, const XMMATRIX&);

bool SetSHaderParameters(ID3D11DeviceContext*, const XMMATRIX&, const XMMATRIX&, const XMMATRIX&);

This should work fine across all the architectures and calling-conventions.