3

我正在使用 DirectXMath 构建我的 3D 模拟项目

   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': 带有 __declspec(align('16')) 的形式参数不会对齐
错误 C2719: '_view': 带有 __declspec(align('16')) 的形式参数不会对齐
错误 C2719 : '_projection': 带有 __declspec(align('16')) 的形参不会对齐

有没有其他方法不将其转换为 DirectX::XMFLOAT4X4?
顺便说一句,我使用的是 x86 机器并在 Visual Studio 2012 Express 上进行编译。

4

3 回答 3

5

通过 const 引用而不是按值传递值。

void SetConstantBuffer(
    ID3D11DeviceContext*_device_context,
    const DirectX::XMMATRIX &_world,
    const DirectX::XMMATRIX &_view,
    const DirectX::XMMATRIX &_projection)
于 2013-03-06T11:19:00.317 回答
1

__declspec(align(16)) 根据 Microsoft: MSDN Align不适用于堆栈变量。我的测试表明这也适用于#pragma pack(16)

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

幸运的是,Direct3D 中的大部分处理都是在显卡中执行的。由于 Microsoft 糟糕的设计决策而偶尔出现的不必要的 64 字节副本应该是难以察觉的。

于 2013-07-22T22:27:59.843 回答
0

MSDN:DirectXMath 库内部

FXMMATRIX 和 CXMMATRIX 别名有助于支持利用通过 __vectorcall 传递的 HVA 参数。

使用 FXMMATRIX 别名将第一个 XMMATRIX 作为参数传递给函数。这假设您没有超过两个 FXMVECTOR 参数或超过两个浮点、双精度或 FXMVECTOR 参数到矩阵的“右侧”。有关其他注意事项的信息,请参阅 __vectorcall 文档。

否则使用 CXMMATRIX 别名。

DirectXMath 代码

// 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;

解决方案

如果你想支持更广泛的处理器架构,你最好使用XM_CALLCONV宏来指定调用约定而不是硬编码__vectorcall

void XM_CALLCONV SetConstantBuffer(
    FXMMATRIX _world, 
    CXMMATRIX _view, 
    CXMMATRIX _projection, 
    ID3D11DeviceContext *_device_context) {
}
于 2017-12-10T09:25:04.410 回答