aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Common
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-07-12 00:07:01 -0300
committerGitHub <noreply@github.com>2020-07-12 05:07:01 +0200
commit4d02a2d2c0451b4de1f6de3bbce54c457cacebe2 (patch)
tree120fe4fb8cfa1ac1c6ef4c97d92be47e955e8c0f /Ryujinx.Common
parent38b26cf4242999fa7d8c550993ac0940cd03d55f (diff)
New NVDEC and VIC implementation (#1384)
* Initial NVDEC and VIC implementation * Update FFmpeg.AutoGen to 4.3.0 * Add nvdec dependencies for Windows * Unify some VP9 structures * Rename VP9 structure fields * Improvements to Video API * XML docs for Common.Memory * Remove now unused or redundant overloads from MemoryAccessor * NVDEC UV surface read/write scalar paths * Add FIXME comments about hacky things/stuff that will need to be fixed in the future * Cleaned up VP9 memory allocation * Remove some debug logs * Rename some VP9 structs * Remove unused struct * No need to compile Ryujinx.Graphics.Host1x with unsafe anymore * Name AsyncWorkQueue threads to make debugging easier * Make Vp9PictureInfo a ref struct * LayoutConverter no longer needs the depth argument (broken by rebase) * Pooling of VP9 buffers, plus fix a memory leak on VP9 * Really wish VS could rename projects properly... * Address feedback * Remove using * Catch OperationCanceledException * Add licensing informations * Add THIRDPARTY.md to release too Co-authored-by: Thog <me@thog.eu>
Diffstat (limited to 'Ryujinx.Common')
-rw-r--r--Ryujinx.Common/AsyncWorkQueue.cs100
-rw-r--r--Ryujinx.Common/Logging/LogClass.cs5
-rw-r--r--Ryujinx.Common/Memory/ArrayPtr.cs123
-rw-r--r--Ryujinx.Common/Memory/IArray.cs21
-rw-r--r--Ryujinx.Common/Memory/Ptr.cs68
-rw-r--r--Ryujinx.Common/Memory/StructArrayHelpers.cs518
6 files changed, 834 insertions, 1 deletions
diff --git a/Ryujinx.Common/AsyncWorkQueue.cs b/Ryujinx.Common/AsyncWorkQueue.cs
new file mode 100644
index 00000000..80f8dcfe
--- /dev/null
+++ b/Ryujinx.Common/AsyncWorkQueue.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections.Concurrent;
+using System.Threading;
+
+namespace Ryujinx.Common
+{
+ public sealed class AsyncWorkQueue<T> : IDisposable
+ {
+ private readonly Thread _workerThread;
+ private readonly CancellationTokenSource _cts;
+ private readonly Action<T> _workerAction;
+ private readonly BlockingCollection<T> _queue;
+
+ public bool IsCancellationRequested => _cts.IsCancellationRequested;
+
+ public AsyncWorkQueue(Action<T> callback, string name = null) : this(callback, name, new BlockingCollection<T>())
+ {
+ }
+
+ public AsyncWorkQueue(Action<T> callback, string name, BlockingCollection<T> collection)
+ {
+ _cts = new CancellationTokenSource();
+ _queue = collection;
+ _workerAction = callback;
+ _workerThread = new Thread(DoWork) { Name = name };
+
+ _workerThread.IsBackground = true;
+ _workerThread.Start();
+ }
+
+ private void DoWork()
+ {
+ try
+ {
+ foreach (var item in _queue.GetConsumingEnumerable(_cts.Token))
+ {
+ _workerAction(item);
+ }
+ }
+ catch (OperationCanceledException)
+ {
+ }
+ }
+
+ public void Cancel()
+ {
+ _cts.Cancel();
+ }
+
+ public void CancelAfter(int millisecondsDelay)
+ {
+ _cts.CancelAfter(millisecondsDelay);
+ }
+
+ public void CancelAfter(TimeSpan delay)
+ {
+ _cts.CancelAfter(delay);
+ }
+
+ public void Add(T workItem)
+ {
+ _queue.Add(workItem);
+ }
+
+ public void Add(T workItem, CancellationToken cancellationToken)
+ {
+ _queue.Add(workItem, cancellationToken);
+ }
+
+ public bool TryAdd(T workItem)
+ {
+ return _queue.TryAdd(workItem);
+ }
+
+ public bool TryAdd(T workItem, int millisecondsDelay)
+ {
+ return _queue.TryAdd(workItem, millisecondsDelay);
+ }
+
+ public bool TryAdd(T workItem, int millisecondsDelay, CancellationToken cancellationToken)
+ {
+ return _queue.TryAdd(workItem, millisecondsDelay, cancellationToken);
+ }
+
+ public bool TryAdd(T workItem, TimeSpan timeout)
+ {
+ return _queue.TryAdd(workItem, timeout);
+ }
+
+ public void Dispose()
+ {
+ _queue.CompleteAdding();
+ _cts.Cancel();
+ _workerThread.Join();
+
+ _queue.Dispose();
+ _cts.Dispose();
+ }
+ }
+}
diff --git a/Ryujinx.Common/Logging/LogClass.cs b/Ryujinx.Common/Logging/LogClass.cs
index aad04891..a35d01a5 100644
--- a/Ryujinx.Common/Logging/LogClass.cs
+++ b/Ryujinx.Common/Logging/LogClass.cs
@@ -9,12 +9,14 @@ namespace Ryujinx.Common.Logging
Emulation,
Gpu,
Hid,
+ Host1x,
Kernel,
KernelIpc,
KernelScheduler,
KernelSvc,
Loader,
ModLoader,
+ Nvdec,
Ptc,
Service,
ServiceAcc,
@@ -50,6 +52,7 @@ namespace Ryujinx.Common.Logging
ServiceSss,
ServiceTime,
ServiceVi,
- SurfaceFlinger
+ SurfaceFlinger,
+ Vic
}
} \ No newline at end of file
diff --git a/Ryujinx.Common/Memory/ArrayPtr.cs b/Ryujinx.Common/Memory/ArrayPtr.cs
new file mode 100644
index 00000000..7a145de2
--- /dev/null
+++ b/Ryujinx.Common/Memory/ArrayPtr.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Common.Memory
+{
+ /// <summary>
+ /// Represents an array of unmanaged resources.
+ /// </summary>
+ /// <typeparam name="T">Array element type</typeparam>
+ public unsafe struct ArrayPtr<T> : IEquatable<ArrayPtr<T>>, IArray<T> where T : unmanaged
+ {
+ private IntPtr _ptr;
+
+ /// <summary>
+ /// Null pointer.
+ /// </summary>
+ public static ArrayPtr<T> Null => new ArrayPtr<T>() { _ptr = IntPtr.Zero };
+
+ /// <summary>
+ /// True if the pointer is null, false otherwise.
+ /// </summary>
+ public bool IsNull => _ptr == IntPtr.Zero;
+
+ /// <summary>
+ /// Number of elements on the array.
+ /// </summary>
+ public int Length { get; }
+
+ /// <summary>
+ /// Gets a reference to the item at the given index.
+ /// </summary>
+ /// <remarks>
+ /// No bounds checks are performed, this allows negative indexing,
+ /// but care must be taken if the index may be out of bounds.
+ /// </remarks>
+ /// <param name="index">Index of the element</param>
+ /// <returns>Reference to the element at the given index</returns>
+ public ref T this[int index] => ref Unsafe.AsRef<T>((T*)_ptr + index);
+
+ /// <summary>
+ /// Creates a new array from a given reference.
+ /// </summary>
+ /// <remarks>
+ /// For data on the heap, proper pinning is necessary during
+ /// use. Failure to do so will result in memory corruption and crashes.
+ /// </remarks>
+ /// <param name="value">Reference of the first array element</param>
+ /// <param name="length">Number of elements on the array</param>
+ public ArrayPtr(ref T value, int length)
+ {
+ _ptr = (IntPtr)Unsafe.AsPointer(ref value);
+ Length = length;
+ }
+
+ /// <summary>
+ /// Creates a new array from a given pointer.
+ /// </summary>
+ /// <param name="ptr">Array base pointer</param>
+ /// <param name="length">Number of elements on the array</param>
+ public ArrayPtr(T* ptr, int length)
+ {
+ _ptr = (IntPtr)ptr;
+ Length = length;
+ }
+
+ /// <summary>
+ /// Creates a new array from a given pointer.
+ /// </summary>
+ /// <param name="ptr">Array base pointer</param>
+ /// <param name="length">Number of elements on the array</param>
+ public ArrayPtr(IntPtr ptr, int length)
+ {
+ _ptr = ptr;
+ Length = length;
+ }
+
+ /// <summary>
+ /// Splits the array starting at the specified position.
+ /// </summary>
+ /// <param name="start">Index where the new array should start</param>
+ /// <returns>New array starting at the specified position</returns>
+ public ArrayPtr<T> Slice(int start) => new ArrayPtr<T>(ref this[start], Length - start);
+
+ /// <summary>
+ /// Gets a span from the array.
+ /// </summary>
+ /// <returns>Span of the array</returns>
+ public Span<T> ToSpan() => Length == 0 ? Span<T>.Empty : MemoryMarshal.CreateSpan(ref this[0], Length);
+
+ /// <summary>
+ /// Gets the array base pointer.
+ /// </summary>
+ /// <returns>Base pointer</returns>
+ public T* ToPointer() => (T*)_ptr;
+
+ public override bool Equals(object obj)
+ {
+ return obj is ArrayPtr<T> other && Equals(other);
+ }
+
+ public bool Equals([AllowNull] ArrayPtr<T> other)
+ {
+ return _ptr == other._ptr && Length == other.Length;
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(_ptr, Length);
+ }
+
+ public static bool operator ==(ArrayPtr<T> left, ArrayPtr<T> right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(ArrayPtr<T> left, ArrayPtr<T> right)
+ {
+ return !(left == right);
+ }
+ }
+}
diff --git a/Ryujinx.Common/Memory/IArray.cs b/Ryujinx.Common/Memory/IArray.cs
new file mode 100644
index 00000000..8f17fade
--- /dev/null
+++ b/Ryujinx.Common/Memory/IArray.cs
@@ -0,0 +1,21 @@
+namespace Ryujinx.Common.Memory
+{
+ /// <summary>
+ /// Array interface.
+ /// </summary>
+ /// <typeparam name="T">Element type</typeparam>
+ public interface IArray<T> where T : unmanaged
+ {
+ /// <summary>
+ /// Used to index the array.
+ /// </summary>
+ /// <param name="index">Element index</param>
+ /// <returns>Element at the specified index</returns>
+ ref T this[int index] { get; }
+
+ /// <summary>
+ /// Number of elements on the array.
+ /// </summary>
+ int Length { get; }
+ }
+}
diff --git a/Ryujinx.Common/Memory/Ptr.cs b/Ryujinx.Common/Memory/Ptr.cs
new file mode 100644
index 00000000..66bcf569
--- /dev/null
+++ b/Ryujinx.Common/Memory/Ptr.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
+namespace Ryujinx.Common.Memory
+{
+ /// <summary>
+ /// Represents a pointer to an unmanaged resource.
+ /// </summary>
+ /// <typeparam name="T">Type of the unmanaged resource</typeparam>
+ public unsafe struct Ptr<T> : IEquatable<Ptr<T>> where T : unmanaged
+ {
+ private IntPtr _ptr;
+
+ /// <summary>
+ /// Null pointer.
+ /// </summary>
+ public static Ptr<T> Null => new Ptr<T>() { _ptr = IntPtr.Zero };
+
+ /// <summary>
+ /// True if the pointer is null, false otherwise.
+ /// </summary>
+ public bool IsNull => _ptr == IntPtr.Zero;
+
+ /// <summary>
+ /// Gets a reference to the value.
+ /// </summary>
+ public ref T Value => ref Unsafe.AsRef<T>((void*)_ptr);
+
+ /// <summary>
+ /// Creates a new pointer to an unmanaged resource.
+ /// </summary>
+ /// <remarks>
+ /// For data on the heap, proper pinning is necessary during
+ /// use. Failure to do so will result in memory corruption and crashes.
+ /// </remarks>
+ /// <param name="value">Reference to the unmanaged resource</param>
+ public Ptr(ref T value)
+ {
+ _ptr = (IntPtr)Unsafe.AsPointer(ref value);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is Ptr<T> other && Equals(other);
+ }
+
+ public bool Equals([AllowNull] Ptr<T> other)
+ {
+ return _ptr == other._ptr;
+ }
+
+ public override int GetHashCode()
+ {
+ return _ptr.GetHashCode();
+ }
+
+ public static bool operator ==(Ptr<T> left, Ptr<T> right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Ptr<T> left, Ptr<T> right)
+ {
+ return !(left == right);
+ }
+ }
+}
diff --git a/Ryujinx.Common/Memory/StructArrayHelpers.cs b/Ryujinx.Common/Memory/StructArrayHelpers.cs
new file mode 100644
index 00000000..eb8d3ce1
--- /dev/null
+++ b/Ryujinx.Common/Memory/StructArrayHelpers.cs
@@ -0,0 +1,518 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Common.Memory
+{
+ public struct Array1<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ public int Length => 1;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 1);
+ }
+ public struct Array2<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array1<T> _other;
+ public int Length => 2;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 2);
+ }
+ public struct Array3<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array2<T> _other;
+ public int Length => 3;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 3);
+ }
+ public struct Array4<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array3<T> _other;
+ public int Length => 4;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 4);
+ }
+ public struct Array5<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array4<T> _other;
+ public int Length => 5;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 5);
+ }
+ public struct Array6<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array5<T> _other;
+ public int Length => 6;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 6);
+ }
+ public struct Array7<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array6<T> _other;
+ public int Length => 7;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 7);
+ }
+ public struct Array8<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array7<T> _other;
+ public int Length => 8;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 8);
+ }
+ public struct Array9<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array8<T> _other;
+ public int Length => 9;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 9);
+ }
+ public struct Array10<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array9<T> _other;
+ public int Length => 10;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 10);
+ }
+ public struct Array11<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array10<T> _other;
+ public int Length => 11;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 11);
+ }
+ public struct Array12<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array11<T> _other;
+ public int Length => 12;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 12);
+ }
+ public struct Array13<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array12<T> _other;
+ public int Length => 13;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 13);
+ }
+ public struct Array14<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array13<T> _other;
+ public int Length => 14;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 14);
+ }
+ public struct Array15<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array14<T> _other;
+ public int Length => 15;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 15);
+ }
+ public struct Array16<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array15<T> _other;
+ public int Length => 16;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 16);
+ }
+ public struct Array17<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array16<T> _other;
+ public int Length => 17;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 17);
+ }
+ public struct Array18<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array17<T> _other;
+ public int Length => 18;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 18);
+ }
+ public struct Array19<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array18<T> _other;
+ public int Length => 19;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 19);
+ }
+ public struct Array20<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array19<T> _other;
+ public int Length => 20;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 20);
+ }
+ public struct Array21<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array20<T> _other;
+ public int Length => 21;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 21);
+ }
+ public struct Array22<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array21<T> _other;
+ public int Length => 22;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 22);
+ }
+ public struct Array23<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array22<T> _other;
+ public int Length => 23;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 23);
+ }
+ public struct Array24<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array23<T> _other;
+ public int Length => 24;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 24);
+ }
+ public struct Array25<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array24<T> _other;
+ public int Length => 25;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 25);
+ }
+ public struct Array26<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array25<T> _other;
+ public int Length => 26;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 26);
+ }
+ public struct Array27<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array26<T> _other;
+ public int Length => 27;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 27);
+ }
+ public struct Array28<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array27<T> _other;
+ public int Length => 28;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 28);
+ }
+ public struct Array29<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array28<T> _other;
+ public int Length => 29;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 29);
+ }
+ public struct Array30<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array29<T> _other;
+ public int Length => 30;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 30);
+ }
+ public struct Array31<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array30<T> _other;
+ public int Length => 31;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 31);
+ }
+ public struct Array32<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array31<T> _other;
+ public int Length => 32;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 32);
+ }
+ public struct Array33<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array32<T> _other;
+ public int Length => 33;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 33);
+ }
+ public struct Array34<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array33<T> _other;
+ public int Length => 34;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 34);
+ }
+ public struct Array35<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array34<T> _other;
+ public int Length => 35;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 35);
+ }
+ public struct Array36<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array35<T> _other;
+ public int Length => 36;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 36);
+ }
+ public struct Array37<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array36<T> _other;
+ public int Length => 37;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 37);
+ }
+ public struct Array38<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array37<T> _other;
+ public int Length => 38;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 38);
+ }
+ public struct Array39<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array38<T> _other;
+ public int Length => 39;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 39);
+ }
+ public struct Array40<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array39<T> _other;
+ public int Length => 40;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 40);
+ }
+ public struct Array41<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array40<T> _other;
+ public int Length => 41;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 41);
+ }
+ public struct Array42<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array41<T> _other;
+ public int Length => 42;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 42);
+ }
+ public struct Array43<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array42<T> _other;
+ public int Length => 43;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 43);
+ }
+ public struct Array44<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array43<T> _other;
+ public int Length => 44;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 44);
+ }
+ public struct Array45<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array44<T> _other;
+ public int Length => 45;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 45);
+ }
+ public struct Array46<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array45<T> _other;
+ public int Length => 46;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 46);
+ }
+ public struct Array47<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array46<T> _other;
+ public int Length => 47;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 47);
+ }
+ public struct Array48<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array47<T> _other;
+ public int Length => 48;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 48);
+ }
+ public struct Array49<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array48<T> _other;
+ public int Length => 49;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 49);
+ }
+ public struct Array50<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array49<T> _other;
+ public int Length => 50;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 50);
+ }
+ public struct Array51<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array50<T> _other;
+ public int Length => 51;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 51);
+ }
+ public struct Array52<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array51<T> _other;
+ public int Length => 52;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 52);
+ }
+ public struct Array53<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array52<T> _other;
+ public int Length => 53;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 53);
+ }
+ public struct Array54<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array53<T> _other;
+ public int Length => 54;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 54);
+ }
+ public struct Array55<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array54<T> _other;
+ public int Length => 55;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 55);
+ }
+ public struct Array56<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array55<T> _other;
+ public int Length => 56;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 56);
+ }
+ public struct Array57<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array56<T> _other;
+ public int Length => 57;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 57);
+ }
+ public struct Array58<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array57<T> _other;
+ public int Length => 58;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 58);
+ }
+ public struct Array59<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array58<T> _other;
+ public int Length => 59;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 59);
+ }
+ public struct Array60<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array59<T> _other;
+ public int Length => 60;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 60);
+ }
+ public struct Array61<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array60<T> _other;
+ public int Length => 61;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 61);
+ }
+ public struct Array62<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array61<T> _other;
+ public int Length => 62;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 62);
+ }
+ public struct Array63<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array62<T> _other;
+ public int Length => 63;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 63);
+ }
+ public struct Array64<T> : IArray<T> where T : unmanaged
+ {
+ T _e0;
+ Array63<T> _other;
+ public int Length => 64;
+ public ref T this[int index] => ref ToSpan()[index];
+ public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 64);
+ }
+
+}