C++ DirectX::XMMATRIX_uudeclspec(align(';16';)赢得';不一致

C++ DirectX::XMMATRIX_uudeclspec(align(';16';)赢得';不一致,c++,windows,visual-studio-2012,directx,directx-11,C++,Windows,Visual Studio 2012,Directx,Directx 11,我正在使用DirectXMath构建我的三维仿真项目 void SetConstantBuffer(ID3D11DeviceContext*_device_context, DirectX::XMMATRIX _world, DirectX::XMMATRIX _view, DirectX::XMMATRIX _projection) { ConstantBuffer const_buffer; const_buffer.View = DirectX::X

我正在使用DirectXMath构建我的三维仿真项目

   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);
   }
我在DirectXMath中的SIMD标志上可能会出现以下类型的编译器错误:

错误C2719:“_world”:带有u declspec(align('16'))的形式参数将不对齐
错误C2719:“\u视图”:带有\u declspec(align('16'))的形式参数将不对齐
错误C2719:“_投影”:带有u declspec(align('16'))的形式参数将不对齐

如果不将其转换为DirectX::XMFLOAT4X4,还有其他方法吗?

顺便说一句,我正在使用x86机器并在Visual Studio 2012 Express上编译。

通过常量引用而不是通过值传递值

void SetConstantBuffer(
    ID3D11DeviceContext*_device_context,
    const DirectX::XMMATRIX &_world,
    const DirectX::XMMATRIX &_view,
    const DirectX::XMMATRIX &_projection)
__根据Microsoft:,declspec(align(16))不适用于堆栈变量。我的测试表明,这也适用于#pragma pack(16)

因此,堆栈变量需要存储为XMFLOAT4X4,并使用XMLoadFloat4x4和XMStoreFloat4x4(您试图避免的)与XMMATRIX进行转换

幸运的是,Direct3D中的大部分处理都是在视频卡中执行的。由于微软设计决策不力,偶尔会出现不必要的64字节拷贝,这应该是难以察觉的。

:

FXMMATRIX和CXMMATRIX别名有助于利用通过_uvectorcall传递的HVA参数

使用FXMMATRIX别名将第一个XMMATRIX作为参数传递给 功能。这假设您没有超过两个FXMVECTOR 参数或两个以上的float、double或FXMVECTOR参数 矩阵的“右”。有关其他注意事项的信息, 请参阅矢量调用文档

否则,请使用CXMMATRIX别名

解决方案

如果希望支持更广泛的处理器体系结构,最好使用
XM\u CALLCONV
宏来指定调用约定,而不是硬编码
\uu vectorcall

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

x86编译器未实现堆栈对齐,因此无法保证参数的最终位置。如果不使用
\uuu declspec(align('16'))
声明,但使用对齐类型(如
XMFLOAT4A
),则可能会引发此错误。下面的解决方案也适用。即使这个注释很旧,我的理解是:对象(XMMATRIX)最初是16字节对齐的。如果按值传递这些值,则会将这些值复制到函数堆栈中,在该堆栈中不再保证16字节对齐。如果您通过常量引用传递它们,那么您将得到1。请确保对象不会更改,并且2。对象不在堆栈上(因此仍然对齐)。如果编译为C会怎么样?我不能在C代码中使用引用。我在函数的一个_m256参数上得到了这个错误,没有decl spec.@Bram我相信通过指针传递应该有相同的效果;如果原始内存已对齐,则指针将指向对齐的内存。C++中的引用就像引擎盖下的指针,你的第二个语句是错误的。首先,如果您总是自己(在堆栈和堆上)保证正确对齐,则根本不需要使用
XMLoadFloat4x4
XMStoreFloat4x4
。其次,根据体系结构(arm64),可以按值传递
XMMATRIX
void XM_CALLCONV SetConstantBuffer(
    FXMMATRIX _world, 
    CXMMATRIX _view, 
    CXMMATRIX _projection, 
    ID3D11DeviceContext *_device_context) {
}