diff options
Diffstat (limited to 'Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs')
-rw-r--r-- | Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs b/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs new file mode 100644 index 00000000..634d32fa --- /dev/null +++ b/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs @@ -0,0 +1,116 @@ +using Ryujinx.Graphics.GAL.Multithreading.Commands.Texture; +using Ryujinx.Graphics.GAL.Multithreading.Model; +using System; + +namespace Ryujinx.Graphics.GAL.Multithreading.Resources +{ + /// <summary> + /// Threaded representation of a texture. + /// </summary> + class ThreadedTexture : ITexture + { + private ThreadedRenderer _renderer; + private TextureCreateInfo _info; + public ITexture Base; + + public int Width => _info.Width; + + public int Height => _info.Height; + + public float ScaleFactor { get; } + + public ThreadedTexture(ThreadedRenderer renderer, TextureCreateInfo info, float scale) + { + _renderer = renderer; + _info = info; + ScaleFactor = scale; + } + + private TableRef<T> Ref<T>(T reference) + { + return new TableRef<T>(_renderer, reference); + } + + public void CopyTo(ITexture destination, int firstLayer, int firstLevel) + { + _renderer.New<TextureCopyToCommand>().Set(Ref(this), Ref((ThreadedTexture)destination), firstLayer, firstLevel); + _renderer.QueueCommand(); + } + + public void CopyTo(ITexture destination, int srcLayer, int dstLayer, int srcLevel, int dstLevel) + { + _renderer.New<TextureCopyToSliceCommand>().Set(Ref(this), Ref((ThreadedTexture)destination), srcLayer, dstLayer, srcLevel, dstLevel); + _renderer.QueueCommand(); + } + + public void CopyTo(ITexture destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter) + { + ThreadedTexture dest = (ThreadedTexture)destination; + + if (_renderer.IsGpuThread()) + { + _renderer.New<TextureCopyToScaledCommand>().Set(Ref(this), Ref(dest), srcRegion, dstRegion, linearFilter); + _renderer.QueueCommand(); + } + else + { + // Scaled copy can happen on another thread for a res scale flush. + ThreadedHelpers.SpinUntilNonNull(ref Base); + ThreadedHelpers.SpinUntilNonNull(ref dest.Base); + + Base.CopyTo(dest.Base, srcRegion, dstRegion, linearFilter); + } + } + + public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel) + { + ThreadedTexture newTex = new ThreadedTexture(_renderer, info, ScaleFactor); + _renderer.New<TextureCreateViewCommand>().Set(Ref(this), Ref(newTex), info, firstLayer, firstLevel); + _renderer.QueueCommand(); + + return newTex; + } + + public ReadOnlySpan<byte> GetData() + { + if (_renderer.IsGpuThread()) + { + ResultBox<PinnedSpan<byte>> box = new ResultBox<PinnedSpan<byte>>(); + _renderer.New<TextureGetDataCommand>().Set(Ref(this), Ref(box)); + _renderer.InvokeCommand(); + + return box.Result.Get(); + } + else + { + ThreadedHelpers.SpinUntilNonNull(ref Base); + + return Base.GetData(); + } + } + + public void SetData(ReadOnlySpan<byte> data) + { + _renderer.New<TextureSetDataCommand>().Set(Ref(this), Ref(data.ToArray())); + _renderer.QueueCommand(); + } + + public void SetData(ReadOnlySpan<byte> data, int layer, int level) + { + _renderer.New<TextureSetDataSliceCommand>().Set(Ref(this), Ref(data.ToArray()), layer, level); + _renderer.QueueCommand(); + } + + public void SetStorage(BufferRange buffer) + { + _renderer.New<TextureSetStorageCommand>().Set(Ref(this), buffer); + _renderer.QueueCommand(); + } + + public void Release() + { + _renderer.New<TextureReleaseCommand>().Set(Ref(this)); + _renderer.QueueCommand(); + } + } +} |