From 0270b98d2f61fd535ae6e75f159c7d6bf5d88892 Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Thu, 23 Aug 2018 12:18:01 +0200 Subject: [PATCH] Optimized VmaBlockMetadata_Linear::FreeAtOffset to use binary search. Refactored VmaBinaryFindFirstNotLess. --- src/vk_mem_alloc.h | 86 +++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h index 9b3a512..1d42070 100644 --- a/src/vk_mem_alloc.h +++ b/src/vk_mem_alloc.h @@ -3003,8 +3003,8 @@ Cmp should return true if first argument is less than second argument. Returned value is the found element, if present in the collection or place where new element with value (key) should be inserted. */ -template -static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT &key, CmpT cmp) +template +static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT &key, CmpLess cmp) { size_t down = 0, up = (end - beg); while(down < up) @@ -3387,23 +3387,18 @@ bool VmaVectorRemoveSorted(VectorT& vector, const typename VectorT::value_type& return false; } -template -size_t VmaVectorFindSorted(const VectorT& vector, const typename VectorT::value_type& value) +template +IterT VmaVectorFindSorted(const IterT& beg, const IterT& end, const KeyT& value) { CmpLess comparator; - typename VectorT::iterator it = VmaBinaryFindFirstNotLess( - vector.data(), - vector.data() + vector.size(), - value, - comparator); - if(it != vector.size() && !comparator(*it, value) && !comparator(value, *it)) + typename IterT it = VmaBinaryFindFirstNotLess( + beg, end, value, comparator); + if(it == end || + !comparator(*it, value) && !comparator(value, *it)) { - return it - vector.begin(); - } - else - { - return vector.size(); + return it; } + return end; } //////////////////////////////////////////////////////////////////////////////// @@ -4338,6 +4333,22 @@ struct VmaSuballocation VmaSuballocationType type; }; +// Comparator for offsets. +struct VmaSuballocationOffsetLess +{ + bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const + { + return lhs.offset < rhs.offset; + } +}; +struct VmaSuballocationOffsetGreater +{ + bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const + { + return lhs.offset > rhs.offset; + } +}; + typedef VmaList< VmaSuballocation, VmaStlAllocator > VmaSuballocationList; // Cost of one additional allocation lost, as equivalent in bytes. @@ -8754,7 +8765,7 @@ void VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset) } } - // Last allocation in 2-part ring buffer or top of 2nd stack (same logic). + // Last allocation in 2-part ring buffer or top of upper stack (same logic). if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER || m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) { @@ -8781,16 +8792,20 @@ void VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset) } // Item from the middle of 1st vector. - // TODO optimize using binary search. - for(size_t i = m_1stNullItemsBeginCount + 1; i < suballocations1st.size(); ++i) { - VmaSuballocation& currSuballoc = suballocations1st[i]; - if(currSuballoc.offset == offset) + VmaSuballocation refSuballoc; + refSuballoc.offset = offset; + // Rest of members stays uninitialized intentionally for better performance. + SuballocationVectorType::iterator it = VmaVectorFindSorted( + suballocations1st.begin() + m_1stNullItemsBeginCount, + suballocations1st.end(), + refSuballoc); + if(it != suballocations1st.end()) { - currSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE; - currSuballoc.hAllocation = VK_NULL_HANDLE; + it->type = VMA_SUBALLOCATION_TYPE_FREE; + it->hAllocation = VK_NULL_HANDLE; ++m_1stNullItemsMiddleCount; - m_SumFreeSize += currSuballoc.size; + m_SumFreeSize += it->size; CleanupAfterFree(); return; } @@ -8799,19 +8814,20 @@ void VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset) if(m_2ndVectorMode != SECOND_VECTOR_EMPTY) { // Item from the middle of 2nd vector. - // TODO optimize using binary search. Careful when DOUBLE_STACK - suballocations are then sorted in reverse order of offsets. - for(size_t i = 0; i < suballocations2nd.size() - 1; ++i) + VmaSuballocation refSuballoc; + refSuballoc.offset = offset; + // Rest of members stays uninitialized intentionally for better performance. + SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ? + VmaVectorFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc) : + VmaVectorFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc); + if(it != suballocations2nd.end()) { - VmaSuballocation& currSuballoc = suballocations2nd[i]; - if(currSuballoc.offset == offset) - { - currSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE; - currSuballoc.hAllocation = VK_NULL_HANDLE; - ++m_2ndNullItemsCount; - m_SumFreeSize += currSuballoc.size; - CleanupAfterFree(); - return; - } + it->type = VMA_SUBALLOCATION_TYPE_FREE; + it->hAllocation = VK_NULL_HANDLE; + ++m_2ndNullItemsCount; + m_SumFreeSize += it->size; + CleanupAfterFree(); + return; } }