Version 2.0.0-alpha.7. Removed VmaAllocatorCreateInfo::preferredSmallHeapBlockSize. VmaBlockVector::Allocate: New algorithm that allocates 1/8, 1/4, 1/2 of preferred block size as first blocks, to save memory.

This commit is contained in:
Adam Sawicki 2018-02-09 16:52:05 +01:00
parent 6ee1560d4d
commit a82e18346e
10 changed files with 140 additions and 149 deletions

Binary file not shown.

View File

@ -189,9 +189,6 @@ $(function() {
<li>preferredLargeHeapBlockSize
: <a class="el" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">VmaAllocatorCreateInfo</a>
</li>
<li>preferredSmallHeapBlockSize
: <a class="el" href="struct_vma_allocator_create_info.html#ab435423d84d5ab26e2c347c51771f90a">VmaAllocatorCreateInfo</a>
</li>
<li>pUserData
: <a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">VmaAllocationCreateInfo</a>
, <a class="el" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">VmaAllocationInfo</a>

View File

@ -189,9 +189,6 @@ $(function() {
<li>preferredLargeHeapBlockSize
: <a class="el" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">VmaAllocatorCreateInfo</a>
</li>
<li>preferredSmallHeapBlockSize
: <a class="el" href="struct_vma_allocator_create_info.html#ab435423d84d5ab26e2c347c51771f90a">VmaAllocatorCreateInfo</a>
</li>
<li>pUserData
: <a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">VmaAllocationCreateInfo</a>
, <a class="el" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">VmaAllocationInfo</a>

View File

@ -62,7 +62,7 @@ $(function() {
<div class="title">Vulkan Memory Allocator </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><b>Version 2.0.0-alpha.6</b> (2017-11-13)</p>
<div class="textblock"><p><b>Version 2.0.0-alpha.7</b> (2018-02-09)</p>
<p>Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. <br />
License: MIT</p>
<p>Documentation of all members: <a class="el" href="vk__mem__alloc_8h.html">vk_mem_alloc.h</a></p>

View File

@ -12,7 +12,6 @@ var searchData=
['pool',['pool',['../struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150',1,'VmaAllocationCreateInfo']]],
['preferredflags',['preferredFlags',['../struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d',1,'VmaAllocationCreateInfo']]],
['preferredlargeheapblocksize',['preferredLargeHeapBlockSize',['../struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a',1,'VmaAllocatorCreateInfo']]],
['preferredsmallheapblocksize',['preferredSmallHeapBlockSize',['../struct_vma_allocator_create_info.html#ab435423d84d5ab26e2c347c51771f90a',1,'VmaAllocatorCreateInfo']]],
['puserdata',['pUserData',['../struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19',1,'VmaAllocationCreateInfo::pUserData()'],['../struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13',1,'VmaAllocationInfo::pUserData()']]],
['pvulkanfunctions',['pVulkanFunctions',['../struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd',1,'VmaAllocatorCreateInfo']]]
];

View File

@ -10,7 +10,6 @@ var searchData=
['pool',['pool',['../struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150',1,'VmaAllocationCreateInfo']]],
['preferredflags',['preferredFlags',['../struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d',1,'VmaAllocationCreateInfo']]],
['preferredlargeheapblocksize',['preferredLargeHeapBlockSize',['../struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a',1,'VmaAllocatorCreateInfo']]],
['preferredsmallheapblocksize',['preferredSmallHeapBlockSize',['../struct_vma_allocator_create_info.html#ab435423d84d5ab26e2c347c51771f90a',1,'VmaAllocatorCreateInfo']]],
['puserdata',['pUserData',['../struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19',1,'VmaAllocationCreateInfo::pUserData()'],['../struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13',1,'VmaAllocationInfo::pUserData()']]],
['pvulkanfunctions',['pVulkanFunctions',['../struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd',1,'VmaAllocatorCreateInfo']]]
];

View File

@ -73,8 +73,7 @@ $(function() {
<tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">pHeapSizeLimit</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">physicalDevice</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">preferredLargeHeapBlockSize</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#ab435423d84d5ab26e2c347c51771f90a">preferredSmallHeapBlockSize</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd">pVulkanFunctions</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd">pVulkanFunctions</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
</table></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>

View File

@ -83,11 +83,8 @@ Public Attributes</h2></td></tr>
<tr class="memdesc:ad924ddd77b04039c88d0c09b0ffcd500"><td class="mdescLeft">&#160;</td><td class="mdescRight">Vulkan device. <a href="#ad924ddd77b04039c88d0c09b0ffcd500">More...</a><br /></td></tr>
<tr class="separator:ad924ddd77b04039c88d0c09b0ffcd500"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a8e4714298e3121cdd8b214a1ae7a637a"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">preferredLargeHeapBlockSize</a></td></tr>
<tr class="memdesc:a8e4714298e3121cdd8b214a1ae7a637a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Preferred size of a single <code>VkDeviceMemory</code> block to be allocated from large heaps. <a href="#a8e4714298e3121cdd8b214a1ae7a637a">More...</a><br /></td></tr>
<tr class="memdesc:a8e4714298e3121cdd8b214a1ae7a637a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Preferred size of a single <code>VkDeviceMemory</code> block to be allocated from large heaps &gt; 1 GiB. <a href="#a8e4714298e3121cdd8b214a1ae7a637a">More...</a><br /></td></tr>
<tr class="separator:a8e4714298e3121cdd8b214a1ae7a637a"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ab435423d84d5ab26e2c347c51771f90a"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#ab435423d84d5ab26e2c347c51771f90a">preferredSmallHeapBlockSize</a></td></tr>
<tr class="memdesc:ab435423d84d5ab26e2c347c51771f90a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Preferred size of a single <code>VkDeviceMemory</code> block to be allocated from small heaps &lt;= 512 MiB. <a href="#ab435423d84d5ab26e2c347c51771f90a">More...</a><br /></td></tr>
<tr class="separator:ab435423d84d5ab26e2c347c51771f90a"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a6e409087e3be55400d0e4ccbe43c608d"><td class="memItemLeft" align="right" valign="top">const VkAllocationCallbacks *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d">pAllocationCallbacks</a></td></tr>
<tr class="memdesc:a6e409087e3be55400d0e4ccbe43c608d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Custom CPU memory allocation callbacks. <a href="#a6e409087e3be55400d0e4ccbe43c608d">More...</a><br /></td></tr>
<tr class="separator:a6e409087e3be55400d0e4ccbe43c608d"><td class="memSeparator" colspan="2">&#160;</td></tr>
@ -246,26 +243,9 @@ Public Attributes</h2></td></tr>
</table>
</div><div class="memdoc">
<p>Preferred size of a single <code>VkDeviceMemory</code> block to be allocated from large heaps. </p>
<p>Preferred size of a single <code>VkDeviceMemory</code> block to be allocated from large heaps &gt; 1 GiB. </p>
<p>Set to 0 to use default, which is currently 256 MiB. </p>
</div>
</div>
<a id="ab435423d84d5ab26e2c347c51771f90a"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ab435423d84d5ab26e2c347c51771f90a">&#9670;&nbsp;</a></span>preferredSmallHeapBlockSize</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">VkDeviceSize VmaAllocatorCreateInfo::preferredSmallHeapBlockSize</td>
</tr>
</table>
</div><div class="memdoc">
<p>Preferred size of a single <code>VkDeviceMemory</code> block to be allocated from small heaps &lt;= 512 MiB. </p>
<p>Set to 0 to use default, which is currently 64 MiB. </p>
</div>
</div>
<a id="a3dc197be3227da7338b1643f70db36bd"></a>

File diff suppressed because one or more lines are too long

View File

@ -29,7 +29,7 @@ extern "C" {
/** \mainpage Vulkan Memory Allocator
<b>Version 2.0.0-alpha.6</b> (2017-11-13)
<b>Version 2.0.0-alpha.7</b> (2018-02-09)
Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. \n
License: MIT
@ -784,12 +784,9 @@ typedef struct VmaAllocatorCreateInfo
/// Vulkan device.
/** It must be valid throughout whole lifetime of created allocator. */
VkDevice device;
/// Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps.
/// Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps > 1 GiB.
/** Set to 0 to use default, which is currently 256 MiB. */
VkDeviceSize preferredLargeHeapBlockSize;
/// Preferred size of a single `VkDeviceMemory` block to be allocated from small heaps <= 512 MiB.
/** Set to 0 to use default, which is currently 64 MiB. */
VkDeviceSize preferredSmallHeapBlockSize;
/// Custom CPU memory allocation callbacks.
/** Optional, can be null. When specified, will also be used for all CPU-side memory allocations. */
const VkAllocationCallbacks* pAllocationCallbacks;
@ -1858,17 +1855,12 @@ If providing your own implementation, you need to implement a subset of std::ato
#ifndef VMA_SMALL_HEAP_MAX_SIZE
/// Maximum size of a memory heap in Vulkan to consider it "small".
#define VMA_SMALL_HEAP_MAX_SIZE (512 * 1024 * 1024)
#define VMA_SMALL_HEAP_MAX_SIZE (1024ull * 1024 * 1024)
#endif
#ifndef VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE
/// Default size of a block allocated as single VkDeviceMemory from a "large" heap.
#define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256 * 1024 * 1024)
#endif
#ifndef VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE
/// Default size of a block allocated as single VkDeviceMemory from a "small" heap.
#define VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE (64 * 1024 * 1024)
#define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256ull * 1024 * 1024)
#endif
static const uint32_t VMA_FRAME_INDEX_LOST = UINT32_MAX;
@ -3660,6 +3652,8 @@ private:
bool m_HasEmptyBlock;
VmaDefragmentator* m_pDefragmentator;
size_t CalcMaxBlockSize() const;
// Finds and removes given block from vector.
void Remove(VmaDeviceMemoryBlock* pBlock);
@ -3929,7 +3923,6 @@ struct VmaAllocator_T
private:
VkDeviceSize m_PreferredLargeHeapBlockSize;
VkDeviceSize m_PreferredSmallHeapBlockSize;
VkPhysicalDevice m_PhysicalDevice;
VMA_ATOMIC_UINT32 m_CurrentFrameIndex;
@ -5959,30 +5952,49 @@ VkResult VmaBlockVector::Allocate(
// 2. Try to create new block.
if(canCreateNewBlock)
{
// 2.1. Start with full preferredBlockSize.
VkDeviceSize blockSize = m_PreferredBlockSize;
size_t newBlockIndex = 0;
VkResult res = CreateBlock(blockSize, &newBlockIndex);
// Calculate optimal size for new block.
VkDeviceSize newBlockSize = m_PreferredBlockSize;
uint32_t newBlockSizeShift = 0;
const uint32_t NEW_BLOCK_SIZE_SHIFT_MAX = 3;
// Allocating blocks of other sizes is allowed only in default pools.
// In custom pools block size is fixed.
if(res < 0 && m_IsCustomPool == false)
if(m_IsCustomPool == false)
{
// 2.2. Try half the size.
blockSize /= 2;
if(blockSize >= vkMemReq.size)
// Allocate 1/8, 1/4, 1/2 as first blocks.
const VkDeviceSize maxExistingBlockSize = CalcMaxBlockSize();
for(uint32_t i = 0; i < NEW_BLOCK_SIZE_SHIFT_MAX; ++i)
{
res = CreateBlock(blockSize, &newBlockIndex);
if(res < 0)
const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
if(smallerNewBlockSize > maxExistingBlockSize && smallerNewBlockSize >= vkMemReq.size * 2)
{
// 2.3. Try quarter the size.
blockSize /= 2;
if(blockSize >= vkMemReq.size)
{
res = CreateBlock(blockSize, &newBlockIndex);
newBlockSize = smallerNewBlockSize;
++newBlockSizeShift;
}
}
}
size_t newBlockIndex = 0;
VkResult res = CreateBlock(newBlockSize, &newBlockIndex);
// Allocation of this size failed? Try 1/2, 1/4, 1/8 of m_PreferredBlockSize.
if(m_IsCustomPool == false)
{
while(res < 0 && newBlockSizeShift < NEW_BLOCK_SIZE_SHIFT_MAX)
{
const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
if(smallerNewBlockSize >= vkMemReq.size)
{
newBlockSize = smallerNewBlockSize;
++newBlockSizeShift;
res = CreateBlock(newBlockSize, &newBlockIndex);
}
else
{
break;
}
}
}
if(res == VK_SUCCESS)
{
VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex];
@ -6183,6 +6195,20 @@ void VmaBlockVector::Free(
}
}
size_t VmaBlockVector::CalcMaxBlockSize() const
{
size_t result = 0;
for(size_t i = m_Blocks.size(); i--; )
{
result = VMA_MAX(result, m_Blocks[i]->m_Metadata.GetSize());
if(result >= m_PreferredBlockSize)
{
break;
}
}
return result;
}
void VmaBlockVector::Remove(VmaDeviceMemoryBlock* pBlock)
{
for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
@ -6707,7 +6733,6 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
m_AllocationCallbacks(pCreateInfo->pAllocationCallbacks ?
*pCreateInfo->pAllocationCallbacks : VmaEmptyAllocationCallbacks),
m_PreferredLargeHeapBlockSize(0),
m_PreferredSmallHeapBlockSize(0),
m_PhysicalDevice(pCreateInfo->physicalDevice),
m_CurrentFrameIndex(0),
m_Pools(VmaStlAllocator<VmaPool>(GetAllocationCallbacks()))
@ -6739,8 +6764,6 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
m_PreferredLargeHeapBlockSize = (pCreateInfo->preferredLargeHeapBlockSize != 0) ?
pCreateInfo->preferredLargeHeapBlockSize : static_cast<VkDeviceSize>(VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE);
m_PreferredSmallHeapBlockSize = (pCreateInfo->preferredSmallHeapBlockSize != 0) ?
pCreateInfo->preferredSmallHeapBlockSize : static_cast<VkDeviceSize>(VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE);
if(pCreateInfo->pHeapSizeLimit != VMA_NULL)
{
@ -6866,10 +6889,8 @@ VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex)
{
const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size;
const bool isSmallHeap = heapSize <= VMA_SMALL_HEAP_MAX_SIZE ||
// HOST_CACHED memory type is treated as small despite it has full size of CPU memory heap, because we usually don't use much of it.
(m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0;
return isSmallHeap ? m_PreferredSmallHeapBlockSize : m_PreferredLargeHeapBlockSize;
const bool isSmallHeap = heapSize <= VMA_SMALL_HEAP_MAX_SIZE;
return isSmallHeap ? (heapSize / 8) : m_PreferredLargeHeapBlockSize;
}
VkResult VmaAllocator_T::AllocateMemoryOfType(