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<byte>((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<T>(int offset, ReadOnlySpan<T> data) where T : unmanaged
+        {
+            SetDataUnchecked(offset, MemoryMarshal.AsBytes(data));
+        }
+
         public void SetDataInline(CommandBufferScoped cbs, Action endRenderPass, int dstOffset, ReadOnlySpan<byte> 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<ulong, BufferHandle>(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<float> 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<float> 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<float> 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<float> 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<float>(bufferHandle, 0, region);
+            buffer.Holder.SetDataUnchecked<float>(buffer.Offset, region);
 
-            _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, RegionBufferSize)) });
+            _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, buffer.Range) });
 
             Span<Viewport> 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<float>(bufferHandle, 0, region);
+            buffer.Holder.SetDataUnchecked<float>(buffer.Offset, region);
 
-            _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, RegionBufferSize)) });
+            _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, buffer.Range) });
 
             Span<Viewport> 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<Viewport> 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<float>(bufferHandle, 0, stackalloc float[] { depthValue });
+            buffer.Holder.SetDataUnchecked<float>(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<Viewport> 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<int>(bufferHandle, 0, shaderParams);
+                buffer.Holder.SetDataUnchecked<int>(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<Auto<DisposableBuffer>> sbRanges = new Auto<DisposableBuffer>[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<int> shaderParams = stackalloc int[sizeof(int)];
+            Span<int> 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<int>(bufferHandle, 0, shaderParams);
+            buffer.Holder.SetDataUnchecked<int>(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<int>(bufferHandle, 0, shaderParams);
+            buffer.Holder.SetDataUnchecked<int>(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<int>(bufferHandle, 0, shaderParams);
+            buffer.Holder.SetDataUnchecked<int>(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<int>(patternBufferHandle, 0, shaderParams);
+            patternBuffer.SetDataUnchecked<int>(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<int>(bufferHandle, 0, shaderParams);
+            buffer.Holder.SetDataUnchecked<int>(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<Auto<DisposableBuffer>> sbRanges = new Auto<DisposableBuffer>[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<PendingCopy>();
             _freeSize = BufferSize;
+            _resourceAlignment = (int)gd.Capabilities.MinResourceAlignment;
         }
 
         public void PushData(CommandBufferPool cbp, CommandBufferScoped? cbs, Action endRenderPass, BufferHolder dst, int dstOffset, ReadOnlySpan<byte> 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.
         /// </summary>
         /// <param name="cbs">Command buffer to reserve the data on</param>
-        /// <param name="data">The data to upload</param>
+        /// <param name="size">The minimum size the reserved data requires</param>
         /// <param name="alignment">The required alignment for the buffer offset</param>
         /// <returns>The reserved range of the staging buffer</returns>
         public unsafe StagingBufferReserved? TryReserveData(CommandBufferScoped cbs, int size, int alignment)
@@ -223,6 +228,18 @@ namespace Ryujinx.Graphics.Vulkan
             return ReserveDataImpl(cbs, size, alignment);
         }
 
+        /// <summary>
+        /// Reserve a range on the staging buffer for the current command buffer and upload data to it.
+        /// Uses the most permissive byte alignment.
+        /// </summary>
+        /// <param name="cbs">Command buffer to reserve the data on</param>
+        /// <param name="size">The minimum size the reserved data requires</param>
+        /// <returns>The reserved range of the staging buffer</returns>
+        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))
                 {