0
\$\begingroup\$

I'm writing a managed (c#) game engine and have stumbled on a bit of a crossroads in design/implementation regarding matrix types.

Matrix types need to be optimized for marshaling to native graphics api wrappers and shader compilers, etc and after viewing the way this is handled in various projects, I'm having a hard time deciding which route would be the optimal way to go.

The problem really arises with the internal storage of matrix data.

SharpDX (a very high quality managed DirectX wrapper) does so by explicitly defining each component as public fields such as:

public float M00, M01, M02, M03;
public float M10, M11, M12, M13;
public float M20, M21, M22, M23;

I'm assuming that this was done to simplify marshaling and also for faster access to fields during math operations and allows the type to be defined as a structure to be a true value type.

In Math.NET they store the internal representation as a one-dimensional array which still allows for rather simple marshaling but the definition becomes a reference type (class) using value-type semantics.

I also seen another implementation using a multi-dimensional array for the internal storage of data which makes performing operations on the field data more natural by using indexing by row and column but this would add overhead and would make marshaling a bit trickier due to the nature of interop with multi-dimensional arrays.

The SharpDX way seems ideal, as it makes the matrix types blittable and seems like it would be faster, however, being a value type would make it have a larger footprint (which I'm assuming is why most operations defined in SharpDX matrices have both pass-by-value and pass-by-ref functions defined).

In that light, it makes sense to define my matrix types as reference types so that only references are being passed, but then that makes interop a bit more challenging.

Being for a game engine, performance and memory footprint take priority over elegance though, so am I right in assuming SharpDX's approach would be best for my scenario?

\$\endgroup\$
1
\$\begingroup\$

I posted recently a response to a similar question https://stackoverflow.com/questions/24231389/struct-or-class-for-matrix-4x4-object

Basically valuetypes are the way to go for storing matrices, more benefits than downsides. You may also organize a matrix to be more GPU friendly by transposing the fields directly into the matrix struct (SharpDX is not doing this requiring a transpose of the final result before uploading it to the GPU) as HLSL matrix packing order is by default column major.

\$\endgroup\$
  • \$\begingroup\$ Thank you @xoofx. I figured that'd be the proper way to handle it and that answer you linked gave me some insight to the benefits. Great job with SharpDX by the way! Very impressive work. \$\endgroup\$ – Mike Johnson Jul 26 '14 at 1:50
  • \$\begingroup\$ Actually, I'm considering using your suggestion of using column-major layout to save needing to transpose matrices before marshaling but is there anything I need to be cautious of if I do use column-major layout? (I'd be using explicit layout via [FieldOffset(n)] attributes) \$\endgroup\$ – Mike Johnson Jul 26 '14 at 2:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.