diff --git a/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs b/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs index bdd5d38566..3673ee5a1f 100644 --- a/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs +++ b/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs @@ -4,6 +4,7 @@ using Silk.NET.Vulkan; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Threading; using VkBuffer = Silk.NET.Vulkan.Buffer; using VkFormat = Silk.NET.Vulkan.Format; @@ -384,7 +385,7 @@ namespace Ryujinx.Graphics.Vulkan var baseData = new Span((void*)(_map + offset), size); var modData = _pendingData.AsSpan(offset, size); - StagingBufferReserved? newMirror = _gd.BufferManager.StagingBuffer.TryReserveData(cbs, size, (int)_gd.Capabilities.MinResourceAlignment); + StagingBufferReserved? newMirror = _gd.BufferManager.StagingBuffer.TryReserveData(cbs, size); if (newMirror != null) { @@ -838,6 +839,11 @@ namespace Ryujinx.Graphics.Vulkan } } + public unsafe void SetDataUnchecked(int offset, ReadOnlySpan data) where T : unmanaged + { + SetDataUnchecked(offset, MemoryMarshal.AsBytes(data)); + } + public void SetDataInline(CommandBufferScoped cbs, Action endRenderPass, int dstOffset, ReadOnlySpan data) { if (!TryPushData(cbs, endRenderPass, dstOffset, data)) diff --git a/src/Ryujinx.Graphics.Vulkan/BufferManager.cs b/src/Ryujinx.Graphics.Vulkan/BufferManager.cs index e9ac988475..33289a0e09 100644 --- a/src/Ryujinx.Graphics.Vulkan/BufferManager.cs +++ b/src/Ryujinx.Graphics.Vulkan/BufferManager.cs @@ -9,6 +9,36 @@ using VkFormat = Silk.NET.Vulkan.Format; namespace Ryujinx.Graphics.Vulkan { + readonly struct ScopedTemporaryBuffer : IDisposable + { + private readonly BufferManager _bufferManager; + private readonly bool _isReserved; + + public readonly BufferRange Range; + public readonly BufferHolder Holder; + + public BufferHandle Handle => Range.Handle; + public int Offset => Range.Offset; + + public ScopedTemporaryBuffer(BufferManager bufferManager, BufferHolder holder, BufferHandle handle, int offset, int size, bool isReserved) + { + _bufferManager = bufferManager; + + Range = new BufferRange(handle, offset, size); + Holder = holder; + + _isReserved = isReserved; + } + + public void Dispose() + { + if (!_isReserved) + { + _bufferManager.Delete(Range.Handle); + } + } + } + class BufferManager : IDisposable { public const MemoryPropertyFlags DefaultBufferMemoryFlags = @@ -238,6 +268,23 @@ namespace Ryujinx.Graphics.Vulkan return Unsafe.As(ref handle64); } + public ScopedTemporaryBuffer ReserveOrCreate(VulkanRenderer gd, CommandBufferScoped cbs, int size) + { + StagingBufferReserved? result = StagingBuffer.TryReserveData(cbs, size); + + if (result.HasValue) + { + return new ScopedTemporaryBuffer(this, result.Value.Buffer, StagingBuffer.Handle, result.Value.Offset, result.Value.Size, true); + } + else + { + // Create a temporary buffer. + BufferHandle handle = CreateWithHandle(gd, size, out BufferHolder holder); + + return new ScopedTemporaryBuffer(this, holder, handle, 0, size, false); + } + } + public unsafe MemoryRequirements GetHostImportedUsageRequirements(VulkanRenderer gd) { var usage = HostImportedBufferUsageFlags; @@ -635,13 +682,14 @@ namespace Ryujinx.Graphics.Vulkan { if (disposing) { + StagingBuffer.Dispose(); + foreach (BufferHolder buffer in _buffers) { buffer.Dispose(); } _buffers.Clear(); - StagingBuffer.Dispose(); } } diff --git a/src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs b/src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs index 23acdcf8f4..5c0fc468bc 100644 --- a/src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs +++ b/src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs @@ -142,19 +142,18 @@ namespace Ryujinx.Graphics.Vulkan.Effects }; int rangeSize = dimensionsBuffer.Length * sizeof(float); - var bufferHandle = _renderer.BufferManager.CreateWithHandle(_renderer, rangeSize); - _renderer.BufferManager.SetData(bufferHandle, 0, dimensionsBuffer); + using var buffer = _renderer.BufferManager.ReserveOrCreate(_renderer, cbs, rangeSize); + buffer.Holder.SetDataUnchecked(buffer.Offset, dimensionsBuffer); - ReadOnlySpan sharpeningBuffer = stackalloc float[] { 1.5f - (Level * 0.01f * 1.5f) }; - var sharpeningBufferHandle = _renderer.BufferManager.CreateWithHandle(_renderer, sizeof(float)); - _renderer.BufferManager.SetData(sharpeningBufferHandle, 0, sharpeningBuffer); + ReadOnlySpan sharpeningBufferData = stackalloc float[] { 1.5f - (Level * 0.01f * 1.5f) }; + using var sharpeningBuffer = _renderer.BufferManager.ReserveOrCreate(_renderer, cbs, sizeof(float)); + sharpeningBuffer.Holder.SetDataUnchecked(sharpeningBuffer.Offset, sharpeningBufferData); int threadGroupWorkRegionDim = 16; int dispatchX = (width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - var bufferRanges = new BufferRange(bufferHandle, 0, rangeSize); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(2, bufferRanges) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(2, buffer.Range) }); _pipeline.SetImage(0, _intermediaryTexture, FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)); _pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.ComputeBarrier(); @@ -162,16 +161,12 @@ namespace Ryujinx.Graphics.Vulkan.Effects // Sharpening pass _pipeline.SetProgram(_sharpeningProgram); _pipeline.SetTextureAndSampler(ShaderStage.Compute, 1, _intermediaryTexture, _sampler); - var sharpeningRange = new BufferRange(sharpeningBufferHandle, 0, sizeof(float)); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(4, sharpeningRange) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(4, sharpeningBuffer.Range) }); _pipeline.SetImage(0, destinationTexture); _pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.ComputeBarrier(); _pipeline.Finish(); - - _renderer.BufferManager.Delete(bufferHandle); - _renderer.BufferManager.Delete(sharpeningBufferHandle); } } } diff --git a/src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs b/src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs index 67e461e515..a7dd8eee80 100644 --- a/src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs +++ b/src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs @@ -66,12 +66,11 @@ namespace Ryujinx.Graphics.Vulkan.Effects ReadOnlySpan resolutionBuffer = stackalloc float[] { view.Width, view.Height }; int rangeSize = resolutionBuffer.Length * sizeof(float); - var bufferHandle = _renderer.BufferManager.CreateWithHandle(_renderer, rangeSize); + using var buffer = _renderer.BufferManager.ReserveOrCreate(_renderer, cbs, rangeSize); - _renderer.BufferManager.SetData(bufferHandle, 0, resolutionBuffer); + buffer.Holder.SetDataUnchecked(buffer.Offset, resolutionBuffer); - var bufferRanges = new BufferRange(bufferHandle, 0, rangeSize); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(2, bufferRanges) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(2, buffer.Range) }); var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize); var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize); @@ -79,7 +78,6 @@ namespace Ryujinx.Graphics.Vulkan.Effects _pipeline.SetImage(0, _texture, FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)); _pipeline.DispatchCompute(dispatchX, dispatchY, 1); - _renderer.BufferManager.Delete(bufferHandle); _pipeline.ComputeBarrier(); _pipeline.Finish(); diff --git a/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs b/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs index c521f2273a..802b73b860 100644 --- a/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs +++ b/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs @@ -215,11 +215,10 @@ namespace Ryujinx.Graphics.Vulkan.Effects ReadOnlySpan resolutionBuffer = stackalloc float[] { view.Width, view.Height }; int rangeSize = resolutionBuffer.Length * sizeof(float); - var bufferHandle = _renderer.BufferManager.CreateWithHandle(_renderer, rangeSize); + using var buffer = _renderer.BufferManager.ReserveOrCreate(_renderer, cbs, rangeSize); - _renderer.BufferManager.SetData(bufferHandle, 0, resolutionBuffer); - var bufferRanges = new BufferRange(bufferHandle, 0, rangeSize); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(2, bufferRanges) }); + buffer.Holder.SetDataUnchecked(buffer.Offset, resolutionBuffer); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(2, buffer.Range) }); _pipeline.SetImage(0, _edgeOutputTexture, FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)); _pipeline.DispatchCompute(dispatchX, dispatchY, 1); _pipeline.ComputeBarrier(); @@ -245,8 +244,6 @@ namespace Ryujinx.Graphics.Vulkan.Effects _pipeline.Finish(); - _renderer.BufferManager.Delete(bufferHandle); - return _outputTexture; } diff --git a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs index deaf81625a..ce84f75218 100644 --- a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs +++ b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs @@ -430,11 +430,11 @@ namespace Ryujinx.Graphics.Vulkan (region[2], region[3]) = (region[3], region[2]); } - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, RegionBufferSize); + using var buffer = gd.BufferManager.ReserveOrCreate(gd, cbs, RegionBufferSize); - gd.BufferManager.SetData(bufferHandle, 0, region); + buffer.Holder.SetDataUnchecked(buffer.Offset, region); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, RegionBufferSize)) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, buffer.Range) }); Span viewports = stackalloc Viewport[1]; @@ -490,8 +490,6 @@ namespace Ryujinx.Graphics.Vulkan } _pipeline.Finish(gd, cbs); - - gd.BufferManager.Delete(bufferHandle); } private void BlitDepthStencil( @@ -527,11 +525,11 @@ namespace Ryujinx.Graphics.Vulkan (region[2], region[3]) = (region[3], region[2]); } - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, RegionBufferSize); + using var buffer = gd.BufferManager.ReserveOrCreate(gd, cbs, RegionBufferSize); - gd.BufferManager.SetData(bufferHandle, 0, region); + buffer.Holder.SetDataUnchecked(buffer.Offset, region); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, RegionBufferSize)) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, buffer.Range) }); Span viewports = stackalloc Viewport[1]; @@ -582,8 +580,6 @@ namespace Ryujinx.Graphics.Vulkan } _pipeline.Finish(gd, cbs); - - gd.BufferManager.Delete(bufferHandle); } private static TextureView CreateDepthOrStencilView(TextureView depthStencilTexture, DepthStencilMode depthStencilMode) @@ -681,11 +677,11 @@ namespace Ryujinx.Graphics.Vulkan _pipeline.SetCommandBuffer(cbs); - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ClearColorBufferSize); + using var buffer = gd.BufferManager.ReserveOrCreate(gd, cbs, ClearColorBufferSize); - gd.BufferManager.SetData(bufferHandle, 0, clearColor); + buffer.Holder.SetDataUnchecked(buffer.Offset, clearColor); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, ClearColorBufferSize)) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, buffer.Range) }); Span viewports = stackalloc Viewport[1]; @@ -721,8 +717,6 @@ namespace Ryujinx.Graphics.Vulkan _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.Draw(4, 1, 0, 0); _pipeline.Finish(); - - gd.BufferManager.Delete(bufferHandle); } public void Clear( @@ -745,11 +739,11 @@ namespace Ryujinx.Graphics.Vulkan _pipeline.SetCommandBuffer(cbs); - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ClearColorBufferSize); + using var buffer = gd.BufferManager.ReserveOrCreate(gd, cbs, ClearColorBufferSize); - gd.BufferManager.SetData(bufferHandle, 0, stackalloc float[] { depthValue }); + buffer.Holder.SetDataUnchecked(buffer.Offset, stackalloc float[] { depthValue }); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, ClearColorBufferSize)) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, buffer.Range) }); Span viewports = stackalloc Viewport[1]; @@ -771,8 +765,6 @@ namespace Ryujinx.Graphics.Vulkan _pipeline.SetStencilTest(CreateStencilTestDescriptor(stencilMask != 0, stencilValue, 0xff, stencilMask)); _pipeline.Draw(4, 1, 0, 0); _pipeline.Finish(); - - gd.BufferManager.Delete(bufferHandle); } public void DrawTexture( @@ -878,13 +870,13 @@ namespace Ryujinx.Graphics.Vulkan shaderParams[2] = size; shaderParams[3] = srcOffset; - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize); + using var buffer = gd.BufferManager.ReserveOrCreate(gd, cbs, ParamsBufferSize); - gd.BufferManager.SetData(bufferHandle, 0, shaderParams); + buffer.Holder.SetDataUnchecked(buffer.Offset, shaderParams); _pipeline.SetCommandBuffer(cbs); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, buffer.Range) }); Span> sbRanges = new Auto[2]; @@ -896,8 +888,6 @@ namespace Ryujinx.Graphics.Vulkan _pipeline.SetProgram(_programStrideChange); _pipeline.DispatchCompute(1 + elems / ConvertElementsPerWorkgroup, 1, 1); - gd.BufferManager.Delete(bufferHandle); - _pipeline.Finish(gd, cbs); } else @@ -1025,7 +1015,7 @@ namespace Ryujinx.Graphics.Vulkan { const int ParamsBufferSize = 4; - Span shaderParams = stackalloc int[sizeof(int)]; + Span shaderParams = stackalloc int[ParamsBufferSize / sizeof(int)]; int srcBpp = src.Info.BytesPerPixel; int dstBpp = dst.Info.BytesPerPixel; @@ -1034,9 +1024,9 @@ namespace Ryujinx.Graphics.Vulkan shaderParams[0] = BitOperations.Log2((uint)ratio); - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize); + using var buffer = gd.BufferManager.ReserveOrCreate(gd, cbs, ParamsBufferSize); - gd.BufferManager.SetData(bufferHandle, 0, shaderParams); + buffer.Holder.SetDataUnchecked(buffer.Offset, shaderParams); TextureView.InsertImageBarrier( gd.Api, @@ -1064,7 +1054,7 @@ namespace Ryujinx.Graphics.Vulkan var srcFormat = GetFormat(componentSize, srcBpp / componentSize); var dstFormat = GetFormat(componentSize, dstBpp / componentSize); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, buffer.Range) }); for (int l = 0; l < levels; l++) { @@ -1093,8 +1083,6 @@ namespace Ryujinx.Graphics.Vulkan } } - gd.BufferManager.Delete(bufferHandle); - _pipeline.Finish(gd, cbs); TextureView.InsertImageBarrier( @@ -1128,9 +1116,9 @@ namespace Ryujinx.Graphics.Vulkan (shaderParams[0], shaderParams[1]) = GetSampleCountXYLog2(samples); (shaderParams[2], shaderParams[3]) = GetSampleCountXYLog2((int)TextureStorage.ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)samples)); - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize); + using var buffer = gd.BufferManager.ReserveOrCreate(gd, cbs, ParamsBufferSize); - gd.BufferManager.SetData(bufferHandle, 0, shaderParams); + buffer.Holder.SetDataUnchecked(buffer.Offset, shaderParams); TextureView.InsertImageBarrier( gd.Api, @@ -1147,7 +1135,7 @@ namespace Ryujinx.Graphics.Vulkan 1); _pipeline.SetCommandBuffer(cbs); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, buffer.Range) }); if (isDepthOrStencil) { @@ -1226,8 +1214,6 @@ namespace Ryujinx.Graphics.Vulkan } } - gd.BufferManager.Delete(bufferHandle); - _pipeline.Finish(gd, cbs); TextureView.InsertImageBarrier( @@ -1261,9 +1247,9 @@ namespace Ryujinx.Graphics.Vulkan (shaderParams[0], shaderParams[1]) = GetSampleCountXYLog2(samples); (shaderParams[2], shaderParams[3]) = GetSampleCountXYLog2((int)TextureStorage.ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)samples)); - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize); + using var buffer = gd.BufferManager.ReserveOrCreate(gd, cbs, ParamsBufferSize); - gd.BufferManager.SetData(bufferHandle, 0, shaderParams); + buffer.Holder.SetDataUnchecked(buffer.Offset, shaderParams); TextureView.InsertImageBarrier( gd.Api, @@ -1299,7 +1285,7 @@ namespace Ryujinx.Graphics.Vulkan _pipeline.SetViewports(viewports); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, buffer.Range) }); if (isDepthOrStencil) { @@ -1364,8 +1350,6 @@ namespace Ryujinx.Graphics.Vulkan } } - gd.BufferManager.Delete(bufferHandle); - _pipeline.Finish(gd, cbs); TextureView.InsertImageBarrier( @@ -1616,10 +1600,11 @@ namespace Ryujinx.Graphics.Vulkan pattern.OffsetIndex.CopyTo(shaderParams[..pattern.OffsetIndex.Length]); - var patternBufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize, out var patternBuffer); + using var patternScoped = gd.BufferManager.ReserveOrCreate(gd, cbs, ParamsBufferSize); + var patternBuffer = patternScoped.Holder; var patternBufferAuto = patternBuffer.GetBuffer(); - gd.BufferManager.SetData(patternBufferHandle, 0, shaderParams); + patternBuffer.SetDataUnchecked(patternScoped.Offset, shaderParams); _pipeline.SetCommandBuffer(cbs); @@ -1635,7 +1620,8 @@ namespace Ryujinx.Graphics.Vulkan indirectDataSize); _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, drawCountBufferAligned) }); - _pipeline.SetStorageBuffers(1, new[] { srcIndirectBuffer.GetBuffer(), dstIndirectBuffer.GetBuffer(), patternBuffer.GetBuffer() }); + _pipeline.SetStorageBuffers(1, new[] { srcIndirectBuffer.GetBuffer(), dstIndirectBuffer.GetBuffer() }); + _pipeline.SetStorageBuffers(stackalloc[] { new BufferAssignment(3, patternScoped.Range) }); _pipeline.SetProgram(_programConvertIndirectData); _pipeline.DispatchCompute(1, 1, 1); @@ -1643,12 +1629,12 @@ namespace Ryujinx.Graphics.Vulkan BufferHolder.InsertBufferBarrier( gd, cbs.CommandBuffer, - patternBufferAuto.Get(cbs, ParamsIndirectDispatchOffset, ParamsIndirectDispatchSize).Value, + patternBufferAuto.Get(cbs, patternScoped.Offset + ParamsIndirectDispatchOffset, ParamsIndirectDispatchSize).Value, AccessFlags.ShaderWriteBit, AccessFlags.IndirectCommandReadBit, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.DrawIndirectBit, - ParamsIndirectDispatchOffset, + patternScoped.Offset + ParamsIndirectDispatchOffset, ParamsIndirectDispatchSize); BufferHolder.InsertBufferBarrier( @@ -1662,11 +1648,11 @@ namespace Ryujinx.Graphics.Vulkan 0, convertedCount * outputIndexSize); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(patternBufferHandle, 0, ParamsBufferSize)) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(patternScoped.Handle, patternScoped.Offset, ParamsBufferSize)) }); _pipeline.SetStorageBuffers(1, new[] { srcIndexBuffer.GetBuffer(), dstIndexBuffer.GetBuffer() }); _pipeline.SetProgram(_programConvertIndexBuffer); - _pipeline.DispatchComputeIndirect(patternBufferAuto, ParamsIndirectDispatchOffset); + _pipeline.DispatchComputeIndirect(patternBufferAuto, patternScoped.Offset + ParamsIndirectDispatchOffset); BufferHolder.InsertBufferBarrier( gd, @@ -1679,8 +1665,6 @@ namespace Ryujinx.Graphics.Vulkan 0, convertedCount * outputIndexSize); - gd.BufferManager.Delete(patternBufferHandle); - _pipeline.Finish(gd, cbs); } @@ -1726,13 +1710,13 @@ namespace Ryujinx.Graphics.Vulkan shaderParams[0] = pixelCount; shaderParams[1] = dstOffset; - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize); + using var buffer = gd.BufferManager.ReserveOrCreate(gd, cbs, ParamsBufferSize); - gd.BufferManager.SetData(bufferHandle, 0, shaderParams); + buffer.Holder.SetDataUnchecked(buffer.Offset, shaderParams); _pipeline.SetCommandBuffer(cbs); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) }); + _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, buffer.Range) }); Span> sbRanges = new Auto[2]; @@ -1744,8 +1728,6 @@ namespace Ryujinx.Graphics.Vulkan _pipeline.SetProgram(_programConvertD32S8ToD24S8); _pipeline.DispatchCompute(1 + inSize / ConvertElementsPerWorkgroup, 1, 1); - gd.BufferManager.Delete(bufferHandle); - _pipeline.Finish(gd, cbs); BufferHolder.InsertBufferBarrier( diff --git a/src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs b/src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs index 3a02a28dca..90a47bb676 100644 --- a/src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs +++ b/src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs @@ -1,5 +1,6 @@ using Ryujinx.Common; using Ryujinx.Common.Logging; +using Ryujinx.Graphics.GAL; using System; using System.Collections.Generic; using System.Diagnostics; @@ -29,6 +30,9 @@ namespace Ryujinx.Graphics.Vulkan private readonly VulkanRenderer _gd; private readonly BufferHolder _buffer; + private readonly int _resourceAlignment; + + public readonly BufferHandle Handle; private readonly struct PendingCopy { @@ -48,9 +52,10 @@ namespace Ryujinx.Graphics.Vulkan public StagingBuffer(VulkanRenderer gd, BufferManager bufferManager) { _gd = gd; - _buffer = bufferManager.Create(gd, BufferSize); + Handle = bufferManager.CreateWithHandle(gd, BufferSize, out _buffer); _pendingCopies = new Queue(); _freeSize = BufferSize; + _resourceAlignment = (int)gd.Capabilities.MinResourceAlignment; } public void PushData(CommandBufferPool cbp, CommandBufferScoped? cbs, Action endRenderPass, BufferHolder dst, int dstOffset, ReadOnlySpan data) @@ -197,7 +202,7 @@ namespace Ryujinx.Graphics.Vulkan /// Reserve a range on the staging buffer for the current command buffer and upload data to it. /// /// Command buffer to reserve the data on - /// The data to upload + /// The minimum size the reserved data requires /// The required alignment for the buffer offset /// The reserved range of the staging buffer public unsafe StagingBufferReserved? TryReserveData(CommandBufferScoped cbs, int size, int alignment) @@ -223,6 +228,18 @@ namespace Ryujinx.Graphics.Vulkan return ReserveDataImpl(cbs, size, alignment); } + /// + /// Reserve a range on the staging buffer for the current command buffer and upload data to it. + /// Uses the most permissive byte alignment. + /// + /// Command buffer to reserve the data on + /// The minimum size the reserved data requires + /// The reserved range of the staging buffer + public unsafe StagingBufferReserved? TryReserveData(CommandBufferScoped cbs, int size) + { + return TryReserveData(cbs, size, _resourceAlignment); + } + private bool WaitFreeCompleted(CommandBufferPool cbp) { if (_pendingCopies.TryPeek(out var pc)) @@ -263,7 +280,7 @@ namespace Ryujinx.Graphics.Vulkan { if (disposing) { - _buffer.Dispose(); + _gd.BufferManager.Delete(Handle); while (_pendingCopies.TryDequeue(out var pc)) {