Moving to DirectXMath
I'm at the point where my codebase is growing larger and larger.
Since I'm still on dx9 and plan to move to / also support dx11, I'm thinking about moving from using d3dx to directxmath. Especially because I'm expanding my codebase with quite some math related stuff (collisions and intersections).
My question is basically what your advice would be, pro's and cons
(will directxmath work fine both with dx9 and 11? Etc)
Ps: for mesh usage and loading for now I'll stick to d3dxmesh, will change that later on. Above I'm aiming at basically ALL other d3dx usage in my engine.
DirectXMath is not directly related to Direct3D/DXGI/WDDM stuffs, so you can use it with both DX9 and DX11, work with both X86 (IA32/SSE/SSE2/x64) and ARM (with ARM NEON support).
It is pretty easy to use, you only need to pay attention to data alignment of vector and matrix structures (you can disable the alignment requirement if you want with the _XM_NO_INTRINSICS_ macro).
On MSDN library you can find a pretty decent programming guide (with migration notes from D3DXMath and compatibility tables with D3DDECLTYPE, D3DFORMAT and DXGI_FORMAT).
The reference guide is pretty decent too, however you had to pay attention if you are using the RH coordinate system since some function without the proper coordinate system suffix need some attention (like the function involving axis... see the "remark" paragraph of related reference guide).
On directx sdk blog you can find some additional x86 SIMD extensions (SSE3/3S/4./4.1, AVX, FMA3/4, F16C...), they are linked somewhere on msdn library too.
DirectX Tool Kit has a DirectXMath wrapper too if you find it too much complicated.
(you can disable the alignment requirement if you want with the _XM_NO_INTRINSICS_ MAXRO).
There is no good reason to do this. XMVECTOR is _not_ meant for storing in general heap-allocated objects. It's for doing computations in local variables or special-purpose buffers. Use XMFLOAT2/3/4 for storing data in heap-allocated objects. Using strict alignment is a performance win but not at all mandatory if the DirectXMath library if used correctly.
(you can disable the alignment requirement if you want with the _XM_NO_INTRINSICS_ MAXRO).
There is no good reason to do this. XMVECTOR is _not_ meant for storing in general heap-allocated objects. It's for doing computations in local variables or special-purpose buffers. Use XMFLOAT2/3/4 for storing data in heap-allocated objects. Using strict alignment is a performance win but not at all mandatory if the DirectXMath library if used correctly.
A good reason could be immediately starting using DirectXMath and become familiar with it, avoiding awkward alignments (like _aligned_mallc plus placement new) if you planned to write your own custom allocator (maybe with different platforms-specific intrinsics) but you don't have it yet ready. When your custom allocator is done and it's ready to use, you will just need to remove that macro.
When I read stuff about intrinsics, macro's etc., honestly I'm not connected.
Maybe I'm thinking too simple, but I believe these are the main things I have to do
- replace all class members of type D3DXVECTOR3 by XMFLOAT3's
- do the same for local D3DXVECTOR3's, which are created on the stack/ within scope of (member) functions
- do the above again, but for D3DXMATRIX to XMFLOAT4X4
- remove all includes of d3dx9(d).h, except in my mesh class header and cpp file
- compile and replace all uses d3dxfunctions by the directxmath replacement, throughout my codebase
Ofcourse I'll run into some minor bumps, but I believe this should be it.
For now I don't see reasons to use XMVECTOR or XMMATRIX instead, based on the MSDN reference I read. I currently also don't use the D3DX.....16 types, for alignment, because I don't have specific reasons to do so (no pre-optimizations wasting time and increasing future risks).
But... If I'm overseeing something, please tell me
You've pretty much covered a lot. I recently switched from DX9 to D3D11. I've converted quite a few classes using just the method you described.
A couple of times I did a search/replace-all in a file for the classes you named and hit the compile key to let VS locate needed corrections. You will need to use XMVECTOR and XMMATRIX for calcs but you'll pick that up pretty quickly. E.g.,
D3DXMATRIX mat1, mat2, mat3;
mat3 = mat1 * mat2;
becomes
XMFLOAT4X4 mat1, mat2, mat3;
XMStoreFloat4x4(&mat3, XMMatrixMultiply(XMLoadFloat4x4(&mat1),XMLoadFloat4x4(&mat2));
That will come pretty quickly to you, I believe.
XMFLOAT* structures don't require any particular alignment and they are meant to be used for simple tasks and getting/settings data.Thanks. I'll probably move on to using directxmath asap.
When I read stuff about intrinsics, macro's etc., honestly I'm not connected.
Maybe I'm thinking too simple, but I believe these are the main things I have to do
- replace all class members of type D3DXVECTOR3 by XMFLOAT3's
- do the same for local D3DXVECTOR3's, which are created on the stack/ within scope of (member) functions
- do the above again, but for D3DXMATRIX to XMFLOAT4X4
- remove all includes of d3dx9(d).h, except in my mesh class header and cpp file
- compile and replace all uses d3dxfunctions by the directxmath replacement, throughout my codebase
Ofcourse I'll run into some minor bumps, but I believe this should be it.
For now I don't see reasons to use XMVECTOR or XMMATRIX instead, based on the MSDN reference I read. I currently also don't use the D3DX.....16 types, for alignment, because I don't have specific reasons to do so (no pre-optimizations wasting time and increasing future risks).
But... If I'm overseeing something, please tell me
XMVECTOR and XMMATRIX take advantage of CPU SIMD so they are meant to be used for computation and most useful DirectXMath function need and use XMVECTOR and XMMATRIX.
They require 16-byte alignment in order to use CPU SIMD extensions like SSE2 and ARM NEON. For automatic allocation (data and stack) you only need to add the /Zp16 compiler flag, for dynamic allocation you need to manually it manually (like _aligned_malloc + placement new) or to write your own custom allocator.
If 16-byte alignment is a problem for you or a pre-optimization wasting time just declare the _XM_NO_INTRINSICS_ macro, and everything will run fine.
Here you can find a direct D3DX-DirectXMath comparison and migration guide: http://msdn.microsoft.com/en-us/library/windows/desktop/ff729728(v=vs.85).aspx
There are some blanks for me. Are these conclusions correct:
- my goal is to make advantage of computation advantages (SSE intrinsics etc.)
- having a good balance, without having to use macro's or manual alignment code
I'll do this by:
- making class members of the types XMFLOATx and XMFLOATxXx
(for alignment reasons)
- for local variables in scope of functions I use XMVECTOR and XMMATRIX types, to take advantage of better computation (SSE etc.) without casting
-- when I need to use, either read or write to the class members of XMFLOAT... type, I always have to cast them to XMVECTOR/XMMATRIX types, when I want to use the DirectXMath functions. I probably also need to "cast" the results back into the class members
This sounds doable.
Till now I always used D3DX and build up a code base for frustum culling, bounding volume checks (intersection/ collision) etc. Besides the math I've learned doing this, I'm thinking about using the functions that do the same coming from the DirectXMath library. What do you think?
Another assumption I have to check, is that I can pass both XMFLOAT (class members in my case) as XMVECTOR/MATRIX type to set shader constants (for now with d3d9, later on d3d11). Now I think of it, I also have to find a solution when not using the d3dx effect framework anymore. Probably compiling the PS and VS manually. The good thing is that I don't set any states through my effects (I use my own state manager for that, through my code).
Then you need 16-byte aligment.- my goal is to make advantage of computation advantages (SSE intrinsics etc.)
Then you need to define and code your own allocator.- having a good balance, without having to use macro's or manual alignment code
XMFLOATx and XMFLOAtxXx don't need 16-byte aligment.- making class members of the types XMFLOATx and XMFLOATxXx
(for alignment reasons)
Remember that /Zp16 must be used setted, you can find the option in the C++ /Code generation tab in the project proprieties.- for local variables in scope of functions I use XMVECTOR and XMMATRIX types, to take advantage of better computation (SSE etc.) without casting
DirectXMath provides loading and storing function for that : )-- when I need to use, either read or write to the class members of XMFLOAT... type, I always have to cast them to XMVECTOR/XMMATRIX types, when I want to use the DirectXMath functions. I probably also need to "cast" the results back into the class members
Aside from data alignment, DirectXMath is a natural evolution of D3DX, you should not having particular problem to convert the code.Till now I always used D3DX and build up a code base for frustum culling, bounding volume checks (intersection/ collision) etc. Besides the math I've learned doing this, I'm thinking about using the functions that do the same coming from the DirectXMath library. What do you think?
Dunno if XMVECTOR could be passed directly to shaders(I always used XMFLOAT* for getting and settings data), however XMMATRIX could bepassed as D3D11_MAPPED_SUBRESOURCE.pData.Another assumption I have to check, is that I can pass both XMFLOAT (class members in my case) as XMVECTOR/MATRIX type to set shader constants (for now with d3d9, later on d3d11). Now I think of it, I also have to find a solution when not using the d3dx effect framework anymore. Probably compiling the PS and VS manually. The good thing is that I don't set any states through my effects (I use my own state manager for that, through my code).
Remember that /Zp16 must be used setted
You don't need /Zp16 at all. The vector types are already set up with __declspec(align(16)) so they will get 16 byte aligned as local/global/static variables without any need for compiler flags. The only time you need to worry about alignment is on heap allocated data.
http://blogs.msdn.com/b/oldnewthing/archive/2007/12/27/6873648.aspx