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
This commit is contained in:
parent
947e14d3be
commit
d1ab9fb42c
12 changed files with 1009 additions and 599 deletions
59
Ryujinx.Common/Utilities/Buffers.cs
Normal file
59
Ryujinx.Common/Utilities/Buffers.cs
Normal file
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
61
Ryujinx.Common/Utilities/SpanHelpers.cs
Normal file
61
Ryujinx.Common/Utilities/SpanHelpers.cs
Normal file
|
@ -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>());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue