Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

DMath is DirectXMath for All

0.00/5 (No votes)
5 Mar 2017 1  
Part 1 - Using DMath from C#

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

  1. 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 :)
  2. 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.
  3. 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.
  4. 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#

  1. 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.
  2. From C#, the DMath functions are contained in 2 namespaces defined in C++ CLI (in the DMathLib.h file):
    1. 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.
    2. The Collision namespace contains the 4 TriangleTests functions (see csharpns2.zip, for the C# semantics of such elements).
  3. 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>
  4. 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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here