PinnedSpan.cs 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using System.Runtime.InteropServices;
  4. namespace Ryujinx.Graphics.GAL
  5. {
  6. public unsafe struct PinnedSpan<T> : IDisposable where T : unmanaged
  7. {
  8. private void* _ptr;
  9. private int _size;
  10. private Action _disposeAction;
  11. /// <summary>
  12. /// Creates a new PinnedSpan from an existing ReadOnlySpan. The span *must* be pinned in memory.
  13. /// The data must be guaranteed to live until disposeAction is called.
  14. /// </summary>
  15. /// <param name="span">Existing span</param>
  16. /// <param name="disposeAction">Action to call on dispose</param>
  17. /// <remarks>
  18. /// If a dispose action is not provided, it is safe to assume the resource will be available until the next call.
  19. /// </remarks>
  20. public static PinnedSpan<T> UnsafeFromSpan(ReadOnlySpan<T> span, Action disposeAction = null)
  21. {
  22. return new PinnedSpan<T>(Unsafe.AsPointer(ref MemoryMarshal.GetReference(span)), span.Length, disposeAction);
  23. }
  24. /// <summary>
  25. /// Creates a new PinnedSpan from an existing unsafe region. The data must be guaranteed to live until disposeAction is called.
  26. /// </summary>
  27. /// <param name="ptr">Pointer to the region</param>
  28. /// <param name="size">The total items of T the region contains</param>
  29. /// <param name="disposeAction">Action to call on dispose</param>
  30. /// <remarks>
  31. /// If a dispose action is not provided, it is safe to assume the resource will be available until the next call.
  32. /// </remarks>
  33. public PinnedSpan(void* ptr, int size, Action disposeAction = null)
  34. {
  35. _ptr = ptr;
  36. _size = size;
  37. _disposeAction = disposeAction;
  38. }
  39. public ReadOnlySpan<T> Get()
  40. {
  41. return new ReadOnlySpan<T>(_ptr, _size * Unsafe.SizeOf<T>());
  42. }
  43. public void Dispose()
  44. {
  45. _disposeAction?.Invoke();
  46. }
  47. }
  48. }