From 092af4585c6fd960ccb89d541909ca38beb265b1 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Fri, 12 Jan 2024 17:56:48 +0000 Subject: [PATCH] Port of texture memory pool PR --- src/Ryujinx.Graphics.GAL/ITexture.cs | 27 +++++- .../Commands/Texture/TextureSetDataCommand.cs | 7 +- .../Texture/TextureSetDataSliceCommand.cs | 7 +- .../TextureSetDataSliceRegionCommand.cs | 7 +- .../Resources/ThreadedTexture.cs | 13 +-- .../Engine/Dma/DmaClass.cs | 3 +- .../InlineToMemory/InlineToMemoryClass.cs | 6 +- src/Ryujinx.Graphics.Gpu/Image/Texture.cs | 86 ++++++++++++------- .../Image/TextureGroup.cs | 3 +- .../Image/TextureBuffer.cs | 13 ++- .../Image/TextureStorage.cs | 6 +- .../Image/TextureView.cs | 24 ++++-- .../Astc/AstcDecoder.cs | 10 +-- src/Ryujinx.Graphics.Texture/BCnDecoder.cs | 44 +++++----- src/Ryujinx.Graphics.Texture/BCnEncoder.cs | 10 ++- src/Ryujinx.Graphics.Texture/ETC2Decoder.cs | 20 +++-- .../LayoutConverter.cs | 15 ++-- .../PixelConverter.cs | 34 ++++---- src/Ryujinx.Graphics.Vulkan/TextureBuffer.cs | 12 ++- src/Ryujinx.Graphics.Vulkan/TextureView.cs | 19 ++-- 20 files changed, 228 insertions(+), 138 deletions(-) diff --git a/src/Ryujinx.Graphics.GAL/ITexture.cs b/src/Ryujinx.Graphics.GAL/ITexture.cs index 5a4623a66..ea8d68649 100644 --- a/src/Ryujinx.Graphics.GAL/ITexture.cs +++ b/src/Ryujinx.Graphics.GAL/ITexture.cs @@ -1,4 +1,5 @@ using Ryujinx.Common.Memory; +using System.Buffers; namespace Ryujinx.Graphics.GAL { @@ -17,9 +18,29 @@ namespace Ryujinx.Graphics.GAL PinnedSpan GetData(); PinnedSpan GetData(int layer, int level); - void SetData(SpanOrArray data); - void SetData(SpanOrArray data, int layer, int level); - void SetData(SpanOrArray data, int layer, int level, Rectangle region); + /// + /// Sets the texture data. The data passed as a will be disposed when the operation completes. + /// + /// Texture data bytes + void SetData(IMemoryOwner data); + + /// + /// Sets the texture data. The data passed as a will be disposed when the operation completes. + /// + /// Texture data bytes + /// Target layer + /// Target level + void SetData(IMemoryOwner data, int layer, int level); + + /// + /// Sets the texture data. The data passed as a will be disposed when the operation completes. + /// + /// Texture data bytes + /// Target layer + /// Target level + /// Target sub-region of the texture to update + void SetData(IMemoryOwner data, int layer, int level, Rectangle region); + void SetStorage(BufferRange buffer); void Release(); } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataCommand.cs index 36feeeba7..a7a8846e4 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataCommand.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataCommand.cs @@ -1,6 +1,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Model; using Ryujinx.Graphics.GAL.Multithreading.Resources; using System; +using System.Buffers; namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture { @@ -8,9 +9,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture { public readonly CommandType CommandType => CommandType.TextureSetData; private TableRef _texture; - private TableRef _data; + private TableRef> _data; - public void Set(TableRef texture, TableRef data) + public void Set(TableRef texture, TableRef> data) { _texture = texture; _data = data; @@ -19,7 +20,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture public static void Run(ref TextureSetDataCommand command, ThreadedRenderer threaded, IRenderer renderer) { ThreadedTexture texture = command._texture.Get(threaded); - texture.Base.SetData(new ReadOnlySpan(command._data.Get(threaded))); + texture.Base.SetData(command._data.Get(threaded)); } } } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceCommand.cs index c50bfe089..bb24ee140 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceCommand.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceCommand.cs @@ -1,6 +1,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Model; using Ryujinx.Graphics.GAL.Multithreading.Resources; using System; +using System.Buffers; namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture { @@ -8,11 +9,11 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture { public readonly CommandType CommandType => CommandType.TextureSetDataSlice; private TableRef _texture; - private TableRef _data; + private TableRef> _data; private int _layer; private int _level; - public void Set(TableRef texture, TableRef data, int layer, int level) + public void Set(TableRef texture, TableRef> data, int layer, int level) { _texture = texture; _data = data; @@ -23,7 +24,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture public static void Run(ref TextureSetDataSliceCommand command, ThreadedRenderer threaded, IRenderer renderer) { ThreadedTexture texture = command._texture.Get(threaded); - texture.Base.SetData(new ReadOnlySpan(command._data.Get(threaded)), command._layer, command._level); + texture.Base.SetData(command._data.Get(threaded), command._layer, command._level); } } } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceRegionCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceRegionCommand.cs index 4c80d9bc3..93631267b 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceRegionCommand.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureSetDataSliceRegionCommand.cs @@ -1,6 +1,7 @@ using Ryujinx.Graphics.GAL.Multithreading.Model; using Ryujinx.Graphics.GAL.Multithreading.Resources; using System; +using System.Buffers; namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture { @@ -8,12 +9,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture { public readonly CommandType CommandType => CommandType.TextureSetDataSliceRegion; private TableRef _texture; - private TableRef _data; + private TableRef> _data; private int _layer; private int _level; private Rectangle _region; - public void Set(TableRef texture, TableRef data, int layer, int level, Rectangle region) + public void Set(TableRef texture, TableRef> data, int layer, int level, Rectangle region) { _texture = texture; _data = data; @@ -25,7 +26,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture public static void Run(ref TextureSetDataSliceRegionCommand command, ThreadedRenderer threaded, IRenderer renderer) { ThreadedTexture texture = command._texture.Get(threaded); - texture.Base.SetData(new ReadOnlySpan(command._data.Get(threaded)), command._layer, command._level, command._region); + texture.Base.SetData(command._data.Get(threaded), command._layer, command._level, command._region); } } } diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs index 9ad9e6454..b674930e1 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs @@ -1,6 +1,7 @@ using Ryujinx.Common.Memory; using Ryujinx.Graphics.GAL.Multithreading.Commands.Texture; using Ryujinx.Graphics.GAL.Multithreading.Model; +using System.Buffers; namespace Ryujinx.Graphics.GAL.Multithreading.Resources { @@ -110,21 +111,21 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources _renderer.QueueCommand(); } - public void SetData(SpanOrArray data) + public void SetData(IMemoryOwner data) { - _renderer.New().Set(Ref(this), Ref(data.ToArray())); + _renderer.New().Set(Ref(this), Ref(data)); _renderer.QueueCommand(); } - public void SetData(SpanOrArray data, int layer, int level) + public void SetData(IMemoryOwner data, int layer, int level) { - _renderer.New().Set(Ref(this), Ref(data.ToArray()), layer, level); + _renderer.New().Set(Ref(this), Ref(data), layer, level); _renderer.QueueCommand(); } - public void SetData(SpanOrArray data, int layer, int level, Rectangle region) + public void SetData(IMemoryOwner data, int layer, int level, Rectangle region) { - _renderer.New().Set(Ref(this), Ref(data.ToArray()), layer, level, region); + _renderer.New().Set(Ref(this), Ref(data), layer, level, region); _renderer.QueueCommand(); } diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs b/src/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs index 6dae829ff..0fc10ff49 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs @@ -4,6 +4,7 @@ using Ryujinx.Graphics.Gpu.Engine.Threed; using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Texture; using System; +using System.Buffers; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -300,7 +301,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma if (target != null) { - byte[] data; + IMemoryOwner data; if (srcLinear) { data = LayoutConverter.ConvertLinearStridedToLinear( diff --git a/src/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs b/src/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs index 37d74fdd3..576ef3266 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs @@ -1,4 +1,5 @@ using Ryujinx.Common; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Device; using Ryujinx.Graphics.Texture; using System; @@ -197,8 +198,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory if (target != null) { + var memory = ByteMemoryPool.Rent(data.Length); + data.CopyTo(memory.Memory.Span); + target.SynchronizeMemory(); - target.SetData(data, 0, 0, new GAL.Rectangle(_dstX, _dstY, _lineLengthIn / target.Info.FormatInfo.BytesPerPixel, _lineCount)); + target.SetData(memory, 0, 0, new GAL.Rectangle(_dstX, _dstY, _lineLengthIn / target.Info.FormatInfo.BytesPerPixel, _lineCount)); target.SignalModified(); return; diff --git a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs index f1615b388..195d13084 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -7,6 +7,7 @@ using Ryujinx.Graphics.Texture.Astc; using Ryujinx.Memory; using Ryujinx.Memory.Range; using System; +using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -661,7 +662,7 @@ namespace Ryujinx.Graphics.Gpu.Image } } - SpanOrArray result = ConvertToHostCompatibleFormat(data); + IMemoryOwner result = ConvertToHostCompatibleFormat(data); if (ScaleFactor != 1f && AllowScaledSetData()) { @@ -681,10 +682,10 @@ namespace Ryujinx.Graphics.Gpu.Image } /// - /// Uploads new texture data to the host GPU. + /// Uploads new texture data to the host GPU. The data passed as a will be disposed when the operation completes. /// /// New data - public void SetData(SpanOrArray data) + public void SetData(IMemoryOwner data) { BlacklistScale(); @@ -698,12 +699,12 @@ namespace Ryujinx.Graphics.Gpu.Image } /// - /// Uploads new texture data to the host GPU for a specific layer/level. + /// Uploads new texture data to the host GPU for a specific layer/level. The data passed as a will be disposed when the operation completes. /// /// New data /// Target layer /// Target level - public void SetData(SpanOrArray data, int layer, int level) + public void SetData(IMemoryOwner data, int layer, int level) { BlacklistScale(); @@ -715,13 +716,13 @@ namespace Ryujinx.Graphics.Gpu.Image } /// - /// Uploads new texture data to the host GPU for a specific layer/level and 2D sub-region. + /// Uploads new texture data to the host GPU for a specific layer/level and 2D sub-region. The data passed as a will be disposed when the operation completes. /// /// New data /// Target layer /// Target level /// Target sub-region of the texture to update - public void SetData(ReadOnlySpan data, int layer, int level, Rectangle region) + public void SetData(IMemoryOwner data, int layer, int level, Rectangle region) { BlacklistScale(); @@ -739,7 +740,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// Mip level to convert /// True to convert a single slice /// Converted data - public SpanOrArray ConvertToHostCompatibleFormat(ReadOnlySpan data, int level = 0, bool single = false) + public IMemoryOwner ConvertToHostCompatibleFormat(ReadOnlySpan data, int level = 0, bool single = false) { int width = Info.Width; int height = Info.Height; @@ -754,11 +755,11 @@ namespace Ryujinx.Graphics.Gpu.Image int sliceDepth = single ? 1 : depth; - SpanOrArray result; + IMemoryOwner linear; if (Info.IsLinear) { - result = LayoutConverter.ConvertLinearStridedToLinear( + linear = LayoutConverter.ConvertLinearStridedToLinear( width, height, Info.FormatInfo.BlockWidth, @@ -770,7 +771,7 @@ namespace Ryujinx.Graphics.Gpu.Image } else { - result = LayoutConverter.ConvertBlockLinearToLinear( + linear = LayoutConverter.ConvertBlockLinearToLinear( width, height, depth, @@ -787,13 +788,15 @@ namespace Ryujinx.Graphics.Gpu.Image data); } + IMemoryOwner result = linear; + // Handle compressed cases not supported by the host: // - ASTC is usually not supported on desktop cards. // - BC4/BC5 is not supported on 3D textures. if (!_context.Capabilities.SupportsAstcCompression && Format.IsAstc()) { if (!AstcDecoder.TryDecodeToRgba8P( - result.ToArray(), + result.Memory, Info.FormatInfo.BlockWidth, Info.FormatInfo.BlockHeight, width, @@ -801,7 +804,7 @@ namespace Ryujinx.Graphics.Gpu.Image sliceDepth, levels, layers, - out byte[] decoded)) + out IMemoryOwner decoded)) { string texInfo = $"{Info.Target} {Info.FormatInfo.Format} {Info.Width}x{Info.Height}x{Info.DepthOrLayers} levels {Info.Levels}"; @@ -810,10 +813,15 @@ namespace Ryujinx.Graphics.Gpu.Image if (GraphicsConfig.EnableTextureRecompression) { - decoded = BCnEncoder.EncodeBC7(decoded, width, height, sliceDepth, levels, layers); + using (decoded) + { + result = BCnEncoder.EncodeBC7(decoded.Memory, width, height, sliceDepth, levels, layers); + } + } + else + { + result = decoded; } - - result = decoded; } else if (!_context.Capabilities.SupportsEtc2Compression && Format.IsEtc2()) { @@ -821,15 +829,15 @@ namespace Ryujinx.Graphics.Gpu.Image { case Format.Etc2RgbaSrgb: case Format.Etc2RgbaUnorm: - result = ETC2Decoder.DecodeRgba(result, width, height, sliceDepth, levels, layers); + result = ETC2Decoder.DecodeRgba(result.Memory.Span, width, height, sliceDepth, levels, layers); break; case Format.Etc2RgbPtaSrgb: case Format.Etc2RgbPtaUnorm: - result = ETC2Decoder.DecodePta(result, width, height, sliceDepth, levels, layers); + result = ETC2Decoder.DecodePta(result.Memory.Span, width, height, sliceDepth, levels, layers); break; case Format.Etc2RgbSrgb: case Format.Etc2RgbUnorm: - result = ETC2Decoder.DecodeRgb(result, width, height, sliceDepth, levels, layers); + result = ETC2Decoder.DecodeRgb(result.Memory.Span, width, height, sliceDepth, levels, layers); break; } } @@ -839,48 +847,55 @@ namespace Ryujinx.Graphics.Gpu.Image { case Format.Bc1RgbaSrgb: case Format.Bc1RgbaUnorm: - result = BCnDecoder.DecodeBC1(result, width, height, sliceDepth, levels, layers); + result = BCnDecoder.DecodeBC1(result.Memory.Span, width, height, sliceDepth, levels, layers); break; case Format.Bc2Srgb: case Format.Bc2Unorm: - result = BCnDecoder.DecodeBC2(result, width, height, sliceDepth, levels, layers); + result = BCnDecoder.DecodeBC2(result.Memory.Span, width, height, sliceDepth, levels, layers); break; case Format.Bc3Srgb: case Format.Bc3Unorm: - result = BCnDecoder.DecodeBC3(result, width, height, sliceDepth, levels, layers); + result = BCnDecoder.DecodeBC3(result.Memory.Span, width, height, sliceDepth, levels, layers); break; case Format.Bc4Snorm: case Format.Bc4Unorm: - result = BCnDecoder.DecodeBC4(result, width, height, sliceDepth, levels, layers, Format == Format.Bc4Snorm); + result = BCnDecoder.DecodeBC4(result.Memory.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc4Snorm); break; case Format.Bc5Snorm: case Format.Bc5Unorm: - result = BCnDecoder.DecodeBC5(result, width, height, sliceDepth, levels, layers, Format == Format.Bc5Snorm); + result = BCnDecoder.DecodeBC5(result.Memory.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc5Snorm); break; case Format.Bc6HSfloat: case Format.Bc6HUfloat: - result = BCnDecoder.DecodeBC6(result, width, height, sliceDepth, levels, layers, Format == Format.Bc6HSfloat); + result = BCnDecoder.DecodeBC6(result.Memory.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc6HSfloat); break; case Format.Bc7Srgb: case Format.Bc7Unorm: - result = BCnDecoder.DecodeBC7(result, width, height, sliceDepth, levels, layers); + result = BCnDecoder.DecodeBC7(result.Memory.Span, width, height, sliceDepth, levels, layers); break; } } else if (!_context.Capabilities.SupportsR4G4Format && Format == Format.R4G4Unorm) { - result = PixelConverter.ConvertR4G4ToR4G4B4A4(result, width); + var converted = PixelConverter.ConvertR4G4ToR4G4B4A4(result.Memory.Span, width); if (!_context.Capabilities.SupportsR4G4B4A4Format) { - result = PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result, width); + using (converted) + { + result = PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(converted.Memory.Span, width); + } + } + else + { + result = converted; } } else if (Format == Format.R4G4B4A4Unorm) { if (!_context.Capabilities.SupportsR4G4B4A4Format) { - result = PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result, width); + result = PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result.Memory.Span, width); } } else if (!_context.Capabilities.Supports5BitComponentFormat && Format.Is16BitPacked()) @@ -889,22 +904,27 @@ namespace Ryujinx.Graphics.Gpu.Image { case Format.B5G6R5Unorm: case Format.R5G6B5Unorm: - result = PixelConverter.ConvertR5G6B5ToR8G8B8A8(result, width); + result = PixelConverter.ConvertR5G6B5ToR8G8B8A8(result.Memory.Span, width); break; case Format.B5G5R5A1Unorm: case Format.R5G5B5X1Unorm: case Format.R5G5B5A1Unorm: - result = PixelConverter.ConvertR5G5B5ToR8G8B8A8(result, width, Format == Format.R5G5B5X1Unorm); + result = PixelConverter.ConvertR5G5B5ToR8G8B8A8(result.Memory.Span, width, Format == Format.R5G5B5X1Unorm); break; case Format.A1B5G5R5Unorm: - result = PixelConverter.ConvertA1B5G5R5ToR8G8B8A8(result, width); + result = PixelConverter.ConvertA1B5G5R5ToR8G8B8A8(result.Memory.Span, width); break; case Format.R4G4B4A4Unorm: - result = PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result, width); + result = PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result.Memory.Span, width); break; } } + if (!ReferenceEquals(linear, result)) + { + linear.Dispose(); + } + return result; } diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs index 0fb4f1be7..c1e0af094 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs @@ -6,6 +6,7 @@ using Ryujinx.Memory; using Ryujinx.Memory.Range; using Ryujinx.Memory.Tracking; using System; +using System.Buffers; using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -445,7 +446,7 @@ namespace Ryujinx.Graphics.Gpu.Image ReadOnlySpan data = dataSpan[(offset - spanBase)..]; - SpanOrArray result = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel + level, true); + IMemoryOwner result = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel + level, true); Storage.SetData(result, info.BaseLayer + layer, info.BaseLevel + level); } diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs index f140b276a..e8f6d9a26 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs @@ -2,6 +2,7 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Common.Memory; using Ryujinx.Graphics.GAL; using System; +using System.Buffers; namespace Ryujinx.Graphics.OpenGL.Image { @@ -54,20 +55,24 @@ namespace Ryujinx.Graphics.OpenGL.Image throw new NotImplementedException(); } - public void SetData(SpanOrArray data) + public void SetData(IMemoryOwner data) { - var dataSpan = data.AsSpan(); + var dataSpan = data.Memory.Span; Buffer.SetData(_buffer, _bufferOffset, dataSpan[..Math.Min(dataSpan.Length, _bufferSize)]); + + data.Dispose(); } - public void SetData(SpanOrArray data, int layer, int level) + public void SetData(IMemoryOwner data, int layer, int level) { + data.Dispose(); throw new NotSupportedException(); } - public void SetData(SpanOrArray data, int layer, int level, Rectangle region) + public void SetData(IMemoryOwner data, int layer, int level, Rectangle region) { + data.Dispose(); throw new NotSupportedException(); } diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs index 79c6cb685..adaa82572 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs @@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.OpenGL.Image private int _viewsCount; - internal ITexture DefaultView { get; private set; } + internal TextureView DefaultView { get; private set; } public TextureStorage(OpenGLRenderer renderer, TextureCreateInfo info) { @@ -144,14 +144,14 @@ namespace Ryujinx.Graphics.OpenGL.Image } } - public ITexture CreateDefaultView() + public TextureView CreateDefaultView() { DefaultView = CreateView(Info, 0, 0); return DefaultView; } - public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel) + public TextureView CreateView(TextureCreateInfo info, int firstLayer, int firstLevel) { IncrementViewsCount(); diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs index 7f1b1c382..7451fc1d4 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs @@ -3,6 +3,7 @@ using Ryujinx.Common; using Ryujinx.Common.Memory; using Ryujinx.Graphics.GAL; using System; +using System.Buffers; using System.Diagnostics; namespace Ryujinx.Graphics.OpenGL.Image @@ -448,10 +449,8 @@ namespace Ryujinx.Graphics.OpenGL.Image } } - public void SetData(SpanOrArray data) + public void SetData(ReadOnlySpan dataSpan) { - var dataSpan = data.AsSpan(); - if (Format == Format.S8UintD24Unorm) { dataSpan = FormatConverter.ConvertS8D24ToD24S8(dataSpan); @@ -466,9 +465,16 @@ namespace Ryujinx.Graphics.OpenGL.Image } } - public void SetData(SpanOrArray data, int layer, int level) + public void SetData(IMemoryOwner data) { - var dataSpan = data.AsSpan(); + SetData(data.Memory.Span); + + data.Dispose(); + } + + public void SetData(IMemoryOwner data, int layer, int level) + { + var dataSpan = data.Memory.Span; if (Format == Format.S8UintD24Unorm) { @@ -485,11 +491,13 @@ namespace Ryujinx.Graphics.OpenGL.Image ReadFrom2D((IntPtr)ptr, layer, level, 0, 0, width, height); } } + + data.Dispose(); } - public void SetData(SpanOrArray data, int layer, int level, Rectangle region) + public void SetData(IMemoryOwner data, int layer, int level, Rectangle region) { - var dataSpan = data.AsSpan(); + var dataSpan = data.Memory.Span; if (Format == Format.S8UintD24Unorm) { @@ -514,6 +522,8 @@ namespace Ryujinx.Graphics.OpenGL.Image BitUtils.AlignUp(wInBlocks * Info.BytesPerPixel, 4) * hInBlocks); } } + + data.Dispose(); } public void ReadFromPbo(int offset, int size) diff --git a/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs b/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs index edf699dc3..3f65e1225 100644 --- a/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs +++ b/src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs @@ -1,5 +1,7 @@ +using Ryujinx.Common.Memory; using Ryujinx.Common.Utilities; using System; +using System.Buffers; using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; @@ -291,16 +293,14 @@ namespace Ryujinx.Graphics.Texture.Astc int depth, int levels, int layers, - out byte[] decoded) + out IMemoryOwner decoded) { - byte[] output = new byte[QueryDecompressedSize(width, height, depth, levels, layers)]; + decoded = ByteMemoryPool.Rent(QueryDecompressedSize(width, height, depth, levels, layers)); - AstcDecoder decoder = new(data, output, blockWidth, blockHeight, width, height, depth, levels, layers); + AstcDecoder decoder = new(data, decoded.Memory, blockWidth, blockHeight, width, height, depth, levels, layers); Enumerable.Range(0, decoder.TotalBlockCount).AsParallel().ForAll(x => decoder.ProcessBlock(x)); - decoded = output; - return decoder.Success; } diff --git a/src/Ryujinx.Graphics.Texture/BCnDecoder.cs b/src/Ryujinx.Graphics.Texture/BCnDecoder.cs index 2d68ca346..fef3b1f03 100644 --- a/src/Ryujinx.Graphics.Texture/BCnDecoder.cs +++ b/src/Ryujinx.Graphics.Texture/BCnDecoder.cs @@ -1,5 +1,7 @@ using Ryujinx.Common; +using Ryujinx.Common.Memory; using System; +using System.Buffers; using System.Buffers.Binary; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; @@ -12,7 +14,7 @@ namespace Ryujinx.Graphics.Texture private const int BlockWidth = 4; private const int BlockHeight = 4; - public static byte[] DecodeBC1(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) + public static IMemoryOwner DecodeBC1(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) { int size = 0; @@ -21,12 +23,12 @@ namespace Ryujinx.Graphics.Texture size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4; } - byte[] output = new byte[size]; + IMemoryOwner output = ByteMemoryPool.Rent(size); Span tile = stackalloc byte[BlockWidth * BlockHeight * 4]; Span tileAsUint = MemoryMarshal.Cast(tile); - Span outputAsUint = MemoryMarshal.Cast(output); + Span outputAsUint = MemoryMarshal.Cast(output.Memory.Span); Span> tileAsVector128 = MemoryMarshal.Cast>(tile); @@ -100,7 +102,7 @@ namespace Ryujinx.Graphics.Texture return output; } - public static byte[] DecodeBC2(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) + public static IMemoryOwner DecodeBC2(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) { int size = 0; @@ -109,12 +111,12 @@ namespace Ryujinx.Graphics.Texture size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4; } - byte[] output = new byte[size]; + IMemoryOwner output = ByteMemoryPool.Rent(size); Span tile = stackalloc byte[BlockWidth * BlockHeight * 4]; Span tileAsUint = MemoryMarshal.Cast(tile); - Span outputAsUint = MemoryMarshal.Cast(output); + Span outputAsUint = MemoryMarshal.Cast(output.Memory.Span); Span> tileAsVector128 = MemoryMarshal.Cast>(tile); @@ -195,7 +197,7 @@ namespace Ryujinx.Graphics.Texture return output; } - public static byte[] DecodeBC3(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) + public static IMemoryOwner DecodeBC3(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) { int size = 0; @@ -204,13 +206,13 @@ namespace Ryujinx.Graphics.Texture size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4; } - byte[] output = new byte[size]; + IMemoryOwner output = ByteMemoryPool.Rent(size); Span tile = stackalloc byte[BlockWidth * BlockHeight * 4]; Span rPal = stackalloc byte[8]; Span tileAsUint = MemoryMarshal.Cast(tile); - Span outputAsUint = MemoryMarshal.Cast(output); + Span outputAsUint = MemoryMarshal.Cast(output.Memory.Span); Span> tileAsVector128 = MemoryMarshal.Cast>(tile); @@ -292,7 +294,7 @@ namespace Ryujinx.Graphics.Texture return output; } - public static byte[] DecodeBC4(ReadOnlySpan data, int width, int height, int depth, int levels, int layers, bool signed) + public static IMemoryOwner DecodeBC4(ReadOnlySpan data, int width, int height, int depth, int levels, int layers, bool signed) { int size = 0; @@ -304,8 +306,8 @@ namespace Ryujinx.Graphics.Texture // Backends currently expect a stride alignment of 4 bytes, so output width must be aligned. int alignedWidth = BitUtils.AlignUp(width, 4); - byte[] output = new byte[size]; - Span outputSpan = new(output); + IMemoryOwner output = ByteMemoryPool.Rent(size); + Span outputSpan = output.Memory.Span; ReadOnlySpan data64 = MemoryMarshal.Cast(data); @@ -400,7 +402,7 @@ namespace Ryujinx.Graphics.Texture return output; } - public static byte[] DecodeBC5(ReadOnlySpan data, int width, int height, int depth, int levels, int layers, bool signed) + public static IMemoryOwner DecodeBC5(ReadOnlySpan data, int width, int height, int depth, int levels, int layers, bool signed) { int size = 0; @@ -412,7 +414,7 @@ namespace Ryujinx.Graphics.Texture // Backends currently expect a stride alignment of 4 bytes, so output width must be aligned. int alignedWidth = BitUtils.AlignUp(width, 2); - byte[] output = new byte[size]; + IMemoryOwner output = ByteMemoryPool.Rent(size); ReadOnlySpan data64 = MemoryMarshal.Cast(data); @@ -421,7 +423,7 @@ namespace Ryujinx.Graphics.Texture Span rPal = stackalloc byte[8]; Span gPal = stackalloc byte[8]; - Span outputAsUshort = MemoryMarshal.Cast(output); + Span outputAsUshort = MemoryMarshal.Cast(output.Memory.Span); Span rTileAsUint = MemoryMarshal.Cast(rTile); Span gTileAsUint = MemoryMarshal.Cast(gTile); @@ -525,7 +527,7 @@ namespace Ryujinx.Graphics.Texture return output; } - public static byte[] DecodeBC6(ReadOnlySpan data, int width, int height, int depth, int levels, int layers, bool signed) + public static IMemoryOwner DecodeBC6(ReadOnlySpan data, int width, int height, int depth, int levels, int layers, bool signed) { int size = 0; @@ -534,7 +536,7 @@ namespace Ryujinx.Graphics.Texture size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 8; } - byte[] output = new byte[size]; + IMemoryOwner output = ByteMemoryPool.Rent(size); int inputOffset = 0; int outputOffset = 0; @@ -548,7 +550,7 @@ namespace Ryujinx.Graphics.Texture { for (int z = 0; z < depth; z++) { - BC6Decoder.Decode(output.AsSpan()[outputOffset..], data[inputOffset..], width, height, signed); + BC6Decoder.Decode(output.Memory.Span[outputOffset..], data[inputOffset..], width, height, signed); inputOffset += w * h * 16; outputOffset += width * height * 8; @@ -563,7 +565,7 @@ namespace Ryujinx.Graphics.Texture return output; } - public static byte[] DecodeBC7(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) + public static IMemoryOwner DecodeBC7(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) { int size = 0; @@ -572,7 +574,7 @@ namespace Ryujinx.Graphics.Texture size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 4; } - byte[] output = new byte[size]; + IMemoryOwner output = ByteMemoryPool.Rent(size); int inputOffset = 0; int outputOffset = 0; @@ -586,7 +588,7 @@ namespace Ryujinx.Graphics.Texture { for (int z = 0; z < depth; z++) { - BC7Decoder.Decode(output.AsSpan()[outputOffset..], data[inputOffset..], width, height); + BC7Decoder.Decode(output.Memory.Span[outputOffset..], data[inputOffset..], width, height); inputOffset += w * h * 16; outputOffset += width * height * 4; diff --git a/src/Ryujinx.Graphics.Texture/BCnEncoder.cs b/src/Ryujinx.Graphics.Texture/BCnEncoder.cs index 8103990ff..74df038b3 100644 --- a/src/Ryujinx.Graphics.Texture/BCnEncoder.cs +++ b/src/Ryujinx.Graphics.Texture/BCnEncoder.cs @@ -1,6 +1,8 @@ using Ryujinx.Common; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.Texture.Encoders; using System; +using System.Buffers; namespace Ryujinx.Graphics.Texture { @@ -9,7 +11,7 @@ namespace Ryujinx.Graphics.Texture private const int BlockWidth = 4; private const int BlockHeight = 4; - public static byte[] EncodeBC7(byte[] data, int width, int height, int depth, int levels, int layers) + public static IMemoryOwner EncodeBC7(Memory data, int width, int height, int depth, int levels, int layers) { int size = 0; @@ -21,7 +23,7 @@ namespace Ryujinx.Graphics.Texture size += w * h * 16 * Math.Max(1, depth >> l) * layers; } - byte[] output = new byte[size]; + IMemoryOwner output = ByteMemoryPool.Rent(size); int imageBaseIOffs = 0; int imageBaseOOffs = 0; @@ -36,8 +38,8 @@ namespace Ryujinx.Graphics.Texture for (int z = 0; z < depth; z++) { BC7Encoder.Encode( - output.AsMemory()[imageBaseOOffs..], - data.AsMemory()[imageBaseIOffs..], + output.Memory[imageBaseOOffs..], + data[imageBaseIOffs..], width, height, EncodeMode.Fast | EncodeMode.Multithreaded); diff --git a/src/Ryujinx.Graphics.Texture/ETC2Decoder.cs b/src/Ryujinx.Graphics.Texture/ETC2Decoder.cs index 57f2e98d0..52801ff47 100644 --- a/src/Ryujinx.Graphics.Texture/ETC2Decoder.cs +++ b/src/Ryujinx.Graphics.Texture/ETC2Decoder.cs @@ -1,5 +1,7 @@ using Ryujinx.Common; +using Ryujinx.Common.Memory; using System; +using System.Buffers; using System.Buffers.Binary; using System.Runtime.InteropServices; @@ -49,15 +51,15 @@ namespace Ryujinx.Graphics.Texture new int[] { -3, -5, -7, -9, 2, 4, 6, 8 }, }; - public static byte[] DecodeRgb(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) + public static IMemoryOwner DecodeRgb(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) { ReadOnlySpan dataUlong = MemoryMarshal.Cast(data); int inputOffset = 0; - byte[] output = new byte[CalculateOutputSize(width, height, depth, levels, layers)]; + IMemoryOwner output = ByteMemoryPool.Rent(CalculateOutputSize(width, height, depth, levels, layers)); - Span outputUint = MemoryMarshal.Cast(output); + Span outputUint = MemoryMarshal.Cast(output.Memory.Span); Span tile = stackalloc uint[BlockWidth * BlockHeight]; int imageBaseOOffs = 0; @@ -111,15 +113,15 @@ namespace Ryujinx.Graphics.Texture return output; } - public static byte[] DecodePta(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) + public static IMemoryOwner DecodePta(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) { ReadOnlySpan dataUlong = MemoryMarshal.Cast(data); int inputOffset = 0; - byte[] output = new byte[CalculateOutputSize(width, height, depth, levels, layers)]; + IMemoryOwner output = ByteMemoryPool.Rent(CalculateOutputSize(width, height, depth, levels, layers)); - Span outputUint = MemoryMarshal.Cast(output); + Span outputUint = MemoryMarshal.Cast(output.Memory.Span); Span tile = stackalloc uint[BlockWidth * BlockHeight]; int imageBaseOOffs = 0; @@ -168,15 +170,15 @@ namespace Ryujinx.Graphics.Texture return output; } - public static byte[] DecodeRgba(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) + public static IMemoryOwner DecodeRgba(ReadOnlySpan data, int width, int height, int depth, int levels, int layers) { ReadOnlySpan dataUlong = MemoryMarshal.Cast(data); int inputOffset = 0; - byte[] output = new byte[CalculateOutputSize(width, height, depth, levels, layers)]; + IMemoryOwner output = ByteMemoryPool.Rent(CalculateOutputSize(width, height, depth, levels, layers)); - Span outputUint = MemoryMarshal.Cast(output); + Span outputUint = MemoryMarshal.Cast(output.Memory.Span); Span tile = stackalloc uint[BlockWidth * BlockHeight]; int imageBaseOOffs = 0; diff --git a/src/Ryujinx.Graphics.Texture/LayoutConverter.cs b/src/Ryujinx.Graphics.Texture/LayoutConverter.cs index d9a666c3f..d6732674b 100644 --- a/src/Ryujinx.Graphics.Texture/LayoutConverter.cs +++ b/src/Ryujinx.Graphics.Texture/LayoutConverter.cs @@ -1,5 +1,7 @@ using Ryujinx.Common; +using Ryujinx.Common.Memory; using System; +using System.Buffers; using System.Runtime.Intrinsics; using static Ryujinx.Graphics.Texture.BlockLinearConstants; @@ -93,7 +95,7 @@ namespace Ryujinx.Graphics.Texture }; } - public static byte[] ConvertBlockLinearToLinear( + public static IMemoryOwner ConvertBlockLinearToLinear( int width, int height, int depth, @@ -119,7 +121,8 @@ namespace Ryujinx.Graphics.Texture blockHeight, bytesPerPixel); - byte[] output = new byte[outSize]; + IMemoryOwner outputOwner = ByteMemoryPool.Rent(outSize); + Span output = outputOwner.Memory.Span; int outOffs = 0; @@ -243,10 +246,10 @@ namespace Ryujinx.Graphics.Texture _ => throw new NotSupportedException($"Unable to convert ${bytesPerPixel} bpp pixel format."), }; } - return output; + return outputOwner; } - public static byte[] ConvertLinearStridedToLinear( + public static IMemoryOwner ConvertLinearStridedToLinear( int width, int height, int blockWidth, @@ -262,8 +265,8 @@ namespace Ryujinx.Graphics.Texture int outStride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment); lineSize = Math.Min(lineSize, outStride); - byte[] output = new byte[h * outStride]; - Span outSpan = output; + IMemoryOwner output = ByteMemoryPool.Rent(h * outStride); + Span outSpan = output.Memory.Span; int outOffs = 0; int inOffs = 0; diff --git a/src/Ryujinx.Graphics.Texture/PixelConverter.cs b/src/Ryujinx.Graphics.Texture/PixelConverter.cs index 7955aed3f..27d134074 100644 --- a/src/Ryujinx.Graphics.Texture/PixelConverter.cs +++ b/src/Ryujinx.Graphics.Texture/PixelConverter.cs @@ -1,5 +1,7 @@ using Ryujinx.Common; +using Ryujinx.Common.Memory; using System; +using System.Buffers; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; @@ -19,13 +21,13 @@ namespace Ryujinx.Graphics.Texture return (remainder, outRemainder, length / stride); } - public unsafe static byte[] ConvertR4G4ToR4G4B4A4(ReadOnlySpan data, int width) + public unsafe static IMemoryOwner ConvertR4G4ToR4G4B4A4(ReadOnlySpan data, int width) { - byte[] output = new byte[data.Length * 2]; + IMemoryOwner output = ByteMemoryPool.Rent(data.Length * 2); (int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 1, 2); - Span outputSpan = MemoryMarshal.Cast(output); + Span outputSpan = MemoryMarshal.Cast(output.Memory.Span); if (remainder == 0) { @@ -36,7 +38,7 @@ namespace Ryujinx.Graphics.Texture int sizeTrunc = data.Length & ~7; start = sizeTrunc; - fixed (byte* inputPtr = data, outputPtr = output) + fixed (byte* inputPtr = data, outputPtr = output.Memory.Span) { for (ulong offset = 0; offset < (ulong)sizeTrunc; offset += 8) { @@ -70,16 +72,16 @@ namespace Ryujinx.Graphics.Texture return output; } - public unsafe static byte[] ConvertR5G6B5ToR8G8B8A8(ReadOnlySpan data, int width) + public unsafe static IMemoryOwner ConvertR5G6B5ToR8G8B8A8(ReadOnlySpan data, int width) { - byte[] output = new byte[data.Length * 2]; + IMemoryOwner output = ByteMemoryPool.Rent(data.Length * 2); int offset = 0; int outOffset = 0; (int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4); ReadOnlySpan inputSpan = MemoryMarshal.Cast(data); - Span outputSpan = MemoryMarshal.Cast(output); + Span outputSpan = MemoryMarshal.Cast(output.Memory.Span); for (int y = 0; y < height; y++) { @@ -107,16 +109,16 @@ namespace Ryujinx.Graphics.Texture return output; } - public unsafe static byte[] ConvertR5G5B5ToR8G8B8A8(ReadOnlySpan data, int width, bool forceAlpha) + public unsafe static IMemoryOwner ConvertR5G5B5ToR8G8B8A8(ReadOnlySpan data, int width, bool forceAlpha) { - byte[] output = new byte[data.Length * 2]; + IMemoryOwner output = ByteMemoryPool.Rent(data.Length * 2); int offset = 0; int outOffset = 0; (int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4); ReadOnlySpan inputSpan = MemoryMarshal.Cast(data); - Span outputSpan = MemoryMarshal.Cast(output); + Span outputSpan = MemoryMarshal.Cast(output.Memory.Span); for (int y = 0; y < height; y++) { @@ -144,16 +146,16 @@ namespace Ryujinx.Graphics.Texture return output; } - public unsafe static byte[] ConvertA1B5G5R5ToR8G8B8A8(ReadOnlySpan data, int width) + public unsafe static IMemoryOwner ConvertA1B5G5R5ToR8G8B8A8(ReadOnlySpan data, int width) { - byte[] output = new byte[data.Length * 2]; + IMemoryOwner output = ByteMemoryPool.Rent(data.Length * 2); int offset = 0; int outOffset = 0; (int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4); ReadOnlySpan inputSpan = MemoryMarshal.Cast(data); - Span outputSpan = MemoryMarshal.Cast(output); + Span outputSpan = MemoryMarshal.Cast(output.Memory.Span); for (int y = 0; y < height; y++) { @@ -181,16 +183,16 @@ namespace Ryujinx.Graphics.Texture return output; } - public unsafe static byte[] ConvertR4G4B4A4ToR8G8B8A8(ReadOnlySpan data, int width) + public unsafe static IMemoryOwner ConvertR4G4B4A4ToR8G8B8A8(ReadOnlySpan data, int width) { - byte[] output = new byte[data.Length * 2]; + IMemoryOwner output = ByteMemoryPool.Rent(data.Length * 2); int offset = 0; int outOffset = 0; (int remainder, int outRemainder, int height) = GetLineRemainders(data.Length, width, 2, 4); ReadOnlySpan inputSpan = MemoryMarshal.Cast(data); - Span outputSpan = MemoryMarshal.Cast(output); + Span outputSpan = MemoryMarshal.Cast(output.Memory.Span); for (int y = 0; y < height; y++) { diff --git a/src/Ryujinx.Graphics.Vulkan/TextureBuffer.cs b/src/Ryujinx.Graphics.Vulkan/TextureBuffer.cs index 81e478814..5cb8b8f49 100644 --- a/src/Ryujinx.Graphics.Vulkan/TextureBuffer.cs +++ b/src/Ryujinx.Graphics.Vulkan/TextureBuffer.cs @@ -2,6 +2,7 @@ using Ryujinx.Common.Memory; using Ryujinx.Graphics.GAL; using Silk.NET.Vulkan; using System; +using System.Buffers; using System.Collections.Generic; using Format = Ryujinx.Graphics.GAL.Format; using VkFormat = Silk.NET.Vulkan.Format; @@ -94,18 +95,21 @@ namespace Ryujinx.Graphics.Vulkan _bufferView = null; } - public void SetData(SpanOrArray data) + public void SetData(IMemoryOwner data) { - _gd.SetBufferData(_bufferHandle, _offset, data); + _gd.SetBufferData(_bufferHandle, _offset, data.Memory.Span); + data.Dispose(); } - public void SetData(SpanOrArray data, int layer, int level) + public void SetData(IMemoryOwner data, int layer, int level) { + data.Dispose(); throw new NotSupportedException(); } - public void SetData(SpanOrArray data, int layer, int level, Rectangle region) + public void SetData(IMemoryOwner data, int layer, int level, Rectangle region) { + data.Dispose(); throw new NotSupportedException(); } diff --git a/src/Ryujinx.Graphics.Vulkan/TextureView.cs b/src/Ryujinx.Graphics.Vulkan/TextureView.cs index f5b80f948..96e113f07 100644 --- a/src/Ryujinx.Graphics.Vulkan/TextureView.cs +++ b/src/Ryujinx.Graphics.Vulkan/TextureView.cs @@ -2,6 +2,7 @@ using Ryujinx.Common.Memory; using Ryujinx.Graphics.GAL; using Silk.NET.Vulkan; using System; +using System.Buffers; using System.Collections.Generic; using Format = Ryujinx.Graphics.GAL.Format; using VkBuffer = Silk.NET.Vulkan.Buffer; @@ -656,19 +657,27 @@ namespace Ryujinx.Graphics.Vulkan return GetDataFromBuffer(result, size, result); } - public void SetData(SpanOrArray data) + public void SetData(ReadOnlySpan data) { SetData(data, 0, 0, Info.GetLayers(), Info.Levels, singleSlice: false); } - public void SetData(SpanOrArray data, int layer, int level) + public void SetData(IMemoryOwner data) { - SetData(data, layer, level, 1, 1, singleSlice: true); + SetData(data.Memory.Span); + data.Dispose(); } - public void SetData(SpanOrArray data, int layer, int level, Rectangle region) + public void SetData(IMemoryOwner data, int layer, int level) { - SetData(data, layer, level, 1, 1, singleSlice: true, region); + SetData(data.Memory.Span, layer, level, 1, 1, singleSlice: true); + data.Dispose(); + } + + public void SetData(IMemoryOwner data, int layer, int level, Rectangle region) + { + SetData(data.Memory.Span, layer, level, 1, 1, singleSlice: true, region); + data.Dispose(); } private void SetData(ReadOnlySpan data, int layer, int level, int layers, int levels, bool singleSlice, Rectangle? region = null)