From e868f829b5bffaca080ef71def4312cb1044172a Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 26 Oct 2019 14:16:33 +0200 Subject: [PATCH] [dxvk] Pad buffers more tightly This will allow for smaller buffers to be laid out more efficiently. --- src/dxvk/dxvk_buffer.cpp | 60 +++++++++++++++++++++++++++++++++------- src/dxvk/dxvk_buffer.h | 9 ++++-- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/dxvk/dxvk_buffer.cpp b/src/dxvk/dxvk_buffer.cpp index 7282894ad..af590136c 100644 --- a/src/dxvk/dxvk_buffer.cpp +++ b/src/dxvk/dxvk_buffer.cpp @@ -12,10 +12,12 @@ namespace dxvk { m_info (createInfo), m_memAlloc (&memAlloc), m_memFlags (memFlags) { - // Align slices to 256 bytes, which guarantees that - // we don't violate any Vulkan alignment requirements + // Align slices so that we don't violate any alignment + // requirements imposed by the Vulkan device/driver + VkDeviceSize sliceAlignment = computeSliceAlignment(); m_physSliceLength = createInfo.size; - m_physSliceStride = align(createInfo.size, 256); + m_physSliceStride = align(createInfo.size, sliceAlignment); + m_physSliceCount = std::max(1, 256 / m_physSliceStride); // Limit size of multi-slice buffers to reduce fragmentation constexpr VkDeviceSize MaxBufferSize = 4 << 20; @@ -23,14 +25,24 @@ namespace dxvk { m_physSliceMaxCount = MaxBufferSize >= m_physSliceStride ? MaxBufferSize / m_physSliceStride : 1; - - // Allocate a single buffer slice - m_buffer = allocBuffer(1); - m_physSlice.handle = m_buffer.buffer; - m_physSlice.offset = 0; - m_physSlice.length = m_physSliceLength; - m_physSlice.mapPtr = m_buffer.memory.mapPtr(0); + // Allocate the initial set of buffer slices + m_buffer = allocBuffer(m_physSliceCount); + + DxvkBufferSliceHandle slice; + slice.handle = m_buffer.buffer; + slice.offset = 0; + slice.length = m_physSliceLength; + slice.mapPtr = m_buffer.memory.mapPtr(0); + + m_physSlice = slice; + + // Push extra slices to the free list + for (uint32_t i = 1; i < m_physSliceCount; i++) { + slice.offset = m_physSliceStride * i; + slice.mapPtr = m_buffer.memory.mapPtr(slice.offset); + m_freeSlices.push_back(slice); + } } @@ -109,6 +121,34 @@ namespace dxvk { } + VkDeviceSize DxvkBuffer::computeSliceAlignment() const { + const auto& devInfo = m_device->properties().core.properties; + + VkDeviceSize result = sizeof(uint32_t); + + if (m_info.usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) + result = std::max(result, devInfo.limits.minUniformBufferOffsetAlignment); + + if (m_info.usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + result = std::max(result, devInfo.limits.minStorageBufferOffsetAlignment); + + if (m_info.usage & (VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) + result = std::max(result, devInfo.limits.minTexelBufferOffsetAlignment); + + if (m_info.usage & (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) + && m_info.size > (devInfo.limits.optimalBufferCopyOffsetAlignment / 2)) + result = std::max(result, devInfo.limits.optimalBufferCopyOffsetAlignment); + + if (m_memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { + result = std::max(result, devInfo.limits.nonCoherentAtomSize); + result = std::max(result, VkDeviceSize(64)); + } + + return result; + } + + + DxvkBufferView::DxvkBufferView( const Rc& vkd, diff --git a/src/dxvk/dxvk_buffer.h b/src/dxvk/dxvk_buffer.h index c180f124e..70bea16eb 100644 --- a/src/dxvk/dxvk_buffer.h +++ b/src/dxvk/dxvk_buffer.h @@ -247,11 +247,12 @@ namespace dxvk { std::unique_lock swapLock(m_swapMutex); DxvkBufferHandle handle = allocBuffer(m_physSliceCount); + DxvkBufferSliceHandle slice; + slice.handle = handle.buffer; + slice.length = m_physSliceLength; + for (uint32_t i = 0; i < m_physSliceCount; i++) { - DxvkBufferSliceHandle slice; - slice.handle = handle.buffer; slice.offset = m_physSliceStride * i; - slice.length = m_physSliceLength; slice.mapPtr = handle.memory.mapPtr(slice.offset); m_freeSlices.push_back(slice); } @@ -306,6 +307,8 @@ namespace dxvk { DxvkBufferHandle allocBuffer( VkDeviceSize sliceCount) const; + + VkDeviceSize computeSliceAlignment() const; };