* Box Simd

* Add 256 bit version of GetAABB

* Add AABB bechmarks

* No real diff between 128 & 256, so removing 256

| Method     | Mean      | Error     | StdDev    | Ratio |
|----------- |----------:|----------:|----------:|------:|
| GetAABB    | 5.8107 ns | 0.0154 ns | 0.0137 ns |  1.00 |
| GetAABB128 | 0.4927 ns | 0.0003 ns | 0.0002 ns |  0.08 |
| GetAABB256 | 0.4332 ns | 0.0006 ns | 0.0006 ns |  0.07 |

* Add Box2Rotated.Transform Benchmark

* Results

20% faster and much smaller code. Also I don't think it inlined RotateVec

* Add Matrix3x2Helper.TransformBox() benchmark

new:

| Method    | Mean     | Error     | StdDev    | Code Size |
|---------- |---------:|----------:|----------:|----------:|
| Transform | 2.463 ns | 0.0766 ns | 0.0679 ns |     216 B |

old:
| Method    | Mean     | Error     | StdDev    | Median   | Code Size |
|---------- |---------:|----------:|----------:|---------:|----------:|
| Transform | 9.469 ns | 0.2140 ns | 0.5408 ns | 9.206 ns |     621 B |

* Fix polygon constructor

* SlimPolygonBenchmark

* use new SimdHelper for other methods

* Fix bugs

* Use new methods

* Simd SlimPolygon.ComputeAABB

* Move simd transform to physics

* Cleanup

* Remove uneccesary Unsafe.SkipInit

* These tests all work on master

* Add Transform.MulSimd test

* Add SlimPolygon constructor tests

* Add ComputeAABB test

---------

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
Leon Friedrich
2025-11-10 20:30:08 +13:00
committed by GitHub
parent fe19ff9bd5
commit 3f19d25018
21 changed files with 638 additions and 193 deletions

View File

@@ -3,7 +3,6 @@ using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
namespace Robust.Shared.Maths;
public static class Matrix3Helpers
@@ -33,38 +32,52 @@ public static class Matrix3Helpers
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Box2 TransformBox(this Matrix3x2 refFromBox, Box2Rotated box)
public static Box2 TransformBox(this Matrix3x2 refFromBox, in Box2Rotated box)
{
return (box.Transform * refFromBox).TransformBox(box.Box);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void TransformBox(
this Matrix3x2 refFromBox,
in Box2Rotated box,
out Vector128<float> x,
out Vector128<float> y)
{
(box.Transform * refFromBox).TransformBox(box.Box, out x, out y);
}
public static Box2 TransformBox(this Matrix3x2 refFromBox, in Box2 box)
{
// Do transformation on all 4 corners of the box at once.
// Then min/max the results to get the new AABB.
TransformBox(refFromBox, box, out var x, out var y);
var aabb = SimdHelpers.GetAABB(x, y);
return Unsafe.As<Vector128<float>, Box2>(ref aabb);
}
/// <summary>
/// Applies a transformation matrix to all of a box's corners and returns their coordinates in two simd vectors.
/// </summary>
/// <remarks>The corners are ordered clockwise, starting from what was the bottom left corner prior to the transformation.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void TransformBox(
this Matrix3x2 refFromBox,
in Box2 box,
out Vector128<float> x,
out Vector128<float> y)
{
var boxVec = Unsafe.As<Box2, Vector128<float>>(ref Unsafe.AsRef(in box));
// Convert box into list of X and Y values for each of the 4 corners
var allX = Vector128.Shuffle(boxVec, Vector128.Create(0, 0, 2, 2));
var allY = Vector128.Shuffle(boxVec, Vector128.Create(1, 3, 3, 1));
var boxX = Vector128.Shuffle(boxVec, Vector128.Create(0, 2, 2, 0));
var boxY = Vector128.Shuffle(boxVec, Vector128.Create(1, 1, 3, 3));
// Transform coordinates
var modX = allX * Vector128.Create(refFromBox.M11);
var modY = allX * Vector128.Create(refFromBox.M12);
modX += allY * Vector128.Create(refFromBox.M21);
modY += allY * Vector128.Create(refFromBox.M22);
modX += Vector128.Create(refFromBox.M31);
modY += Vector128.Create(refFromBox.M32);
// Get bounding box by finding the min and max X and Y values.
var l = SimdHelpers.MinHorizontal128(modX);
var b = SimdHelpers.MinHorizontal128(modY);
var r = SimdHelpers.MaxHorizontal128(modX);
var t = SimdHelpers.MaxHorizontal128(modY);
var lbrt = SimdHelpers.MergeRows128(l, b, r, t);
return Unsafe.As<Vector128<float>, Box2>(ref lbrt);
x = Vector128.Create(refFromBox.M31)
+ boxX * Vector128.Create(refFromBox.M11)
+ boxY * Vector128.Create(refFromBox.M21);
y = Vector128.Create(refFromBox.M32)
+ boxX * Vector128.Create(refFromBox.M12)
+ boxY * Vector128.Create(refFromBox.M22);
}
/// <summary>
@@ -76,6 +89,23 @@ public static class Matrix3Helpers
return new Angle(Math.Atan2(t.M12, t.M11));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 CreateTransform(float posX, float posY, double angle)
{
// returns a matrix that is equivalent to returning CreateRotation(angle) * CreateTranslation(posX, posY)
var sin = (float) Math.Sin(angle);
var cos = (float) Math.Cos(angle);
return new Matrix3x2
{
M11 = cos,
M21 = -sin,
M31 = posX,
M12 = sin,
M22 = cos,
M32 = posY,
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 CreateTransform(float posX, float posY, double angle, float scaleX = 1, float scaleY = 1)
{