PersistentFlushBuffer.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. using Ryujinx.Graphics.GAL;
  2. using SharpMetal.Metal;
  3. using System;
  4. using System.Runtime.Versioning;
  5. namespace Ryujinx.Graphics.Metal
  6. {
  7. [SupportedOSPlatform("macos")]
  8. internal class PersistentFlushBuffer : IDisposable
  9. {
  10. private readonly MetalRenderer _renderer;
  11. private BufferHolder _flushStorage;
  12. public PersistentFlushBuffer(MetalRenderer renderer)
  13. {
  14. _renderer = renderer;
  15. }
  16. private BufferHolder ResizeIfNeeded(int size)
  17. {
  18. BufferHolder flushStorage = _flushStorage;
  19. if (flushStorage == null || size > _flushStorage.Size)
  20. {
  21. flushStorage?.Dispose();
  22. flushStorage = _renderer.BufferManager.Create(size);
  23. _flushStorage = flushStorage;
  24. }
  25. return flushStorage;
  26. }
  27. public Span<byte> GetBufferData(CommandBufferPool cbp, BufferHolder buffer, int offset, int size)
  28. {
  29. BufferHolder flushStorage = ResizeIfNeeded(size);
  30. Auto<DisposableBuffer> srcBuffer;
  31. using (CommandBufferScoped cbs = cbp.Rent())
  32. {
  33. srcBuffer = buffer.GetBuffer();
  34. Auto<DisposableBuffer> dstBuffer = flushStorage.GetBuffer();
  35. if (srcBuffer.TryIncrementReferenceCount())
  36. {
  37. BufferHolder.Copy(cbs, srcBuffer, dstBuffer, offset, 0, size, registerSrcUsage: false);
  38. }
  39. else
  40. {
  41. // Source buffer is no longer alive, don't copy anything to flush storage.
  42. srcBuffer = null;
  43. }
  44. }
  45. flushStorage.WaitForFences();
  46. srcBuffer?.DecrementReferenceCount();
  47. return flushStorage.GetDataStorage(0, size);
  48. }
  49. public Span<byte> GetTextureData(CommandBufferPool cbp, Texture view, int size)
  50. {
  51. TextureCreateInfo info = view.Info;
  52. BufferHolder flushStorage = ResizeIfNeeded(size);
  53. using (CommandBufferScoped cbs = cbp.Rent())
  54. {
  55. MTLBuffer buffer = flushStorage.GetBuffer().Get(cbs).Value;
  56. MTLTexture image = view.GetHandle();
  57. view.CopyFromOrToBuffer(cbs, buffer, image, size, true, 0, 0, info.GetLayers(), info.Levels, singleSlice: false);
  58. }
  59. flushStorage.WaitForFences();
  60. return flushStorage.GetDataStorage(0, size);
  61. }
  62. public Span<byte> GetTextureData(CommandBufferPool cbp, Texture view, int size, int layer, int level)
  63. {
  64. BufferHolder flushStorage = ResizeIfNeeded(size);
  65. using (CommandBufferScoped cbs = cbp.Rent())
  66. {
  67. MTLBuffer buffer = flushStorage.GetBuffer().Get(cbs).Value;
  68. MTLTexture image = view.GetHandle();
  69. view.CopyFromOrToBuffer(cbs, buffer, image, size, true, layer, level, 1, 1, singleSlice: true);
  70. }
  71. flushStorage.WaitForFences();
  72. return flushStorage.GetDataStorage(0, size);
  73. }
  74. public void Dispose()
  75. {
  76. _flushStorage.Dispose();
  77. }
  78. }
  79. }