在研究DirectX 12时,它说我应该使用XMFLOAT而不是XMVECTOR来用于类数据成员。 我不明白为什么。
在我的班级中定义XMVECTOR变量是错误的吗?或直接在我班上使用XMVECTOR?
答案 0 :(得分:1)
在[{3}}上的DirectXMath程序员指南中对此进行了介绍,您应该花些时间阅读。请特别阅读标题为MSDN的使用入门部分。
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对齐,则可以在内部实现中自由使用对齐的类型。当'public'类是Windows运行时ref类或打算与std :: shared_ptr<>一起使用时,这是一个很好的选择,否则会破坏仔细对齐。
但是,通常更容易和更紧凑,以避免直接在类或结构中使用XMVECTOR或XMMATRIX。相反,请使用XMFLOAT3,XMFLOAT4,XMFLOAT4X3,XMFLOAT4X4等作为结构的成员。此外,您可以使用向量加载和向量存储功能将数据有效地移动到XMVECTOR或XMMATRIX局部变量中,执行计算并存储结果。还有流函数(XMVector3TransformStream,XMVector4TransformStream等)可以直接在这些数据类型的数组上高效运行。
这种严格的对齐要求和详细程度是按设计,因为它使程序员在发生加载/存储开销时变得清晰。但是,如果您发现它有点单调乏味,请考虑使用 DirectX工具包中的Type Usage Guidelines包装器SimpleMath / DirectX 11
请记住,DirectX与DirectXMath没有任何关系。 DirectXMath可以与任何版本的Direct3D甚至OpenGL一样工作,因为它只是进行CPU端向量和矩阵计算。 DirectXMath根本不依赖于Windows操作系统;它只是一个使用内在函数的C / C ++代码集合,所以编译器才是最重要的。
事实上,由于你显然已经足够新,因为DirectX通常不知道如何使用DirectXMath,你应该考虑使用DirectX 11而不是试图跳进DirectX 12冷。 DirectX 12是一个非常难以置信的API,专为图形专家设计,并且主要假设您已经是Direct3D 11编程的专家。
答案 1 :(得分:0)
您有权将一个或多个XMVECTOR
存储为对象成员。
执行此操作时,您需要确保遵守XMVECTOR
:128位的对齐约束。这就是他们在没有对齐要求的情况下引入XMFLOATx
来处理存储的原因。
如果不这样做可能会给您最多崩溃和最坏的计算错误。当new
不需要返回至少16个字节的内存对齐时,更可能发生32位可执行文件。