【问题标题】:Working with DirectXMath and D3DXMath使用 DirectXMath 和 D3DXMath
【发布时间】:2017-11-21 09:16:40
【问题描述】:

在 D3DXMath 中,我们能够乘、加或减甚至除向量类型,即 D3DXVECTOR2、D3DXVECTOR3、D3DXVECTOR4 结构...... 现在在 DirectXMath 化身中,我们有 XMFLOAT2、XMFLOAT3、XMFLOAT4 和 XMVECTOR。如果我想做任何数学运算,我必须以任何一种方式从 XMFLOAT 转换为 XMVECTOR,Visual Studio 会抛出错误“没有 用户定义的转换”。为什么会这样?实际上,在 DirectX 数学库矢量操作的新版本(Windows 8.1、10)中,矢量操作略有变化。我做错了什么............ ?!

附:好吧,矩阵还有另一个问题,但现在我们只讨论向量。这些变化正在推动第三方开发者创建他们自己的数学库,他们已经做到了..... :)

【问题讨论】:

    标签: directxmath


    【解决方案1】:

    这个其实在MSDN上的DirectXMath Programmer's Guide里面有详细的解释:

    XMVECTOR 和 XMMATRIX 类型是 DirectXMath 库的主要工作对象。每个操作都会消耗或产生这些类型的数据。与他们合作是使用图书馆的关键。但是,由于 DirectXMath 使用 SIMD 指令集,因此这些数据类型受到许多限制。如果您想充分利用 DirectXMath 函数,了解这些限制至关重要。

    您应该将 XMVECTOR 视为 SIMD 硬件寄存器的代理,并将 XMMATRIX 视为四个 SIMD 硬件寄存器的逻辑分组的代理。这些类型被注释以表明它们需要 16 字节对齐才能正常工作。当它们用作局部变量时,编译器会自动将它们正确放置在堆栈中,或者当它们用作全局变量时将它们放置在数据段中。通过适当的约定,它们也可以作为参数安全地传递给函数(有关详细信息,请参阅调用约定)。

    但是,堆中的分配更为复杂。因此,当您使用 XMVECTOR 或 XMMATRIX 作为要从堆分配的类或结构的成员时,您需要小心。在 Windows x64 上,所有堆分配都是 16 字节对齐的,但对于 Windows x86,它们只有 8 字节对齐。有一些选项可以从堆中分配具有 16 字节对齐的结构(请参阅正确对齐分配)。对于 C++ 程序,如果需要,您可以使用 operator new/delete/new[]/delete[] 重载(全局或特定类)来强制实现最佳对齐。

    但是,避免在类或结构中直接使用 XMVECTOR 或 XMMATRIX 通常更容易且更紧凑。相反,请使用 XMFLOAT3、XMFLOAT4、XMFLOAT4X3、XMFLOAT4X4 等作为结构的成员。此外,您可以使用向量加载和向量存储功能将数据有效地移动到 XMVECTOR 或 XMMATRIX 局部变量中,执行计算并存储结果。还有一些流函数(XMVector3TransformStream、XMVector4TransformStream 等)可以直接对这些数据类型的数组进行高效操作。

    通过设计,DirectXMath 鼓励您编写高效、SIMD 友好的代码。加载或存储向量的成本很高,因此您应该尝试在加载数据的“流”模型中工作,在寄存器中大量使用它,然后写入结果。

    也就是说,我完全明白,对于刚接触 SIMD 数学或 DirectX 的人来说,这个用法有点复杂,即使对于专业开发人员来说也有点冗长。这就是为什么我还为 DirectXMath 编写了 SimpleMath 包装器,这使得它更像是您使用 XNA Game Studio 寻找的经典数学库,例如 Vector2Vector3Matrix 类,并覆盖了“C++ 魔法”所有显式加载和存储。 SimpleMath 类型与 DirectXMath 巧妙地互操作,因此您可以随意混合和匹配。

    参见this blog postGitHub

    DirectXMath 特意是一个“内联”库,这意味着在优化的代码中您不应该过多地传递变量,而只是计算较大函数中的值。 deprecatedD3DX9D3DX10D3DX11 库中的 D3DXMath 库更老派,它依赖于函数指针表,并且性能受到调用约定开销的严重限制。

    这些当然代表了不同的工程权衡。 D3DXMath 能够在运行时对专用处理器代码路径进行更多的替换,但是通过调用约定和间接开销为这种灵活性付出了代价。另一方面,DirectXMath 假设 SIMD 基线为 SSE/SSE2(或 Xbox One 上的 AVX),因此您无需运行时检测或间接,而是积极利用内联。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多