1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-18 02:52:10 +01:00

[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.
This commit is contained in:
Philip Rebohle 2018-03-19 14:53:59 +01:00
parent c6251d28fc
commit f762811af0
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 21 additions and 11 deletions

View File

@ -31,16 +31,22 @@ namespace dxvk {
DxvkPhysicalBufferSlice DxvkBuffer::allocPhysicalSlice() {
std::unique_lock<std::mutex> lock(m_mutex);
std::unique_lock<std::mutex> 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<std::mutex> 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<DxvkPhysicalBuffer> 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<std::mutex> lock(m_mutex);
m_slices.push_back(slice);
// Add slice to a separate free list to reduce lock contention.
std::unique_lock<std::mutex> swapLock(m_swapMutex);
m_nextSlices.push_back(slice);
}

View File

@ -140,8 +140,11 @@ namespace dxvk {
DxvkPhysicalBufferSlice m_physSlice;
uint32_t m_revision = 0;
std::mutex m_mutex;
std::vector<DxvkPhysicalBufferSlice> m_slices;
std::mutex m_freeMutex;
std::mutex m_swapMutex;
std::vector<DxvkPhysicalBufferSlice> m_freeSlices;
std::vector<DxvkPhysicalBufferSlice> m_nextSlices;
VkDeviceSize m_physSliceLength = 0;
VkDeviceSize m_physSliceStride = 0;