为什么要转换为 XMFLOAT 而不是直接使用 XMVECTOR?

Why convert to XMFLOAT instead of using XMVECTOR directly?

在研究 DirectX 12 时,它说我应该对 class 数据成员使用 XMFLOAT 而不是 XMVECTOR。 我不明白为什么。

在我的 class 中定义 XMVECTOR 变量是错误的吗?或者直接在我的 class?

中使用 XMVECTOR

您有权将一个或多个 XMVECTOR 存储为对象成员。

这样做时,您需要确保遵守 XMVECTOR 的对齐约束:128 位。这就是为什么他们引入 XMFLOATx 来处理没有对齐要求的存储。

如果不这样做,最好的情况下可能会导致崩溃,最坏的情况下可能会导致计算错误。当不需要 new 返回至少 16 字节的内存对齐时,32 位可执行文件更有可能发生这种情况。

Docs.Microsoft which you should take the time to read. In particular, read the Getting Started section titled Type Usage Guidelines 上的 DirectXMath 程序员指南对此进行了介绍。

The XMVECTOR and XMMATRIX types are the work horses for the DirectXMath Library. Every operation consumes or produces data of these types. Working with them is key to using the library. However, since DirectXMath makes use of the SIMD instruction sets, these data types are subject to a number of restrictions. It is critical that you understand these restrictions if you want to make good use of the DirectXMath functions.

You should think of XMVECTOR as a proxy for a SIMD hardware register, and XMMATRIX as a proxy for a logical grouping of four SIMD hardware registers. These types are annotated to indicate they require 16-byte alignment to work correctly. The compiler will automatically place them correctly on the stack when they are used as a local variable, or place them in the data segment when they are used as a global variable. With proper conventions, they can also be passed safely as parameters to a function (see Calling Conventions for details).

Allocations from the heap, however, are more complicated. As such, you need to be careful whenever you use either XMVECTOR or XMMATRIX as a member of a class or structure to be allocated from the heap. On Windows x64, all heap allocations are 16-byte aligned, but for Windows x86, they are only 8-byte aligned. There are options for allocating structures from the heap with 16-byte alignment (see Properly Align Allocations). For C++ programs, you can use operator new/delete/new[]/delete[] overloads (either globally or class-specific) to enforce optimal alignment if desired.

Note  As an alternative to enforcing alignment in your C++ class directly by overloading new/delete, you can use the pImpl idiom. If you ensure your Impl class is aligned via __aligned_malloc internally, you can then freely use aligned types within the internal implementation. This is a good option when the 'public' class is a Windows Runtime ref class or intended for use with std::shared_ptr<>, which can otherwise disrupt careful alignment.

However, often it is easier and more compact to avoid using XMVECTOR or XMMATRIX directly in a class or structure. Instead, make use of the XMFLOAT3, XMFLOAT4, XMFLOAT4X3, XMFLOAT4X4, and so on, as members of your structure. Further, you can use the Vector Loading and Vector Storage functions to move the data efficiently into XMVECTOR or XMMATRIX local variables, perform computations, and store the results. There are also streaming functions (XMVector3TransformStream, XMVector4TransformStream, and so on) that efficiently operate directly on arrays of these data types.

这种严格的对齐要求和冗长是设计,因为当load/store 开销被招致时,它让程序员清楚。但是,如果您觉得它有点乏味,请考虑使用 SimpleMath wrapper in the DirectX Tool Kit for DirectX 11 / DirectX 12

请记住,DirectX 与 DirectXMath 没有特别的关系。 DirectXMath 可以与任何版本的 Direct3D 甚至 OpenGL 一起工作,就像它只进行 CPU 端向量和矩阵计算一样。 DirectXMath 根本不依赖于 Windows OS;它只是使用内部函数的 C/C++ 代码的集合,因此编译器才是真正重要的。

事实上,由于您对 DirectX 显然还很陌生,通常还不知道如何使用 DirectXMath,因此您应该考虑使用 DirectX 11,而不是尝试冷落到 DirectX 12。 DirectX 12 是一个非常无情的 API 专为图形专家设计,并且在很大程度上假设您已经是 Direct3D 11 编程专家。

DirectX Tool Kit for DirectX 12 tutorials and Getting Started with Direct3D 12