Crash after m = XMMatrixIdentity() - alignment memory in classes?
Asked Answered
O

4

9

I was looking at the tutorials in DirectX SDK. Tutorial 5 works fine, but after I have copied and separated the code to my own classes, I got strange error during launching my application.

The line is:

g_World1 = XMMatrixIdentity();

Because of it, I got error in xnamathmatrix.int operator= which looks like that:

XMFINLINE _XMMATRIX& _XMMATRIX::operator=
(
    CONST _XMMATRIX& M
)
{
    r[0] = M.r[0];
    r[1] = M.r[1];
    r[2] = M.r[2];
    r[3] = M.r[3];
    return *this;
}

And the error message is:

Access violation reading location 0xffffffff

I have read somewhere that it could be caused by something connected to XMFLOAT4X4 / XMMATRIX:

Have you considered using XMFLOAT4X4 to store the matrix, and only using XMMATRIX?

But I think I already use XMMATRIX.

MyClass.h:

private:
    XMMATRIX g_World1;

MyClass.cpp:

void init(){
   g_World1 = XMMatrixIdentity();
}

I don't think I should change XMMATRIX g_World1; to XMFLOAT4X4 g_World1, because it produces errors like:

error C2679: binary '=' : no operator found which takes a right-hand operand of type 'XMMATRIX' (or there is no acceptable conversion)

Olcott answered 1/7, 2012 at 21:17 Comment(0)
T
5

XMVECTOR and XMMATRIX are the 'register proxy' types. You can use them safely as types for the Xbox 360, Xbox One, and Windows x64 platforms as they all natively have 16-byte alignment for the data on the stack and allocated on the heap.

Using them for Windows 32-bit or Windows RT/ARM takes more effort since the native alignment is les than 16-bytes. One approach is the technique used by DirectX Tool Kit... it uses the pImpl idiom and the pImpl internal classes are explicitly allocated with 16-byte alignment which is where XMVECTOR and XMMATRIX types are used directly. Another approach is to use all the various 'storage' types like XMFLOAT4 and XMFLOAT4X4.

Note: the DirectXMath programmer's guide covers this. It's not a long document to read, and it's packed with a lot of hints and recommendations.

PS: There's a version of the standard Direct3D tutorials for Win32 desktop on MSDN Code Gallery that does not require the DirectX SDK... it just uses the Windows 8.x SDK included with VS 2012 or VS 2013.enter link description here

Tletski answered 26/6, 2014 at 7:28 Comment(0)
S
6

Since XMMATRIX represents a 16-byte aligned 4x4 matrix, the unaligned allocation of g_World1 causes the access violation (simply put, g_World1's address is not divisible by 16).

Sort of solution: enable structure member alignment by 16 bytes (for MyClass to have the g_World1 "in place"). But still you'll have to ensure, that MyClass instances reside at the addresses divisible by 16.

You can use the placement 'new' operator to allocate MyClass objects.

About alignment see here: How to align pointer

Sunken answered 1/7, 2012 at 21:27 Comment(6)
Maybe it's a stupid question but how to achive it? I have made a struct Matrixs that contains four matrixs (view, world etc.) but how to 'enable structure member alignment by 16 bytes' for it?Olcott
For VStudio: Project Properties -> Configuration Properties -> C/C++ -> Code Generation -> Struct Memeber Alignment -> select 16 thereSunken
For GCC there is an "attribute ((aligned (16)))" for structsSunken
Viktor Latypov, thanks. I have done it for VStudio, but still I have the same error.Olcott
Alignment is only the part of the problem. Imaging you have a MyClass starting at, say, 8. The g_World will have the "8 + 16 * N" address. That does not help you much. You should allocate a memory block for XMMATRIXes which starts at 16-byte aligned address.Sunken
You can also use the SimpleMath wrapper types from DirectX Tool Kit which do the load/stores automatically for you.Tletski
T
5

XMVECTOR and XMMATRIX are the 'register proxy' types. You can use them safely as types for the Xbox 360, Xbox One, and Windows x64 platforms as they all natively have 16-byte alignment for the data on the stack and allocated on the heap.

Using them for Windows 32-bit or Windows RT/ARM takes more effort since the native alignment is les than 16-bytes. One approach is the technique used by DirectX Tool Kit... it uses the pImpl idiom and the pImpl internal classes are explicitly allocated with 16-byte alignment which is where XMVECTOR and XMMATRIX types are used directly. Another approach is to use all the various 'storage' types like XMFLOAT4 and XMFLOAT4X4.

Note: the DirectXMath programmer's guide covers this. It's not a long document to read, and it's packed with a lot of hints and recommendations.

PS: There's a version of the standard Direct3D tutorials for Win32 desktop on MSDN Code Gallery that does not require the DirectX SDK... it just uses the Windows 8.x SDK included with VS 2012 or VS 2013.enter link description here

Tletski answered 26/6, 2014 at 7:28 Comment(0)
O
1

Thank you.

Finally I decided to use XMLoadFloat4x4() and XMStoreFloat4x4() functions. I store members of class as Float4x4 and convert them for temporary use to XMMATRIX every render() loop. But... it's a fast or dumb solution?

Olcott answered 1/7, 2012 at 23:2 Comment(2)
Consider starting another question, this is not a discussion forum. If the number of matrices is small this won't be an issue.Sunken
Looks like they are equal. If you do not convert them to XMMatrix for calculations (lol), of course.Amidase
N
1

In the Book "Introduction to 3D Game Programming with Directx 11" from "Frank D. Luna" it says:

Do not use XMMATRIX as Member of a class or Structure. Always use XMFloat4x4 and load and store back if you need it.

Nicki answered 24/6, 2014 at 22:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.