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 }