2

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.

aj_dev
  • 23
  • 4

1 Answers1

1

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.

Community
  • 1
  • 1
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • Thanks, that makes sense. Working with C++11 in GCC was way better, but I'm stuck with MSVC due to this new "metro app" thing and windows store requirements. Final solution: inline vector4(scalar v0, scalar v1, scalar v2, scalar v3) { f[0] = v0; f[1] = v1; f[2] = v2; f[3] = v3; } – aj_dev Mar 09 '13 at 14:44