Introduction to HPM – High-Performance Matrices Libary

Computer graphics are used all from movies, renders, games and etc. What they all have in common is that they are based on math. Commonly linear algebra for doing both 2D and 3D. Where like points and vectors needs to transformed, projected and etc. Therefore, here I will give a simple introduction to a library that provides many common linear algebra math functions used in real-time graphics and as well renders.

This library has been part of a hobby project for learning primarily SIMD programming and how much of a improvement it can yield in a runtime applications.

HPM – High-Performance Matrices

Hpm is a 3D math library that supports multiple SIMD (single instruction multiple data) extensions. This can signification improve the performance of many of the mathematical functions. Furthermore, the selected SIMD extension can be chosen during runtime as well changed. But none of the functions of the library is allowed to be executed before being initialized nor being changed.

Initialize the Library

Before any of the functions associated with the library can be used. The library has to be initialized with the specified SIMD extension. But if you don’t know what version or just want the library to choose the latest extension. The HPM_DEFAULT argument can be passed via the hpm_init function. However, if you wish to use no SIMD extension whatsoever, the HPM_NOSIMD argument can be used instead. It will load the functions pointer that does not utilize any SIMD extension.

See Following for what SIMD enums that are present in the library.

/**
 * SIMD (single instruction multiple data) extensions flags.
 */
#define HPM_NONE        (0 << 0)    /*  No HPM SIMD exention flag.	*/
#define HPM_NOSIMD      (1 << 0)    /*  No SIMD hardware feature, using the FPU and ALU.	*/
#define HPM_MMX         (1 << 1)    /*  MMX. (Yet not supported)	*/
#define HPM_SSE         (1 << 2)    /*  SSE (Streaming SIMD Extensions).	*/
#define HPM_SSE2        (1 << 3)    /*  SSE2 (Streaming SIMD Extensions).	*/
#define HPM_SSE3        (1 << 4)    /*  SSE3 (Streaming SIMD Extensions).	*/
#define HPM_SSSE3       (1 << 5)    /*  SSSE3 (Streaming SIMD Extensions).	*/
#define HPM_SSE4_1      (1 << 6)    /*  SSE4.1 (Streaming SIMD Extensions).	*/
#define HPM_SSE4_2      (1 << 7)    /*  SSE4.2 (Streaming SIMD Extensions).	*/
#define HPM_AVX         (1 << 8)    /*  AVX Version 1 (Advanced Vector Extension).	*/
#define HPM_AVX2        (1 << 9)    /*  AVX Version 2 (Advanced Vector Extension).	(Not tested)*/
#define HPM_AVX512      (1 << 10)   /*  AVX512 (Advanced Vector Extension). (Yet not supported)	*/
#define HPM_NEON        (1 << 11)   /*  ARM	FPU (floating-point unit) feature.	*/
#define HPM_FMA         (1 << 12)   /*  Not supported.	*/
#define HPM_SVML        (1 << 29)   /*  Not supported.	*/
#define HPM_ACML        (1 << 30)   /*  Not supported.	*/
#define HPM_DEFAULT     (1 << 31)   /*  Default, makes attempt to take the best SIMD extension on the system.	*/

The following example will only initialize followed by releasing the functions. The release functions is not required. However, if you wish to change SIMD extension at runtime it will be required.

#include<hpm/hpm.h>

int main(int argc, const char** argv){
	hpm_init(HPM_SSE2);
	hpm_release();
}

Vector Math Functions

With the library initialize and ready. Let us look at some vector math functions commonly used in 3D applications that are supported via the hpm library.

Dot product

The dot product is a common function used for things like light contribution, how much two vectors align in the angle between and etc. See the following equation:

The dot product can expressed both as the sum of product of each element.

(1)   \begin{equation*} A \cdot B = \sum_{i=1}^{n} A_i \cdot B_i  = |A| |B|\cos(\theta) \end{equation*}

#include<hpm/hpm.h>

int main(int argc, const char** argv){
	hpm_init(HPM_SSE2);
	hpmvec4f vec1 = { 1, 2, 1, 1 };
	hpmvec4f vec2 = { 1, 0, 6, 1 };
	float dot = hpm_vec4_dotfv(&vec1, &vec2);
	hpm_release();
}

Matrix Multiplication for MVP (Model View Projection)

Now, let us look at a common important example for most 3D applications. Computing the model view projection (MVP) matrix in order to display the 3D geometry.

#include<hpm/hpm.h>

int main(int argc, const char** argv){
	hpm_init(HPM_SSE2);
        hpmvec4x4f_t A;
	hpmvec4x4f_t B;
	hpmvec4x4f_t C;
	hpm_mat4x4_identityfv(&A);
	hpm_mat4x4_identityfv(&A);
        hpm_mat4x4_multiply_mat4x4fv(&A, &B, &C);
	hpm_release();
}

Quaternion Multiplication

Rotation in 3D has its challenges. The old method uses Eular rotation, but it’s slow and has a gimble lock which will cause some rotation from a to be to not be a linear rotation but instead rotated not expected.

#include<hpm/hpm.h>

int main(int argc, const char** argv){
	hpm_init(HPM_SSE2);
        hpmquatf q1;
        hpmquatf q2;
        hpmquatf q3;
	hpm_quat_identityfv(&q1);
	hpm_quat_identityfv(&q2);
        hpm_quat_multi_quatfv(&q1, &q2, &q2);
	hpm_release();
}

Wrapper support

The library has been exported to a couple of other programming languages. Currently, two exported language has been supported such as Java and C++. Though, of course, there can be some performance penalty as a consequence of having additional instruction in order to execute the main hpm functions.

Resources

The source code for the HPM C library can be found at GitHub:

  • C Version: The native version of the library.
  • Java Version: It uses JNI (Java Native Interface) to translates the java execution to C execution.’
  • C++ Version: Class wrapper exposed in the header for reducing overhead.
  • C# – Work in progress
  • Lua – Work in progress