diff --git a/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs b/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs index 8927d2264..c2c2ba6f2 100644 --- a/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs +++ b/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using VkBuffer = Silk.NET.Vulkan.Buffer; namespace Ryujinx.Graphics.Vulkan @@ -61,29 +62,65 @@ namespace Ryujinx.Graphics.Vulkan { if (_count != 0) { - for (int i = 0; i < _count; i++) - { - _buffers[i] = _bufferAutos[i].Get(cbs, _bufferOffsetsForGet[i], _bufferSizesForGet[i]).Value; - _bufferAutos[i] = null; - } - - if (_gd.Capabilities.SupportsExtendedDynamicState) - { - _gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2( - cbs.CommandBuffer, - _baseBinding, - _count, - _buffers.Pointer, - _offsets.Pointer, - _sizes.Pointer, - _strides.Pointer); - } - else - { - _gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, _baseBinding, _count, _buffers.Pointer, _offsets.Pointer); - } - + int count = (int)_count; + uint baseBinding = _baseBinding; _count = 0; + + Auto[] autos = ArrayPool>.Shared.Rent(count); + Span getOffsets = stackalloc int[Constants.MaxVertexBuffers]; + Span getSizes = stackalloc int[Constants.MaxVertexBuffers]; + Span offsets = stackalloc ulong[Constants.MaxVertexBuffers]; + Span sizes = stackalloc ulong[Constants.MaxVertexBuffers]; + Span strides = stackalloc ulong[Constants.MaxVertexBuffers]; + Span buffers = stackalloc VkBuffer[Constants.MaxVertexBuffers]; + + for (int i = 0; i < count; i++) + { + autos[i] = _bufferAutos[i]; + _bufferAutos[i] = null; + getOffsets[i] = _bufferOffsetsForGet[i]; + getSizes[i] = _bufferSizesForGet[i]; + offsets[i] = _offsets[i]; + sizes[i] = _sizes[i]; + strides[i] = _strides[i]; + } + + try + { + for (int i = 0; i < count; i++) + { + buffers[i] = autos[i].Get(cbs, getOffsets[i], getSizes[i]).Value; + autos[i] = null; + } + + for (int i = 0; i < count; i++) + { + _buffers[i] = buffers[i]; + _offsets[i] = offsets[i]; + _sizes[i] = sizes[i]; + _strides[i] = strides[i]; + } + + if (_gd.Capabilities.SupportsExtendedDynamicState) + { + _gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2( + cbs.CommandBuffer, + baseBinding, + (uint)count, + _buffers.Pointer, + _offsets.Pointer, + _sizes.Pointer, + _strides.Pointer); + } + else + { + _gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, baseBinding, (uint)count, _buffers.Pointer, _offsets.Pointer); + } + } + finally + { + ArrayPool>.Shared.Return(autos, clearArray: true); + } } }