Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm writing another game engine in C++11/VC11 which presently uses DirectX/Direct3D11 as rendering backend. In order to hide DirectX types from the public interface (and a possible later implementation of an OpenGL backend), I'm rolling a linear algebra library on my own, which - however - still uses DirectX Math internally for the time being. DirectX Math is more or less a bunch of typedefs around the C++ SIMD intrinsics (__m128 etc.). In order to keep the levels of indirection low and have the stuff as "atomic" and inlined as possible, I prefer to inherit from the DirectX Math types directly (XMVECTORF32 in this case) - i.e. I don't want to use it as a member variable:

struct vector4 : private DirectX::XMVECTORF32

MSDN gives following example for the correct initialization of the XMVECTORF32 structure:

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

However, my attempts to initialize the XMVECTORF32 as a base structure are not understood by the compiler.

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
    {
    }
};

Am I missing something? How to correctly perform the base initialization I am intending to do? Is there maybe some new C++11 initialization sugar to help me out?

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

For some reasons, I was not seeing the obvious. After examining the definition of XMVECTORF32, it was clear that the underlying union-float-array "f" was accessible for me, so the initialization looks like this.

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;
    }
};

No casts, no unions, no c arrays. With inlining, performance should be near optimum.

------------ EDIT 2 -----------

XMVECTORF32 is not meant for storing data. Therefore the vector must inherit from XMFLOAT4. Otherwise, this gives non-reproducible access violation exceptions, especially with optimizations turned on. Here is more background: http://www.asawicki.info/news_1429_xna_math_and_access_violation.html

My final code looks like this:

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; }
};

The vector data must be loaded into an XMVECTOR using XMLoadFloat4 prior SIMD calculations - no way around it. Think of XMVECTOR like a register - not a memory location.

like image 548
aj_dev Avatar asked Jun 30 '26 21:06

aj_dev


1 Answers

Provided that DirectX::XMVECTORF32 is an aggregate class, your code is fine in C++11 (see a live example which demonstrates its use).

However, the compiler you are using does not support uniform initialization (as clarified by this Q&A on StackOverflow), and in C++03 you cannot initialize a base aggregate class as you would copy-initialize a variable.

Therefore, you will have to initialize the member of your base class explicitly in the initialization list, or call something like SetVector() in the body of your vector4 constructor.

like image 115
Andy Prowl Avatar answered Jul 02 '26 11:07

Andy Prowl