c++ 11 DirectX Math: XMVECTORF32作为基结构初始化

C++11 DirectX Math: XMVECTORF32 as base structure initialization

本文关键字:结构 初始化 XMVECTORF32 DirectX Math c++      更新时间:2023-10-16

我正在用c++ 11/VC11编写另一个游戏引擎,目前使用DirectX/Direct3D11作为渲染后端。为了在公共接口中隐藏DirectX类型(以及可能的OpenGL后端实现),我自己开发了一个线性代数库,然而,它暂时仍然在内部使用DirectX Math。DirectX Math或多或少是围绕c++ SIMD intrinsic (__m128等)的一堆类型。为了保持间接的低水平,并有东西作为"原子"和内联尽可能,我更喜欢从DirectX数学类型直接继承(XMVECTORF32在这种情况下)-也就是说,我不想使用它作为一个成员变量:

struct vector4 : private DirectX::XMVECTORF32

MSDN给出了以下示例来正确初始化XMVECTORF32结构:

XMVECTOR data;
XMVECTORF32 floatingVector = { 0.f, 0.f, 0.1f, 1.f };
data = floatingVector;

但是,我试图将XMVECTORF32初始化为基结构,编译器无法理解。

struct vector4 : private DirectX::XMVECTORF32 // not XMFLOAT4 due to possible conversation overhead
{
    friend class matrix44;
    inline vector4(scalar v0, scalar v1, scalar v2, scalar v3)
        :   DirectX::XMVECTORF32{v0, v1, v2, v3} // ERROR: ';' expected
    {
    }
};

我错过了什么吗?如何正确地执行基础初始化我打算做?也许有一些新的c++ 11初始化糖来帮助我?

------------ EDIT -----------

由于某些原因,我没有看到显而易见的。在检查了XMVECTORF32的定义之后,很明显底层的联合浮点数组"f"对我来说是可以访问的,所以初始化是这样的:

struct vector4 : private DirectX::XMVECTORF32
{
    friend struct matrix44;
    inline vector4(scalar v0, scalar v1, scalar v2, scalar v3)
    {
        f[0] = v0;
        f[1] = v1;
        f[2] = v2;
        f[3] = v3;
    }
};

没有强制类型转换,没有联合,没有c数组。使用内联,性能应该接近最佳。

------------ <2 辑> -----------

XMVECTORF32不是用来存储数据的。因此,向量必须继承自XMFLOAT4。否则,这会产生不可再现的访问冲突异常,特别是在启用优化的情况下。这里有更多的背景信息:http://www.asawicki.info/news_1429_xna_math_and_access_violation.html

最后的代码是这样的:

struct vector4 : private DirectX::XMFLOAT4
{
    friend struct matrix44;
    inline vector4(scalar v0, scalar v1, scalar v2, scalar v3)
        :   DirectX::XMFLOAT4(v0, v1, v2, v3)
    {
    }
    inline scalar& v0() { return x; }
    inline scalar& v1() { return y; }
    inline scalar& v2() { return z; }
    inline scalar& v3() { return w; }
};

向量数据必须使用XMLoadFloat4预先SIMD计算加载到XMVECTOR中-没有办法绕过它。可以把XMVECTOR看作一个寄存器,而不是一个内存位置。

如果DirectX::XMVECTORF32是一个聚合类,那么您的代码在c++ 11中是很好的(请参阅演示其使用的实时示例)。

然而,你正在使用的编译器不支持统一初始化(正如this Q&A在StackOverflow上澄清的那样),并且在c++ 03中,你不能像初始化变量那样初始化基聚合类。

因此,你必须在初始化列表中显式初始化基类的成员,或者在vector4构造函数的主体中调用SetVector()之类的东西。