mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-22 20:18:47 +00:00
Added SpanExtensions and the reinterpret between Unity's structs to System.Numerics structs
This commit is contained in:
parent
1e98e6910f
commit
e1a7ac03c6
@ -1,5 +1,6 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using UnityEngine;
|
||||
|
||||
namespace X10D.Unity.Numerics;
|
||||
@ -18,7 +19,7 @@ public static class QuaternionExtensions
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static System.Numerics.Quaternion ToSystemQuaternion(this Quaternion quaternion)
|
||||
{
|
||||
return new System.Numerics.Quaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w);
|
||||
return UnsafeUtility.As<Quaternion, System.Numerics.Quaternion>(ref quaternion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -30,6 +31,6 @@ public static class QuaternionExtensions
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion ToUnityQuaternion(this System.Numerics.Quaternion quaternion)
|
||||
{
|
||||
return new Quaternion(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
|
||||
return UnsafeUtility.As<System.Numerics.Quaternion, Quaternion>(ref quaternion);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using UnityEngine;
|
||||
|
||||
namespace X10D.Unity.Numerics;
|
||||
@ -18,7 +19,7 @@ public static class Vector2Extensions
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static System.Numerics.Vector2 ToSystemVector(this Vector2 vector)
|
||||
{
|
||||
return new System.Numerics.Vector2(vector.x, vector.y);
|
||||
return UnsafeUtility.As<Vector2, System.Numerics.Vector2>(ref vector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -30,7 +31,7 @@ public static class Vector2Extensions
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vector2 ToUnityVector(this System.Numerics.Vector2 vector)
|
||||
{
|
||||
return new Vector2(vector.X, vector.Y);
|
||||
return UnsafeUtility.As<System.Numerics.Vector2, Vector2>(ref vector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using UnityEngine;
|
||||
|
||||
namespace X10D.Unity.Numerics;
|
||||
@ -18,7 +19,7 @@ public static class Vector3Extensions
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static System.Numerics.Vector3 ToSystemVector(this Vector3 vector)
|
||||
{
|
||||
return new System.Numerics.Vector3(vector.x, vector.y, vector.z);
|
||||
return UnsafeUtility.As<Vector3, System.Numerics.Vector3>(ref vector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -30,7 +31,7 @@ public static class Vector3Extensions
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vector3 ToUnityVector(this System.Numerics.Vector3 vector)
|
||||
{
|
||||
return new Vector3(vector.X, vector.Y, vector.Z);
|
||||
return UnsafeUtility.As<System.Numerics.Vector3, Vector3>(ref vector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using UnityEngine;
|
||||
|
||||
namespace X10D.Unity.Numerics;
|
||||
@ -18,7 +19,8 @@ public static class Vector4Extensions
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static System.Numerics.Vector4 ToSystemVector(this Vector4 vector)
|
||||
{
|
||||
return new System.Numerics.Vector4(vector.x, vector.y, vector.z, vector.w);
|
||||
return UnsafeUtility.As<Vector4, System.Numerics.Vector4>(ref vector);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -30,7 +32,7 @@ public static class Vector4Extensions
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vector4 ToUnityVector(this System.Numerics.Vector4 vector)
|
||||
{
|
||||
return new Vector4(vector.X, vector.Y, vector.Z, vector.W);
|
||||
return UnsafeUtility.As<System.Numerics.Vector4, Vector4>(ref vector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -80,7 +80,7 @@ public static class Int32Extensions
|
||||
var shuffle = Avx2.Shuffle(vec, mask1);
|
||||
var and = Avx2.AndNot(shuffle, mask2);
|
||||
var cmp = Avx2.CompareEqual(and, Vector256<byte>.Zero);
|
||||
var correctness = Avx2.And(cmp, Vector256.Create((byte)0x01));
|
||||
var correctness = Avx2.And(cmp, Vector256.Create((byte)0x01));
|
||||
|
||||
Avx.Store((byte*)pDestination, correctness);
|
||||
}
|
||||
@ -110,6 +110,7 @@ public static class Int32Extensions
|
||||
and = Sse2.AndNot(shuffle, mask2);
|
||||
cmp = Sse2.CompareEqual(and, Vector128<byte>.Zero);
|
||||
correctness = Sse2.And(cmp, one);
|
||||
|
||||
Sse2.Store((byte*)pDestination + 16, correctness);
|
||||
}
|
||||
}
|
||||
|
89
X10D/src/Core/SpanExtensions.cs
Normal file
89
X10D/src/Core/SpanExtensions.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace X10D.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="Span{T}"/> and <see cref="ReadOnlySpan{T}"/>.
|
||||
/// </summary>
|
||||
public static class SpanExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicate whether a specific enumeration value is found in a span.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="span">The span to search from.</param>
|
||||
/// <param name="value">The enum to search for.</param>
|
||||
/// <returns><see langword="true"/> if found, <see langword="false"/> otherwise.</returns>
|
||||
/// <exception cref="ArgumentException">Unexpected enum memory size.</exception>
|
||||
#if NETSTANDARD2_1
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
#endif
|
||||
public static bool Contains<T>(this Span<T> span, T value) where T : Enum
|
||||
{
|
||||
return Contains((ReadOnlySpan<T>)span, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicate whether a specific enumeration value is found in a span.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="span">The span to search from.</param>
|
||||
/// <param name="value">The enum to search for.</param>
|
||||
/// <returns><see langword="true"/> if found, <see langword="false"/> otherwise.</returns>
|
||||
/// <exception cref="ArgumentException">Unexpected enum memory size.</exception>
|
||||
#if NETSTANDARD2_1
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#else
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
#endif
|
||||
public static bool Contains<T>(this ReadOnlySpan<T> span, T value)
|
||||
{
|
||||
// Use MemoryMarshal.CreateSpan instead of using creating new Span instance from pointer will trim down a lot of instructions
|
||||
// on Release mode.
|
||||
// https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBDAzgWwB8ABABgAJiBGAOgCUBXAOwwEt8YaBJFmKCAA4BlPgDdWYGLgDcAWABQZSrUYt2nAMIR8A1gBs+IqOMkyFxAExVzFIQAtsUAQBlsweszYc588wGZyGCYGfHIAFSkMAFFg0JByVhZyAG8FcnTyAEE0cgAhHI0cgBE0BQBfBX9KC3INFLSMgG0AKVYMAHEgvgkACgwATwEYCAAzHojcaNiASmmAXQb0xoBZGAw7CAATLh09HtX1rZ2BPQB5ATYIJlwaTIBzO9hcXFZRGB49RMS78kJyA4221250u11uDyeLzeIPYrAAXthQfNFpQAtQkORmLhsCMYORgBAIHp/mtAVQADxhAB8PSEAmwTEpVPIuHpTByYXIomwegYMGm5AA7nY+HjOfEYiF6vIMrLyLARgkkkEQrhyABeeUwRUAVWuOM4mVwlJyiQwNIVJPw0H6y0cuAcehonQwdG1oqYkh6rIZsx8coyxAA7FabXaoA6eTQNLBETA6QyepaVfhcDkfUwaM4gnd1tNo1cMNhErgenrsbjbsawqaWBbtVyeXy/SiKjKMiiWm1OkxumA+oNhmMJlMQrMFu2lgCjrt9qSZycYVcbvdHlIoe8mJ8mN9fiTDkDFxdWMvwWvnq8YDD8PDESemMjJ6jlBisQb8YTidPNhYmbS2UyLJshyja8vyQoirA4TkBKsTSgG6TBuQvaCuQCaMmaNLlgaVYAAoQGafBJg2qzWlAtr2o6zprG6uKwJ6MDemyszpmyWY5nmBYsMW1xlvqlZGiaSrmsRircmBLZPm2ZRAA===
|
||||
|
||||
// TODO: Figure out some kind of way to directly pass the Span directly into Contains call, which make method smaller and more prone to inlining...
|
||||
unsafe
|
||||
{
|
||||
#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
ref byte enums = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span));
|
||||
return MemoryMarshal.CreateSpan(ref enums, span.Length).Contains(Unsafe.As<T, byte>(ref value));
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
ref ushort enums = ref Unsafe.As<T, ushort>(ref MemoryMarshal.GetReference(span));
|
||||
return MemoryMarshal.CreateSpan(ref enums, span.Length).Contains(Unsafe.As<T, ushort>(ref value));
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
ref uint enums = ref Unsafe.As<T, uint>(ref MemoryMarshal.GetReference(span));
|
||||
return MemoryMarshal.CreateSpan(ref enums, span.Length).Contains(Unsafe.As<T, uint>(ref value));
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
ref ulong enums = ref Unsafe.As<T, ulong>(ref MemoryMarshal.GetReference(span));
|
||||
return MemoryMarshal.CreateSpan(ref enums, span.Length).Contains(Unsafe.As<T, ulong>(ref value));
|
||||
}
|
||||
|
||||
default:
|
||||
#if NET7_0_OR_GREATER
|
||||
throw new UnreachableException($"Enum with the size of {Unsafe.SizeOf<T>()} bytes is unexpected.");
|
||||
#else
|
||||
throw new ArgumentException($"Enum with the size of {Unsafe.SizeOf<T>()} bytes is unexpected.");
|
||||
#endif
|
||||
}
|
||||
#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user