PersistentFlushBuffer.cs
1 using Ryujinx.Graphics.GAL; 2 using System; 3 4 namespace Ryujinx.Graphics.Vulkan 5 { 6 internal class PersistentFlushBuffer : IDisposable 7 { 8 private readonly VulkanRenderer _gd; 9 10 private BufferHolder _flushStorage; 11 12 public PersistentFlushBuffer(VulkanRenderer gd) 13 { 14 _gd = gd; 15 } 16 17 private BufferHolder ResizeIfNeeded(int size) 18 { 19 var flushStorage = _flushStorage; 20 21 if (flushStorage == null || size > _flushStorage.Size) 22 { 23 flushStorage?.Dispose(); 24 25 flushStorage = _gd.BufferManager.Create(_gd, size); 26 _flushStorage = flushStorage; 27 } 28 29 return flushStorage; 30 } 31 32 public Span<byte> GetBufferData(CommandBufferPool cbp, BufferHolder buffer, int offset, int size) 33 { 34 var flushStorage = ResizeIfNeeded(size); 35 Auto<DisposableBuffer> srcBuffer; 36 37 using (var cbs = cbp.Rent()) 38 { 39 srcBuffer = buffer.GetBuffer(cbs.CommandBuffer); 40 var dstBuffer = flushStorage.GetBuffer(cbs.CommandBuffer); 41 42 if (srcBuffer.TryIncrementReferenceCount()) 43 { 44 BufferHolder.Copy(_gd, cbs, srcBuffer, dstBuffer, offset, 0, size, registerSrcUsage: false); 45 } 46 else 47 { 48 // Source buffer is no longer alive, don't copy anything to flush storage. 49 srcBuffer = null; 50 } 51 } 52 53 flushStorage.WaitForFences(); 54 srcBuffer?.DecrementReferenceCount(); 55 return flushStorage.GetDataStorage(0, size); 56 } 57 58 public Span<byte> GetTextureData(CommandBufferPool cbp, TextureView view, int size) 59 { 60 TextureCreateInfo info = view.Info; 61 62 var flushStorage = ResizeIfNeeded(size); 63 64 using (var cbs = cbp.Rent()) 65 { 66 var buffer = flushStorage.GetBuffer(cbs.CommandBuffer).Get(cbs).Value; 67 var image = view.GetImage().Get(cbs).Value; 68 69 view.CopyFromOrToBuffer(cbs.CommandBuffer, buffer, image, size, true, 0, 0, info.GetLayers(), info.Levels, singleSlice: false); 70 } 71 72 flushStorage.WaitForFences(); 73 return flushStorage.GetDataStorage(0, size); 74 } 75 76 public Span<byte> GetTextureData(CommandBufferPool cbp, TextureView view, int size, int layer, int level) 77 { 78 var flushStorage = ResizeIfNeeded(size); 79 80 using (var cbs = cbp.Rent()) 81 { 82 var buffer = flushStorage.GetBuffer(cbs.CommandBuffer).Get(cbs).Value; 83 var image = view.GetImage().Get(cbs).Value; 84 85 view.CopyFromOrToBuffer(cbs.CommandBuffer, buffer, image, size, true, layer, level, 1, 1, singleSlice: true); 86 } 87 88 flushStorage.WaitForFences(); 89 return flushStorage.GetDataStorage(0, size); 90 } 91 92 public void Dispose() 93 { 94 _flushStorage.Dispose(); 95 } 96 } 97 }