ThreadedTexture.cs
  1  using Ryujinx.Common.Memory;
  2  using Ryujinx.Graphics.GAL.Multithreading.Commands.Texture;
  3  using Ryujinx.Graphics.GAL.Multithreading.Model;
  4  
  5  namespace Ryujinx.Graphics.GAL.Multithreading.Resources
  6  {
  7      /// <summary>
  8      /// Threaded representation of a texture.
  9      /// </summary>
 10      class ThreadedTexture : ITexture
 11      {
 12          private readonly ThreadedRenderer _renderer;
 13          private readonly TextureCreateInfo _info;
 14          public ITexture Base;
 15  
 16          public int Width => _info.Width;
 17  
 18          public int Height => _info.Height;
 19  
 20          public ThreadedTexture(ThreadedRenderer renderer, TextureCreateInfo info)
 21          {
 22              _renderer = renderer;
 23              _info = info;
 24          }
 25  
 26          private TableRef<T> Ref<T>(T reference)
 27          {
 28              return new TableRef<T>(_renderer, reference);
 29          }
 30  
 31          public void CopyTo(ITexture destination, int firstLayer, int firstLevel)
 32          {
 33              _renderer.New<TextureCopyToCommand>().Set(Ref(this), Ref((ThreadedTexture)destination), firstLayer, firstLevel);
 34              _renderer.QueueCommand();
 35          }
 36  
 37          public void CopyTo(ITexture destination, int srcLayer, int dstLayer, int srcLevel, int dstLevel)
 38          {
 39              _renderer.New<TextureCopyToSliceCommand>().Set(Ref(this), Ref((ThreadedTexture)destination), srcLayer, dstLayer, srcLevel, dstLevel);
 40              _renderer.QueueCommand();
 41          }
 42  
 43          public void CopyTo(ITexture destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter)
 44          {
 45              ThreadedTexture dest = (ThreadedTexture)destination;
 46  
 47              if (_renderer.IsGpuThread())
 48              {
 49                  _renderer.New<TextureCopyToScaledCommand>().Set(Ref(this), Ref(dest), srcRegion, dstRegion, linearFilter);
 50                  _renderer.QueueCommand();
 51              }
 52              else
 53              {
 54                  // Scaled copy can happen on another thread for a res scale flush.
 55                  ThreadedHelpers.SpinUntilNonNull(ref Base);
 56                  ThreadedHelpers.SpinUntilNonNull(ref dest.Base);
 57  
 58                  Base.CopyTo(dest.Base, srcRegion, dstRegion, linearFilter);
 59              }
 60          }
 61  
 62          public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
 63          {
 64              ThreadedTexture newTex = new(_renderer, info);
 65              _renderer.New<TextureCreateViewCommand>().Set(Ref(this), Ref(newTex), info, firstLayer, firstLevel);
 66              _renderer.QueueCommand();
 67  
 68              return newTex;
 69          }
 70  
 71          public PinnedSpan<byte> GetData()
 72          {
 73              if (_renderer.IsGpuThread())
 74              {
 75                  ResultBox<PinnedSpan<byte>> box = new();
 76                  _renderer.New<TextureGetDataCommand>().Set(Ref(this), Ref(box));
 77                  _renderer.InvokeCommand();
 78  
 79                  return box.Result;
 80              }
 81              else
 82              {
 83                  ThreadedHelpers.SpinUntilNonNull(ref Base);
 84  
 85                  return Base.GetData();
 86              }
 87          }
 88  
 89          public PinnedSpan<byte> GetData(int layer, int level)
 90          {
 91              if (_renderer.IsGpuThread())
 92              {
 93                  ResultBox<PinnedSpan<byte>> box = new();
 94                  _renderer.New<TextureGetDataSliceCommand>().Set(Ref(this), Ref(box), layer, level);
 95                  _renderer.InvokeCommand();
 96  
 97                  return box.Result;
 98              }
 99              else
100              {
101                  ThreadedHelpers.SpinUntilNonNull(ref Base);
102  
103                  return Base.GetData(layer, level);
104              }
105          }
106  
107          public void CopyTo(BufferRange range, int layer, int level, int stride)
108          {
109              _renderer.New<TextureCopyToBufferCommand>().Set(Ref(this), range, layer, level, stride);
110              _renderer.QueueCommand();
111          }
112  
113          /// <inheritdoc/>
114          public void SetData(MemoryOwner<byte> data)
115          {
116              _renderer.New<TextureSetDataCommand>().Set(Ref(this), Ref(data));
117              _renderer.QueueCommand();
118          }
119  
120          /// <inheritdoc/>
121          public void SetData(MemoryOwner<byte> data, int layer, int level)
122          {
123              _renderer.New<TextureSetDataSliceCommand>().Set(Ref(this), Ref(data), layer, level);
124              _renderer.QueueCommand();
125          }
126  
127          /// <inheritdoc/>
128          public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
129          {
130              _renderer.New<TextureSetDataSliceRegionCommand>().Set(Ref(this), Ref(data), layer, level, region);
131              _renderer.QueueCommand();
132          }
133  
134          public void SetStorage(BufferRange buffer)
135          {
136              _renderer.New<TextureSetStorageCommand>().Set(Ref(this), buffer);
137              _renderer.QueueCommand();
138          }
139  
140          public void Release()
141          {
142              _renderer.New<TextureReleaseCommand>().Set(Ref(this));
143              _renderer.QueueCommand();
144          }
145      }
146  }