/ src / Ryujinx.Graphics.Vulkan / PersistentFlushBuffer.cs
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  }