在学习 DirectX 12 时,它说我应该对类数据成员使用 XMFLOAT 而不是 XMVECTOR。我不懂为什么。
在我的类中定义 XMVECTOR 变量是错误的吗?还是直接在我的课堂上使用 XMVECTOR?
在学习 DirectX 12 时,它说我应该对类数据成员使用 XMFLOAT 而不是 XMVECTOR。我不懂为什么。
在我的类中定义 XMVECTOR 变量是错误的吗?还是直接在我的课堂上使用 XMVECTOR?
这在MSDN上的 DirectXMath 程序员指南中有介绍,您应该花时间阅读。特别是,请阅读标题为Type Usage Guidelines的入门部分。
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[] 重载(全局或特定于类)来强制实现最佳对齐。
注意 作为通过重载 new/delete 直接在 C++ 类中强制对齐的替代方法,您可以使用 pImpl 习惯用法。如果您确保您的 Impl 类在内部通过 __aligned_malloc 对齐,则您可以在内部实现中自由使用对齐类型。当“公共”类是 Windows 运行时引用类或旨在与 std::shared_ptr<> 一起使用时,这是一个不错的选择,否则可能会破坏仔细对齐。
但是,避免在类或结构中直接使用 XMVECTOR 或 XMMATRIX 通常更容易且更紧凑。相反,请使用 XMFLOAT3、XMFLOAT4、XMFLOAT4X3、XMFLOAT4X4 等作为结构的成员。此外,您可以使用向量加载和向量存储函数将数据有效地移动到 XMVECTOR 或 XMMATRIX 局部变量中,执行计算并存储结果。还有一些流函数(XMVector3TransformStream、XMVector4TransformStream 等)可以直接对这些数据类型的数组进行有效操作。
这种严格的对齐要求和冗长是设计使然,因为它使程序员清楚地知道何时发生加载/存储开销。但是,如果您觉得它有点乏味,请考虑使用DirectX Tool Kit for DirectX 11 / DirectX 12中的SimpleMath包装器
请记住,DirectX 与 DirectXMath 没有特别的关系。DirectXMath 可以与任何版本的 Direct3D 甚至 OpenGL 一起工作,就像它只用于 CPU 端矢量和矩阵计算一样。DirectXMath 根本不依赖于 Windows 操作系统。它只是使用内部函数的 C/C++ 代码的集合,因此编译器才是真正重要的。
事实上,由于您显然对 DirectX 还不够熟悉,通常还不知道如何使用 DirectXMath,因此您应该考虑使用 DirectX 11,而不是试图跳入 DirectX 12 冷。DirectX 12 是为图形专家设计的非常无情的 API,并且在很大程度上假设您已经是 Direct3D 11 编程方面的专家。
您有权将一个或多个存储XMVECTOR
为对象成员。
当你这样做时,你需要确保你遵守XMVECTOR
: 128bits 的对齐约束。这就是为什么他们引入了XMFLOATx
在没有对齐要求的情况下处理存储的原因。
不这样做可能会给你带来最好的崩溃和最坏的计算错误。new
当不需要返回至少 16 个字节的内存对齐时,这更有可能发生在 32 位可执行文件中。