Skip to content

Instantly share code, notes, and snippets.

@Doprez
Last active December 25, 2024 03:00
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.

@Doprez
Copy link
Author

Doprez commented Dec 25, 2024

stride3d/stride#2238 (comment)
Fix for the Matrix conversions.

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