Skip to content

Instantly share code, notes, and snippets.

@Doprez
Last active June 24, 2024 05:12
Show Gist options
  • Save Doprez/04d61e03915a9527a482cddbaa826544 to your computer and use it in GitHub Desktop.
Save Doprez/04d61e03915a9527a482cddbaa826544 to your computer and use it in GitHub Desktop.
Testing faster conversion methods between different C# math libraries.
using BenchmarkDotNet.Attributes;
using NVector3 = System.Numerics.Vector3;
using SVector3 = Stride.Core.Mathematics.Vector3;
using MVector3 = Microsoft.Xna.Framework.Vector3;
using MMatrix = Microsoft.Xna.Framework.Matrix;
using NMatrix = System.Numerics.Matrix4x4;
using SMatrix = Stride.Core.Mathematics.Matrix;
using NQuaternion = System.Numerics.Quaternion;
using MQuaternion = Microsoft.Xna.Framework.Quaternion;
using SQuaternion = Stride.Core.Mathematics.Quaternion;
namespace TestMath;
[RPlotExporter]
[MemoryDiagnoser]
public class ConversionTest
{
[Params(100, 10000)]
public int Iterations;
public SVector3 SVector = new(1, 2, 3);
public NVector3 NVector = new(1, 2, 3);
public MVector3 MVector = new(1, 2, 3);
public MMatrix MMatrix = new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
public NMatrix NMatrix = new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
public SMatrix SMatrix = new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
public MQuaternion MQuaternion = new(1, 2, 3, 4);
public NQuaternion NQuaternion = new(1, 2, 3, 4);
public SQuaternion SQuaternion = new(1, 2, 3, 4);
[Benchmark]
public void Vector3_TestStrideToNumericWithNew()
{
for (int i = 0; i < Iterations; i++)
{
SVector3.Subtract(NVector.NumericToStride(), NVector.NumericToStride());
}
}
[Benchmark]
public void Vector3_TestStrideToNumericWithUnsafeAs()
{
for (int i = 0; i < Iterations; i++)
{
SVector3.Subtract(NVector.NumericToStrideUnsafe(), NVector.NumericToStrideUnsafe());
}
}
[Benchmark]
public void Matrix_TestStrideToNumericWithNew()
{
for (int i = 0; i < Iterations; i++)
{
SMatrix.Subtract(NMatrix.NumericToStride(), NMatrix.NumericToStride());
}
}
[Benchmark]
public void Matrix_TestStrideToNumericWithUnsafeAs()
{
for (int i = 0; i < Iterations; i++)
{
SMatrix.Subtract(NMatrix.NumericToStrideUnsafe(), NMatrix.NumericToStrideUnsafe());
}
}
[Benchmark]
public void Quaternion_TestStrideToNumericWithNew()
{
for (int i = 0; i < Iterations; i++)
{
SQuaternion.Subtract(NQuaternion.NumericToStride(), NQuaternion.NumericToStride());
}
}
[Benchmark]
public void Quaternion_TestStrideToNumericWithUnsafeAs()
{
for (int i = 0; i < Iterations; i++)
{
SQuaternion.Subtract(NQuaternion.NumericToStrideUnsafe(), NQuaternion.NumericToStrideUnsafe());
}
}
[Benchmark]
public void Vector3_MonoToNumericWithNew()
{
for (int i = 0; i < Iterations; i++)
{
MVector3.Subtract(NVector, NVector);
}
}
[Benchmark]
public void Vector3_MonoToNumericWithUnsafeAs()
{
for (int i = 0; i < Iterations; i++)
{
MVector3.Subtract(NVector.NumericToMonoUnsafe(), NVector.NumericToMonoUnsafe());
}
}
[Benchmark]
public void Matrix_MonoToNumericWithNew()
{
for (int i = 0; i < Iterations; i++)
{
MMatrix.Subtract(NMatrix.NumericToMono(), NMatrix.NumericToMono());
}
}
[Benchmark]
public void Matrix_MonoToNumericWithUnsafeAs()
{
for (int i = 0; i < Iterations; i++)
{
MMatrix.Subtract(NMatrix.NumericToMonoUnsafe(), NMatrix.NumericToMonoUnsafe());
}
}
[Benchmark]
public void Quaternion_MonoToNumericWithNew()
{
for (int i = 0; i < Iterations; i++)
{
MQuaternion.Subtract(NQuaternion, NQuaternion);
}
}
[Benchmark]
public void Quaternion_MonoToNumericWithUnsafeAs()
{
for (int i = 0; i < Iterations; i++)
{
MQuaternion.Subtract(NQuaternion.NumericToMonoUnsafe(), NQuaternion.NumericToMonoUnsafe());
}
}
}
using System.Runtime.CompilerServices;
using NVector3 = System.Numerics.Vector3;
using SVector3 = Stride.Core.Mathematics.Vector3;
using MVector3 = Microsoft.Xna.Framework.Vector3;
using MMatrix = Microsoft.Xna.Framework.Matrix;
using NMatrix = System.Numerics.Matrix4x4;
using SMatrix = Stride.Core.Mathematics.Matrix;
using NQuaternion = System.Numerics.Quaternion;
using MQuaternion = Microsoft.Xna.Framework.Quaternion;
using SQuaternion = Stride.Core.Mathematics.Quaternion;
namespace TestMath;
public static class MathExtensions
{
public static NVector3 StrideToNumericUnsafe(this SVector3 v)
{
return Unsafe.As<SVector3, NVector3>(ref v);
}
public static SVector3 NumericToStrideUnsafe(this NVector3 v)
{
return Unsafe.As<NVector3, SVector3>(ref v);
}
public static SMatrix NumericToStrideUnsafe(this NMatrix v)
{
return Unsafe.As<NMatrix, SMatrix>(ref v);
}
public static NMatrix StrideToNumericUnsafe(this SMatrix v)
{
return Unsafe.As<SMatrix, NMatrix>(ref v);
}
public static SQuaternion NumericToStrideUnsafe(this NQuaternion v)
{
return Unsafe.As<NQuaternion, SQuaternion>(ref v);
}
public static NQuaternion StrideToNumericUnsafe(this SQuaternion v)
{
return Unsafe.As<SQuaternion, NQuaternion>(ref v);
}
public static MVector3 MonoToNumericUnsafe(this MVector3 v)
{
return Unsafe.As<MVector3, NVector3>(ref v);
}
public static MVector3 NumericToMonoUnsafe(this NVector3 v)
{
return Unsafe.As<NVector3, MVector3>(ref v);
}
public static MMatrix MonoToNumericUnsafe(this MMatrix v)
{
return Unsafe.As<MMatrix, NMatrix>(ref v);
}
public static MMatrix NumericToMonoUnsafe(this NMatrix v)
{
return Unsafe.As<NMatrix, MMatrix>(ref v);
}
public static NQuaternion MonoToNumericUnsafe(this MQuaternion v)
{
return Unsafe.As<MQuaternion, NQuaternion>(ref v);
}
public static MQuaternion NumericToMonoUnsafe(this NQuaternion v)
{
return Unsafe.As<NQuaternion, MQuaternion>(ref v);
}
public static NVector3 StrideToNumeric(this SVector3 v)
{
return new NVector3(v.X, v.Y, v.Z);
}
public static SVector3 NumericToStride(this NVector3 v)
{
return new SVector3(v.X, v.Y, v.Z);
}
public static MVector3 NumericToMono(this NVector3 v)
{
return new MVector3(v.X, v.Y, v.Z);
}
public static NVector3 MonoToNumeric(this MVector3 v)
{
return new NVector3(v.X, v.Y, v.Z);
}
public static MMatrix MonoToNumeric(this MMatrix v)
{
return new MMatrix(v.M11, v.M12, v.M13, v.M14, v.M21, v.M22, v.M23, v.M24, v.M31, v.M32, v.M33, v.M34, v.M41, v.M42, v.M43, v.M44);
}
public static NMatrix NumericToMono(this NMatrix v)
{
return new NMatrix(v.M11, v.M12, v.M13, v.M14, v.M21, v.M22, v.M23, v.M24, v.M31, v.M32, v.M33, v.M34, v.M41, v.M42, v.M43, v.M44);
}
public static NQuaternion MonoToNumeric(this MQuaternion v)
{
return new NQuaternion(v.X, v.Y, v.Z, v.W);
}
public static MQuaternion NumericToMono(this NQuaternion v)
{
return new MQuaternion(v.X, v.Y, v.Z, v.W);
}
public static SMatrix NumericToStride(this NMatrix v)
{
return new SMatrix(v.M11, v.M12, v.M13, v.M14, v.M21, v.M22, v.M23, v.M24, v.M31, v.M32, v.M33, v.M34, v.M41, v.M42, v.M43, v.M44);
}
public static NMatrix StrideToNumeric(this SMatrix v)
{
return new NMatrix(v.M11, v.M12, v.M13, v.M14, v.M21, v.M22, v.M23, v.M24, v.M31, v.M32, v.M33, v.M34, v.M41, v.M42, v.M43, v.M44);
}
public static SQuaternion NumericToStride(this NQuaternion v)
{
return new SQuaternion(v.X, v.Y, v.Z, v.W);
}
public static NQuaternion StrideToNumeric(this SQuaternion v)
{
return new NQuaternion(v.X, v.Y, v.Z, v.W);
}
}
@Doprez
Copy link
Author

Doprez commented Jun 18, 2024

Benchmark tests with MonoGame, Stride, .Net:
image

@Doprez
Copy link
Author

Doprez commented Jun 24, 2024

stride3d/stride#291
This explains the issues with Strides matrix conversions and they are actually invalid due to the layout.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment