aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Common/Utilities
diff options
context:
space:
mode:
authorAlex Barney <thealexbarney@gmail.com>2019-12-26 23:09:49 -0700
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commitd1ab9fb42c2fd9f018d4410ca619cd66294eafc9 (patch)
treedcac71560b921f29d73ee6e21f235528184d9f84 /Ryujinx.Common/Utilities
parent947e14d3be0f7c5e4b6f77df204ec675b8e9e719 (diff)
ASTC optimizations (#845)
* ASTC optimizations * Move code to Ryujinx.Common * Support 3D textures * Address feedback * Remove ASTC logging * Use stackalloc instead of a Buffer20 struct * Code style and cleanup * Respond to feedback * Rearrange public/private property ordering
Diffstat (limited to 'Ryujinx.Common/Utilities')
-rw-r--r--Ryujinx.Common/Utilities/Buffers.cs59
-rw-r--r--Ryujinx.Common/Utilities/SpanHelpers.cs61
2 files changed, 120 insertions, 0 deletions
diff --git a/Ryujinx.Common/Utilities/Buffers.cs b/Ryujinx.Common/Utilities/Buffers.cs
new file mode 100644
index 00000000..d614bfc4
--- /dev/null
+++ b/Ryujinx.Common/Utilities/Buffers.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Common.Utilities
+{
+ [DebuggerDisplay("{ToString()}")]
+ [StructLayout(LayoutKind.Sequential, Size = 16)]
+ public struct Buffer16
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy0;
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy1;
+
+ public byte this[int i]
+ {
+ get => Bytes[i];
+ set => Bytes[i] = value;
+ }
+
+ public Span<byte> Bytes => SpanHelpers.AsByteSpan(ref this);
+
+ // Prevent a defensive copy by changing the read-only in reference to a reference with Unsafe.AsRef()
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator Span<byte>(in Buffer16 value)
+ {
+ return SpanHelpers.AsByteSpan(ref Unsafe.AsRef(in value));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator ReadOnlySpan<byte>(in Buffer16 value)
+ {
+ return SpanHelpers.AsReadOnlyByteSpan(ref Unsafe.AsRef(in value));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ref T As<T>() where T : unmanaged
+ {
+ if (Unsafe.SizeOf<T>() > (uint)Unsafe.SizeOf<Buffer16>())
+ {
+ throw new ArgumentException();
+ }
+
+ return ref MemoryMarshal.GetReference(AsSpan<T>());
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Span<T> AsSpan<T>() where T : unmanaged
+ {
+ return SpanHelpers.AsSpan<Buffer16, T>(ref this);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly ReadOnlySpan<T> AsReadOnlySpan<T>() where T : unmanaged
+ {
+ return SpanHelpers.AsReadOnlySpan<Buffer16, T>(ref Unsafe.AsRef(in this));
+ }
+ }
+}
diff --git a/Ryujinx.Common/Utilities/SpanHelpers.cs b/Ryujinx.Common/Utilities/SpanHelpers.cs
new file mode 100644
index 00000000..84c13023
--- /dev/null
+++ b/Ryujinx.Common/Utilities/SpanHelpers.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Common.Utilities
+{
+ public static class SpanHelpers
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<T> CreateSpan<T>(ref T reference, int length)
+ {
+ return MemoryMarshal.CreateSpan(ref reference, length);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<T> AsSpan<T>(ref T reference) where T : unmanaged
+ {
+ return CreateSpan(ref reference, 1);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<TSpan> AsSpan<TStruct, TSpan>(ref TStruct reference)
+ where TStruct : unmanaged where TSpan : unmanaged
+ {
+ return CreateSpan(ref Unsafe.As<TStruct, TSpan>(ref reference),
+ Unsafe.SizeOf<TStruct>() / Unsafe.SizeOf<TSpan>());
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<byte> AsByteSpan<T>(ref T reference) where T : unmanaged
+ {
+ return CreateSpan(ref Unsafe.As<T, byte>(ref reference), Unsafe.SizeOf<T>());
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ReadOnlySpan<T> CreateReadOnlySpan<T>(ref T reference, int length)
+ {
+ return MemoryMarshal.CreateReadOnlySpan(ref reference, length);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ReadOnlySpan<T> AsReadOnlySpan<T>(ref T reference) where T : unmanaged
+ {
+ return CreateReadOnlySpan(ref reference, 1);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ReadOnlySpan<TSpan> AsReadOnlySpan<TStruct, TSpan>(ref TStruct reference)
+ where TStruct : unmanaged where TSpan : unmanaged
+ {
+ return CreateReadOnlySpan(ref Unsafe.As<TStruct, TSpan>(ref reference),
+ Unsafe.SizeOf<TStruct>() / Unsafe.SizeOf<TSpan>());
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ReadOnlySpan<byte> AsReadOnlyByteSpan<T>(ref T reference) where T : unmanaged
+ {
+ return CreateReadOnlySpan(ref Unsafe.As<T, byte>(ref reference), Unsafe.SizeOf<T>());
+ }
+ }
+}