From 0c445184c185f6cd4b870d88b5eaad46c633b83b Mon Sep 17 00:00:00 2001 From: riperiperi Date: Wed, 16 Aug 2023 22:06:46 +0100 Subject: [PATCH] Vulkan: Periodically free regions of the staging buffer (#5572) * Vulkan: Periodically free regions of the staging buffer There was an edge case where a game could submit tens of thousands of small copies over the course of over half a minute to unique fences. This could result in a large stutter when the staging buffer became full and it tried to check and free thousands of completed fences. This became visible with some games and mirrors on Windows, as they don't submit any buffer data via the staging buffer, but may submit copies of the support buffer. This change makes the Vulkan backend check for staging buffer completion on each command buffer submit, so it can't get backed up with 1000s of copies to check. * Add comment --- src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs | 2 +- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs b/src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs index 32ec8c7c6..3a02a28dc 100644 --- a/src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs +++ b/src/Ryujinx.Graphics.Vulkan/StagingBuffer.cs @@ -246,7 +246,7 @@ namespace Ryujinx.Graphics.Vulkan return true; } - private void FreeCompleted() + public void FreeCompleted() { FenceHolder signalledFence = null; while (_pendingCopies.TryPeek(out var pc) && (pc.Fence == signalledFence || pc.Fence.IsSignaled())) diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 3383d728b..7848bc877 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -475,6 +475,9 @@ namespace Ryujinx.Graphics.Vulkan internal void RegisterFlush() { SyncManager.RegisterFlush(); + + // Periodically free unused regions of the staging buffer to avoid doing it all at once. + BufferManager.StagingBuffer.FreeCompleted(); } public PinnedSpan GetBufferData(BufferHandle buffer, int offset, int size)