Introduction
DirectXMath
is a great SIMD-friendly Visual Studio C++ Math Library. It requires Visual Studio 2010 and later and targets Windows Vista and later. It can also be used with operating systems based on the neon-arm processor.
DirectXMath
is mostly used for game, multimedia and image processing programming, but is also frequently a tool in physics and electronics modeling, artificial intelligence and other areas of science and math.
You cannot use DirectXMath
if you develop in any programming language other than C++ or even if you develop with a non-Microsoft C++ compiler.
DMath
is totally developed in x86 and x64 Assembly Language and contains all 547 functions of DirectXMath
3.09. DMath
is not a SIMD-friendly library, it is a 100% SIMD library. While DirectXMath
uses special C++ structures to align data to memory before using SIMD through intrinsics, DMath
makes the alignment within the Assembly Language itself. This makes it possible to use all the features of DirectXMath
from any programming language. The DMath
library has been tested extensively over many months, it appears stable but like any other software, it may contain bugs and, of course, is subject to improvements.
DMath versus DirectXMath
DMath
is fully compatible with DirectXMath
, i.e., you will obtain the same output. Well, not 100% correct, in a small number of cases, the output from DMath
is more precise because the algorithm is better. For example, DMath XMVectorPow
comes very close to the results of the Windows Calculator for power calculations while DirectXMath
diverges noticeably for large exponents. You can safely infer that we believe that the Windows Calculator has a good algorithm to calculate powers :)
- In most cases,
DMath
is faster than DirectXMath
, but not dramatically faster. We found that where DirectXMath
is a little bit faster is related to the fact that it inlines almost every call to a function. DMath
inlines a lot of calls as well, but not as many. On the other hand, DMath
is clearly faster in functions where DirectXMath
uses x87 floating point instructions for calculations and there is a bunch of them within DirectXMath
.
DMath
can be used with old Windows operating systems (it was tested in Windows 2000) because SSE instructions depend much more on the CPU than on the operating system itself.
DMath
is simpler to use because many of DirectXMath
special structures and types are just meant to solve alignment problems in C++. DMath
solves them inside the Assembly Language itself - and you should not use such structures and types with DMath
! For example, even from Visual Studio C++ don't use variables of type __m128
with the DMath
library.
DMath Deployment
Essentially, DMath
is contained in 2 DLLs, one is compiled for x86 using the CDecl calling convention and the other for x64 Intel processors using the Windows ABI. We plan for the short term to provide static linking facilities instead of the DLLs for people that have more advanced needs. And in the future, if it is worth the effort, we may compile for other operating systems of the Intel family, but currently we are all committed with Windows.
What DMath Contains?
As mentioned earlier, DMath
contains 547 functions which are the whole contents counterpart of the same number of functions included in the various files that make up the DirectXMath
library.
We have not included in this article Collision functions, other than the TriangleTests
functions because they are not part of the DirectXMath
Library proper. However, we will deal with them in forthcoming articles.
Using DMath from C#
- C#, and the .NET languages in general, are, in my opinion, the most difficult languages to interface with native code. Add to that the sad fact that I am not an expert in .NET languages, so the simple perception that I was able to make
DMath
work with C# makes me feel happy. Probably, you can improve on my solution and I would love to see people come up with alternatives.
Now, a little correction, I was lying! C# is not actually interfacing with DMath
, I made a .NET library in C++ CLI that C# references. Most complications I had to deal with are actually on the C++ CLI side, the C# side is the application you will be developing and I don't think you will find difficulties to get it up and running. If you are a Visual Basic aficionado, you will find your way as easily because, as I mentioned, the interface nitty gritties are in the C++ CLI library.
- From C#, the
DMath
functions are contained in 2 namespaces defined in C++ CLI (in the DMathLib.h file):
- The
DMathLib
namespace contains most functions and structures (see csharpns1.zip, for the C# semantics of such elements). Note that structure names are prefixed with "dm
" in relation to their DirectXMath
counterpart. So XMVECTOR
will be dmXMVECTOR
, XMMATRIX
will be dmXMMATRIX
, etc.
- The
Collision
namespace contains the 4 TriangleTests
functions (see csharpns2.zip, for the C# semantics of such elements).
- When making an application, bear in mind that you have 3 DLLs to deal with: 1 native x86 DLL (DMathCDll32.dll), 1 native x64 DLL (DMathDll64.dll) and 1 .NET library DLL (DMathLib.dll).
The best way to deal with all this is make a solution with the .NET library project and your application project (see our demo).
Your C# application must be built either for x86 or x64, the ALL CPUs alternative will not work.
To automate things and copy the correct DLLs to the Output folder according to the CPU bitness, edit the Project file of your application and add the following lines (see our demo):
<ItemGroup Condition="'$(Platform)'=='x64'">
<Content Include="DMathDll64.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition="'$(Platform)'=='x86'">
<Content Include="DMathCDll32.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Reference Include="DMathLib"
Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<HintPath>Debug\DMathLib.dll</HintPath>
</Reference>
<Reference Include="DMathLib"
Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<HintPath>Release\DMathLib.dll</HintPath>
</Reference>
<Reference Include="DMathLib"
Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<HintPath>x64\Release\DMathLib.dll</HintPath>
</Reference>
<Reference Include="DMathLib"
Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<HintPath>x64\Debug\DMathLib.dll</HintPath>
</Reference>
- After building the application, you will need to include in the distribution either the x86 (if you compiled for x86) or the x64 native DLL (if you compiled for x64) and the library DLL. When we are able to provide static linking (see above) instead of the native DLLs you will be able to have a standalone application, as explained in our previous article, Mixing .NET and Assembly Language in a standalone 64-bit EXE.
Our Demo
Our Demo tests almost every DMath
function - not all, because some functions are just slight variations of others. You will see that the results are presented extremely fast in spite of some functions being very complex. No wonders for this, there are Assembly Language behind the scenes that more than compensate for all the marshaling hips and hops.
A previous note at this point, I am aware that some of the parameter values used in the demo are not realistic, even when not trapped by the assert
functions. But the purpose of the demo is just to show how to use each function. BTW, I have tested separately each function with DirectXMath
in a C++ application to confirm that the results are the same, and they are.
The solution was built with Visual Studio 2015. The DMathLib
project uses the VS 2013 toolset, so Visual Studio 2015 may invite you to upgrade. I would decline the upgrade, if I intend to run at least on Windows 7 without further complications. But you can accept the challenge and deal with it.
What is Next?
This article is part 1 of a number not yet established of parts. All will depend on the audience's interest, I have no clue about that.