From f762811af06847957b7ec837d33f248c432ef10a Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 19 Mar 2018 14:53:59 +0100 Subject: [PATCH] [dxvk] Use multiple free lists for physical buffer slices Reduces lock contention and slightly improves performance in games that rely heavily on the buffer renaming mechanism if the lock protecting the original free list was contested. --- src/dxvk/dxvk_buffer.cpp | 25 ++++++++++++++++--------- src/dxvk/dxvk_buffer.h | 7 +++++-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/dxvk/dxvk_buffer.cpp b/src/dxvk/dxvk_buffer.cpp index 52c5eb23..948c6004 100644 --- a/src/dxvk/dxvk_buffer.cpp +++ b/src/dxvk/dxvk_buffer.cpp @@ -31,16 +31,22 @@ namespace dxvk { DxvkPhysicalBufferSlice DxvkBuffer::allocPhysicalSlice() { - std::unique_lock lock(m_mutex); + std::unique_lock freeLock(m_freeMutex); - // If necessary, create a new buffer - // that we'll allocate slices from. - if (m_slices.size() == 0) { + // If no slices are available, swap the two free lists. + if (m_freeSlices.size() == 0) { + std::unique_lock swapLock(m_swapMutex); + std::swap(m_freeSlices, m_nextSlices); + } + + // If there are still no slices available, create a new + // physical buffer and add all slices to the free list. + if (m_freeSlices.size() == 0) { const Rc buffer = this->allocPhysicalBuffer(m_physSliceCount); for (uint32_t i = 0; i < m_physSliceCount; i++) { - m_slices.push_back(buffer->slice( + m_freeSlices.push_back(buffer->slice( m_physSliceStride * i, m_physSliceLength)); } @@ -49,15 +55,16 @@ namespace dxvk { } // Take the first slice from the queue - DxvkPhysicalBufferSlice result = std::move(m_slices.back()); - m_slices.pop_back(); + DxvkPhysicalBufferSlice result = std::move(m_freeSlices.back()); + m_freeSlices.pop_back(); return result; } void DxvkBuffer::freePhysicalSlice(const DxvkPhysicalBufferSlice& slice) { - std::unique_lock lock(m_mutex); - m_slices.push_back(slice); + // Add slice to a separate free list to reduce lock contention. + std::unique_lock swapLock(m_swapMutex); + m_nextSlices.push_back(slice); } diff --git a/src/dxvk/dxvk_buffer.h b/src/dxvk/dxvk_buffer.h index d233667f..50631448 100644 --- a/src/dxvk/dxvk_buffer.h +++ b/src/dxvk/dxvk_buffer.h @@ -140,8 +140,11 @@ namespace dxvk { DxvkPhysicalBufferSlice m_physSlice; uint32_t m_revision = 0; - std::mutex m_mutex; - std::vector m_slices; + std::mutex m_freeMutex; + std::mutex m_swapMutex; + + std::vector m_freeSlices; + std::vector m_nextSlices; VkDeviceSize m_physSliceLength = 0; VkDeviceSize m_physSliceStride = 0;