using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace Ryujinx.Graphics.GAL { public unsafe struct PinnedSpan : IDisposable where T : unmanaged { private void* _ptr; private int _size; private Action _disposeAction; /// /// Creates a new PinnedSpan from an existing ReadOnlySpan. The span *must* be pinned in memory. /// The data must be guaranteed to live until disposeAction is called. /// /// Existing span /// Action to call on dispose /// /// If a dispose action is not provided, it is safe to assume the resource will be available until the next call. /// public static PinnedSpan UnsafeFromSpan(ReadOnlySpan span, Action disposeAction = null) { return new PinnedSpan(Unsafe.AsPointer(ref MemoryMarshal.GetReference(span)), span.Length, disposeAction); } /// /// Creates a new PinnedSpan from an existing unsafe region. The data must be guaranteed to live until disposeAction is called. /// /// Pointer to the region /// The total items of T the region contains /// Action to call on dispose /// /// If a dispose action is not provided, it is safe to assume the resource will be available until the next call. /// public PinnedSpan(void* ptr, int size, Action disposeAction = null) { _ptr = ptr; _size = size; _disposeAction = disposeAction; } public ReadOnlySpan Get() { return new ReadOnlySpan(_ptr, _size * Unsafe.SizeOf()); } public void Dispose() { _disposeAction?.Invoke(); } } }