New API for defragmentation. COMPATIBILITY BREAKING!

See structure VmaDefragmentationInfo, VmaDefragmentationMove, VmaDefragmentationPassMoveInfo, VmaDefragmentationStats, function vmaBeginDefragmentation, vmaEndDefragmentation, vmaBeginDefragmentationPass, vmaEndDefragmentationPass.

Switched to TLSF as the default algorithm - in default pools, custom pools, virtual blocks. Removed generic and buddy algorithm. Removed flags: VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT, VMA_POOL_CREATE_TLSF_ALGORITHM_BIT, VMA_VIRTUAL_BLOCK_CREATE_BUDDY_ALGORITHM_BIT, VMA_VIRTUAL_BLOCK_CREATE_TLSF_ALGORITHM_BIT.

Updated and regenerated documentation.
This commit is contained in:
Adam Sawicki 2022-02-22 23:38:19 +01:00
parent 9104ef3d45
commit 88510e9801
67 changed files with 3403 additions and 4413 deletions

View file

@ -70,164 +70,55 @@ $(function() {
</div><!--header-->
<div class="contents">
<div class="textblock"><p >Interleaved allocations and deallocations of many objects of varying size can cause fragmentation over time, which can lead to a situation where the library is unable to find a continuous range of free memory for a new allocation despite there is enough free space, just scattered across many small free ranges between existing allocations.</p>
<p >To mitigate this problem, you can use defragmentation feature: structure <a class="el" href="struct_vma_defragmentation_info2.html" title="Parameters for defragmentation.">VmaDefragmentationInfo2</a>, function <a class="el" href="group__group__alloc.html#ga36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a>, <a class="el" href="group__group__alloc.html#ga8774e20e91e245aae959ba63efa15dd2" title="Ends defragmentation process.">vmaDefragmentationEnd()</a>. Given set of allocations, this function can move them to compact used memory, ensure more continuous free space and possibly also free some <code>VkDeviceMemory</code> blocks.</p>
<p >What the defragmentation does is:</p>
<ul>
<li>Updates <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> objects to point to new <code>VkDeviceMemory</code> and offset. After allocation has been moved, its <a class="el" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67" title="Handle to Vulkan memory object.">VmaAllocationInfo::deviceMemory</a> and/or <a class="el" href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268" title="Offset in VkDeviceMemory object to the beginning of this allocation, in bytes. (deviceMemory,...">VmaAllocationInfo::offset</a> changes. You must query them again using <a class="el" href="group__group__alloc.html#ga86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation.">vmaGetAllocationInfo()</a> if you need them.</li>
<li>Moves actual data in memory.</li>
</ul>
<p >What it doesn't do, so you need to do it yourself:</p>
<ul>
<li>Recreate buffers and images that were bound to allocations that were defragmented and bind them with their new places in memory. You must use <code>vkDestroyBuffer()</code>, <code>vkDestroyImage()</code>, <code>vkCreateBuffer()</code>, <code>vkCreateImage()</code>, <a class="el" href="group__group__alloc.html#ga6b0929b914b60cf2d45cac4bf3547470" title="Binds buffer to allocation.">vmaBindBufferMemory()</a>, <a class="el" href="group__group__alloc.html#ga3d3ca45799923aa5d138e9e5f9eb2da5" title="Binds image to allocation.">vmaBindImageMemory()</a> for that purpose and NOT <a class="el" href="group__group__alloc.html#ga0d9f4e4ba5bf9aab1f1c746387753d77" title="Destroys Vulkan buffer and frees allocated memory.">vmaDestroyBuffer()</a>, <a class="el" href="group__group__alloc.html#gae50d2cb3b4a3bfd4dd40987234e50e7e" title="Destroys Vulkan image and frees allocated memory.">vmaDestroyImage()</a>, <a class="el" href="group__group__alloc.html#gac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>, <a class="el" href="group__group__alloc.html#ga02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a>, because you don't need to destroy or create allocation objects!</li>
<li>Recreate views and update descriptors that point to these buffers and images.</li>
</ul>
<h1><a class="anchor" id="defragmentation_cpu"></a>
Defragmenting CPU memory</h1>
<p >Following example demonstrates how you can run defragmentation on CPU. Only allocations created in memory types that are <code>HOST_VISIBLE</code> can be defragmented. Others are ignored.</p>
<p >The way it works is:</p>
<ul>
<li>It temporarily maps entire memory blocks when necessary.</li>
<li>It moves data using <code>memmove()</code> function.</li>
</ul>
<div class="fragment"><div class="line"><span class="comment">// Given following variables already initialized:</span></div>
<div class="line">VkDevice device;</div>
<div class="line"><a class="code hl_struct" href="struct_vma_allocator.html">VmaAllocator</a> allocator;</div>
<div class="line">std::vector&lt;VkBuffer&gt; buffers;</div>
<div class="line">std::vector&lt;VmaAllocation&gt; allocations;</div>
<div class="line"> </div>
<div class="line"> </div>
<div class="line"><span class="keyword">const</span> uint32_t allocCount = (uint32_t)allocations.size();</div>
<div class="line">std::vector&lt;VkBool32&gt; allocationsChanged(allocCount);</div>
<div class="line"> </div>
<div class="line"><a class="code hl_struct" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a> defragInfo = {};</div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a> = allocCount;</div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info2.html#ab6d288f29d028156cf73542d630a2e32">pAllocations</a> = allocations.data();</div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">pAllocationsChanged</a> = allocationsChanged.data();</div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">maxCpuBytesToMove</a> = VK_WHOLE_SIZE; <span class="comment">// No limit.</span></div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">maxCpuAllocationsToMove</a> = UINT32_MAX; <span class="comment">// No limit.</span></div>
<div class="line"> </div>
<div class="line"><a class="code hl_struct" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> defragCtx;</div>
<div class="line"><a class="code hl_function" href="group__group__alloc.html#ga36ba776fd7fd5cb1e9359fdc0d8e6e8a">vmaDefragmentationBegin</a>(allocator, &amp;defragInfo, <span class="keyword">nullptr</span>, &amp;defragCtx);</div>
<div class="line"><a class="code hl_function" href="group__group__alloc.html#ga8774e20e91e245aae959ba63efa15dd2">vmaDefragmentationEnd</a>(allocator, defragCtx);</div>
<div class="line"> </div>
<div class="line"><span class="keywordflow">for</span>(uint32_t i = 0; i &lt; allocCount; ++i)</div>
<div class="line">{</div>
<div class="line"> <span class="keywordflow">if</span>(allocationsChanged[i])</div>
<div class="line"> {</div>
<div class="line"> <span class="comment">// Destroy buffer that is immutably bound to memory region which is no longer valid.</span></div>
<div class="line"> vkDestroyBuffer(device, buffers[i], <span class="keyword">nullptr</span>);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Create new buffer with same parameters.</span></div>
<div class="line"> VkBufferCreateInfo bufferInfo = ...;</div>
<div class="line"> vkCreateBuffer(device, &amp;bufferInfo, <span class="keyword">nullptr</span>, &amp;buffers[i]);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning.</span></div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Bind new buffer to new memory region. Data contained in it is already moved.</span></div>
<div class="line"> <a class="code hl_struct" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div>
<div class="line"> <a class="code hl_function" href="group__group__alloc.html#ga86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a>(allocator, allocations[i], &amp;allocInfo);</div>
<div class="line"> <a class="code hl_function" href="group__group__alloc.html#ga6b0929b914b60cf2d45cac4bf3547470">vmaBindBufferMemory</a>(allocator, allocations[i], buffers[i]);</div>
<div class="line"> }</div>
<div class="line">}</div>
<div class="ttc" id="agroup__group__alloc_html_ga36ba776fd7fd5cb1e9359fdc0d8e6e8a"><div class="ttname"><a href="group__group__alloc.html#ga36ba776fd7fd5cb1e9359fdc0d8e6e8a">vmaDefragmentationBegin</a></div><div class="ttdeci">VkResult vmaDefragmentationBegin(VmaAllocator allocator, const VmaDefragmentationInfo2 *pInfo, VmaDefragmentationStats *pStats, VmaDefragmentationContext *pContext)</div><div class="ttdoc">Begins defragmentation process.</div></div>
<div class="ttc" id="agroup__group__alloc_html_ga6b0929b914b60cf2d45cac4bf3547470"><div class="ttname"><a href="group__group__alloc.html#ga6b0929b914b60cf2d45cac4bf3547470">vmaBindBufferMemory</a></div><div class="ttdeci">VkResult vmaBindBufferMemory(VmaAllocator allocator, VmaAllocation allocation, VkBuffer buffer)</div><div class="ttdoc">Binds buffer to allocation.</div></div>
<div class="ttc" id="agroup__group__alloc_html_ga86dd08aba8633bfa4ad0df2e76481d8b"><div class="ttname"><a href="group__group__alloc.html#ga86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a></div><div class="ttdeci">void vmaGetAllocationInfo(VmaAllocator allocator, VmaAllocation allocation, VmaAllocationInfo *pAllocationInfo)</div><div class="ttdoc">Returns current information about specified allocation.</div></div>
<div class="ttc" id="agroup__group__alloc_html_ga8774e20e91e245aae959ba63efa15dd2"><div class="ttname"><a href="group__group__alloc.html#ga8774e20e91e245aae959ba63efa15dd2">vmaDefragmentationEnd</a></div><div class="ttdeci">VkResult vmaDefragmentationEnd(VmaAllocator allocator, VmaDefragmentationContext context)</div><div class="ttdoc">Ends defragmentation process.</div></div>
<div class="ttc" id="astruct_vma_allocation_info_html"><div class="ttname"><a href="struct_vma_allocation_info.html">VmaAllocationInfo</a></div><div class="ttdoc">Parameters of VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1333</div></div>
<div class="ttc" id="astruct_vma_allocator_html"><div class="ttname"><a href="struct_vma_allocator.html">VmaAllocator</a></div><div class="ttdoc">Represents main object of this library initialized.</div></div>
<div class="ttc" id="astruct_vma_defragmentation_context_html"><div class="ttname"><a href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a></div><div class="ttdoc">Represents Opaque object that represents started defragmentation process.</div></div>
<div class="ttc" id="astruct_vma_defragmentation_info2_html"><div class="ttname"><a href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></div><div class="ttdoc">Parameters for defragmentation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1388</div></div>
<div class="ttc" id="astruct_vma_defragmentation_info2_html_a3cf86ab32c1da779b4923d301a3056ba"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">VmaDefragmentationInfo2::allocationCount</a></div><div class="ttdeci">uint32_t allocationCount</div><div class="ttdoc">Number of allocations in pAllocations array.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1394</div></div>
<div class="ttc" id="astruct_vma_defragmentation_info2_html_a76d51a644dc7f5405d0cdd0025ecd0cc"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">VmaDefragmentationInfo2::pAllocationsChanged</a></div><div class="ttdeci">VkBool32 * pAllocationsChanged</div><div class="ttdoc">Optional, output. Pointer to array that will be filled with information whether the allocation at cer...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1408</div></div>
<div class="ttc" id="astruct_vma_defragmentation_info2_html_a94c2c7223d52878445a8cccce396b671"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">VmaDefragmentationInfo2::maxCpuAllocationsToMove</a></div><div class="ttdeci">uint32_t maxCpuAllocationsToMove</div><div class="ttdoc">Maximum number of allocations that can be moved to a different place using transfers on CPU side,...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1437</div></div>
<div class="ttc" id="astruct_vma_defragmentation_info2_html_ab6d288f29d028156cf73542d630a2e32"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#ab6d288f29d028156cf73542d630a2e32">VmaDefragmentationInfo2::pAllocations</a></div><div class="ttdeci">const VmaAllocation * pAllocations</div><div class="ttdoc">Pointer to array of allocations that can be defragmented.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1402</div></div>
<div class="ttc" id="astruct_vma_defragmentation_info2_html_af78e1ea40c22d85137b65f6b384a4d0a"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">VmaDefragmentationInfo2::maxCpuBytesToMove</a></div><div class="ttdeci">VkDeviceSize maxCpuBytesToMove</div><div class="ttdoc">Maximum total numbers of bytes that can be copied while moving allocations to different places using ...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1432</div></div>
</div><!-- fragment --><p >Setting <a class="el" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc" title="Optional, output. Pointer to array that will be filled with information whether the allocation at cer...">VmaDefragmentationInfo2::pAllocationsChanged</a> is optional. This output array tells whether particular allocation in <a class="el" href="struct_vma_defragmentation_info2.html#ab6d288f29d028156cf73542d630a2e32" title="Pointer to array of allocations that can be defragmented.">VmaDefragmentationInfo2::pAllocations</a> at the same index has been modified during defragmentation. You can pass null, but you then need to query every allocation passed to defragmentation for new parameters using <a class="el" href="group__group__alloc.html#ga86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation.">vmaGetAllocationInfo()</a> if you might need to recreate and rebind a buffer or image associated with it.</p>
<p >If you use <a class="el" href="choosing_memory_type.html#choosing_memory_type_custom_memory_pools">Custom memory pools</a>, you can fill <a class="el" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d" title="Numer of pools in pPools array.">VmaDefragmentationInfo2::poolCount</a> and <a class="el" href="struct_vma_defragmentation_info2.html#a3c9c6aa5c97d5670f8e362b3a6f3029b" title="Either null or pointer to array of pools to be defragmented.">VmaDefragmentationInfo2::pPools</a> instead of <a class="el" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba" title="Number of allocations in pAllocations array.">VmaDefragmentationInfo2::allocationCount</a> and <a class="el" href="struct_vma_defragmentation_info2.html#ab6d288f29d028156cf73542d630a2e32" title="Pointer to array of allocations that can be defragmented.">VmaDefragmentationInfo2::pAllocations</a> to defragment all allocations in given pools. You cannot use <a class="el" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc" title="Optional, output. Pointer to array that will be filled with information whether the allocation at cer...">VmaDefragmentationInfo2::pAllocationsChanged</a> in that case. You can also combine both methods.</p>
<h1><a class="anchor" id="defragmentation_gpu"></a>
Defragmenting GPU memory</h1>
<p >It is also possible to defragment allocations created in memory types that are not <code>HOST_VISIBLE</code>. To do that, you need to pass a command buffer that meets requirements as described in <a class="el" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd" title="Optional. Command buffer where GPU copy commands will be posted.">VmaDefragmentationInfo2::commandBuffer</a>. The way it works is:</p>
<ul>
<li>It creates temporary buffers and binds them to entire memory blocks when necessary.</li>
<li>It issues <code>vkCmdCopyBuffer()</code> to passed command buffer.</li>
</ul>
<p >To mitigate this problem, you can use defragmentation feature. It doesn't happen automatically thought and needs your cooperation, because VMA is a low level library that only allocates memory. It cannot recreate buffers and images in a new place as it doesn't remember the contents of <code>VkBufferCreateInfo</code> / <code>VkImageCreateInfo</code> structures. It cannot copy their contents as it doesn't record any commands to a command buffer.</p>
<p >Example:</p>
<div class="fragment"><div class="line"><span class="comment">// Given following variables already initialized:</span></div>
<div class="line">VkDevice device;</div>
<div class="line"><a class="code hl_struct" href="struct_vma_allocator.html">VmaAllocator</a> allocator;</div>
<div class="line">VkCommandBuffer commandBuffer;</div>
<div class="line">std::vector&lt;VkBuffer&gt; buffers;</div>
<div class="line">std::vector&lt;VmaAllocation&gt; allocations;</div>
<div class="line"> </div>
<div class="line"> </div>
<div class="line"><span class="keyword">const</span> uint32_t allocCount = (uint32_t)allocations.size();</div>
<div class="line">std::vector&lt;VkBool32&gt; allocationsChanged(allocCount);</div>
<div class="line"> </div>
<div class="line">VkCommandBufferBeginInfo cmdBufBeginInfo = ...;</div>
<div class="line">vkBeginCommandBuffer(commandBuffer, &amp;cmdBufBeginInfo);</div>
<div class="line"> </div>
<div class="line"><a class="code hl_struct" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a> defragInfo = {};</div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a> = allocCount;</div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info2.html#ab6d288f29d028156cf73542d630a2e32">pAllocations</a> = allocations.data();</div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">pAllocationsChanged</a> = allocationsChanged.data();</div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">maxGpuBytesToMove</a> = VK_WHOLE_SIZE; <span class="comment">// Notice it is &quot;GPU&quot; this time.</span></div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">maxGpuAllocationsToMove</a> = UINT32_MAX; <span class="comment">// Notice it is &quot;GPU&quot; this time.</span></div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">commandBuffer</a> = commandBuffer;</div>
<div class="fragment"><div class="line"><a class="code hl_struct" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a> defragInfo = {};</div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info.html#a18dd2097d8ab2976cdc7dd3e7b978bd4">pool</a> = myPool;</div>
<div class="line">defragInfo.<a class="code hl_variable" href="struct_vma_defragmentation_info.html#a3e23080c978ecf3abb3180f5b2069da7">flags</a> = <a class="code hl_enumvalue" href="group__group__alloc.html#gga6552a65b71d16f378c6994b3ceaef50ca2e6469bcf5a094776ceb5d118263f04b">VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT</a>;</div>
<div class="line"> </div>
<div class="line"><a class="code hl_struct" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> defragCtx;</div>
<div class="line"><a class="code hl_function" href="group__group__alloc.html#ga36ba776fd7fd5cb1e9359fdc0d8e6e8a">vmaDefragmentationBegin</a>(allocator, &amp;defragInfo, <span class="keyword">nullptr</span>, &amp;defragCtx);</div>
<div class="line">VkResult res = <a class="code hl_function" href="group__group__alloc.html#gac3335566858b45541fa9c0d7a6bbb57e">vmaBeginDefragmentation</a>(allocator, &amp;defragInfo, &amp;defragCtx);</div>
<div class="line"><span class="comment">// Check res...</span></div>
<div class="line"> </div>
<div class="line">vkEndCommandBuffer(commandBuffer);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Submit commandBuffer.</span></div>
<div class="line"><span class="comment">// Wait for a fence that ensures commandBuffer execution finished.</span></div>
<div class="line"> </div>
<div class="line"><a class="code hl_function" href="group__group__alloc.html#ga8774e20e91e245aae959ba63efa15dd2">vmaDefragmentationEnd</a>(allocator, defragCtx);</div>
<div class="line"> </div>
<div class="line"><span class="keywordflow">for</span>(uint32_t i = 0; i &lt; allocCount; ++i)</div>
<div class="line"><span class="keywordflow">for</span>(;;)</div>
<div class="line">{</div>
<div class="line"> <span class="keywordflow">if</span>(allocationsChanged[i])</div>
<div class="line"> <a class="code hl_struct" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a> pass;</div>
<div class="line"> res = <a class="code hl_function" href="group__group__alloc.html#ga980d7da2ce3b1fd5c8b8476bc362cc00">vmaBeginDefragmentationPass</a>(allocator, defragCtx, &amp;pass);</div>
<div class="line"> <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
<div class="line"> <span class="keywordflow">break</span>;</div>
<div class="line"> <span class="keywordflow">else</span> <span class="keywordflow">if</span>(res == VK_INCOMPLETE)</div>
<div class="line"> {</div>
<div class="line"> <span class="comment">// Destroy buffer that is immutably bound to memory region which is no longer valid.</span></div>
<div class="line"> vkDestroyBuffer(device, buffers[i], <span class="keyword">nullptr</span>);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Create new buffer with same parameters.</span></div>
<div class="line"> VkBufferCreateInfo bufferInfo = ...;</div>
<div class="line"> vkCreateBuffer(device, &amp;bufferInfo, <span class="keyword">nullptr</span>, &amp;buffers[i]);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning.</span></div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Bind new buffer to new memory region. Data contained in it is already moved.</span></div>
<div class="line"> <a class="code hl_struct" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div>
<div class="line"> <a class="code hl_function" href="group__group__alloc.html#ga86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a>(allocator, allocations[i], &amp;allocInfo);</div>
<div class="line"> <a class="code hl_function" href="group__group__alloc.html#ga6b0929b914b60cf2d45cac4bf3547470">vmaBindBufferMemory</a>(allocator, allocations[i], buffers[i]);</div>
<div class="line"> <span class="keywordflow">for</span>(uint32_t i = 0; i &lt; pass.<a class="code hl_variable" href="struct_vma_defragmentation_pass_move_info.html#a1b3e18c23f9691f35baf183e615c4408">moveCount</a>; ++i)</div>
<div class="line"> {</div>
<div class="line"> <span class="comment">//- Inspect pass.pMoves[i].srcAllocation, identify what buffer or image it represents.</span></div>
<div class="line"> <span class="comment">//- Recreate this buffer or image at pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset.</span></div>
<div class="line"> <span class="comment">//- Issue a vkCmdCopyBuffer/vkCmdCopyImage to copy its content to the new place.</span></div>
<div class="line"> }</div>
<div class="line"> <span class="comment">//- Make sure the copy commands finished executing.</span></div>
<div class="line"> <span class="comment">//- Update appropriate descriptors to point to the new places.</span></div>
<div class="line"> <a class="code hl_function" href="group__group__alloc.html#gaded05a445742a00718ee766144c5c226">vmaEndDefragmentationPass</a>(allocator, defragCtx, &amp;pass);</div>
<div class="line"> }</div>
<div class="line"> <span class="keywordflow">else</span></div>
<div class="line"> <span class="comment">// Handle error...</span></div>
<div class="line">}</div>
<div class="ttc" id="astruct_vma_defragmentation_info2_html_a40d53d33e71ba0b66f844ed63c05a3f6"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">VmaDefragmentationInfo2::maxGpuAllocationsToMove</a></div><div class="ttdeci">uint32_t maxGpuAllocationsToMove</div><div class="ttdoc">Maximum number of allocations that can be moved to a different place using transfers on GPU side,...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1447</div></div>
<div class="ttc" id="astruct_vma_defragmentation_info2_html_a4ddbc898d0afe1518f863a3763628f08"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">VmaDefragmentationInfo2::maxGpuBytesToMove</a></div><div class="ttdeci">VkDeviceSize maxGpuBytesToMove</div><div class="ttdoc">Maximum total numbers of bytes that can be copied while moving allocations to different places using ...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1442</div></div>
<div class="ttc" id="astruct_vma_defragmentation_info2_html_a7f71f39590c5316771493d2333f9c1bd"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">VmaDefragmentationInfo2::commandBuffer</a></div><div class="ttdeci">VkCommandBuffer commandBuffer</div><div class="ttdoc">Optional. Command buffer where GPU copy commands will be posted.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1456</div></div>
</div><!-- fragment --><p >You can combine these two methods by specifying non-zero <code>maxGpu*</code> as well as <code>maxCpu*</code> parameters. The library automatically chooses best method to defragment each memory pool.</p>
<p >You may try not to block your entire program to wait until defragmentation finishes, but do it in the background, as long as you carefully fullfill requirements described in function <a class="el" href="group__group__alloc.html#ga36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a>.</p>
<h1><a class="anchor" id="defragmentation_additional_notes"></a>
Additional notes</h1>
<p >It is only legal to defragment allocations bound to:</p>
<ul>
<li>buffers</li>
<li>images created with <code>VK_IMAGE_CREATE_ALIAS_BIT</code>, <code>VK_IMAGE_TILING_LINEAR</code>, and being currently in <code>VK_IMAGE_LAYOUT_GENERAL</code> or <code>VK_IMAGE_LAYOUT_PREINITIALIZED</code>.</li>
</ul>
<p >Defragmentation of images created with <code>VK_IMAGE_TILING_OPTIMAL</code> or in any other layout may give undefined results.</p>
<p >If you defragment allocations bound to images, new images to be bound to new memory region after defragmentation should be created with <code>VK_IMAGE_LAYOUT_PREINITIALIZED</code> and then transitioned to their original layout from before defragmentation if needed using an image memory barrier.</p>
<p >While using defragmentation, you may experience validation layer warnings, which you just need to ignore. See <a class="el" href="general_considerations.html#general_considerations_validation_layer_warnings">Validation layer warnings</a>.</p>
<p >Please don't expect memory to be fully compacted after defragmentation. Algorithms inside are based on some heuristics that try to maximize number of Vulkan memory blocks to make totally empty to release them, as well as to maximize continuous empty space inside remaining blocks, while minimizing the number and size of allocations that need to be moved. Some fragmentation may still remain - this is normal.</p>
<h1><a class="anchor" id="defragmentation_custom_algorithm"></a>
Writing custom defragmentation algorithm</h1>
<p >If you want to implement your own, custom defragmentation algorithm, there is infrastructure prepared for that, but it is not exposed through the library API - you need to hack its source code. Here are steps needed to do this:</p>
<ol type="1">
<li>Main thing you need to do is to define your own class derived from base abstract class <code>VmaDefragmentationAlgorithm</code> and implement your version of its pure virtual methods. See definition and comments of this class for details.</li>
<li>Your code needs to interact with device memory block metadata. If you need more access to its data than it is provided by its public interface, declare your new class as a friend class e.g. in class <code>VmaBlockMetadata_Generic</code>.</li>
<li>If you want to create a flag that would enable your algorithm or pass some additional flags to configure it, add them to <code>VmaDefragmentationFlagBits</code> and use them in <a class="el" href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9" title="Reserved for future use. Should be 0.">VmaDefragmentationInfo2::flags</a>.</li>
<li>Modify function <code>VmaBlockVectorDefragmentationContext::Begin</code> to create object of your new class whenever needed. </li>
</ol>
<div class="line"> </div>
<div class="line"><a class="code hl_function" href="group__group__alloc.html#ga729a594b45ae1681096940a44f3eb174">vmaEndDefragmentation</a>(allocator, defragCtx, <span class="keyword">nullptr</span>);</div>
<div class="ttc" id="agroup__group__alloc_html_ga729a594b45ae1681096940a44f3eb174"><div class="ttname"><a href="group__group__alloc.html#ga729a594b45ae1681096940a44f3eb174">vmaEndDefragmentation</a></div><div class="ttdeci">VkResult vmaEndDefragmentation(VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationStats *pStats)</div><div class="ttdoc">Ends defragmentation process.</div></div>
<div class="ttc" id="agroup__group__alloc_html_ga980d7da2ce3b1fd5c8b8476bc362cc00"><div class="ttname"><a href="group__group__alloc.html#ga980d7da2ce3b1fd5c8b8476bc362cc00">vmaBeginDefragmentationPass</a></div><div class="ttdeci">VkResult vmaBeginDefragmentationPass(VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationPassMoveInfo *pPassInfo)</div><div class="ttdoc">Starts single defragmentation pass.</div></div>
<div class="ttc" id="agroup__group__alloc_html_gac3335566858b45541fa9c0d7a6bbb57e"><div class="ttname"><a href="group__group__alloc.html#gac3335566858b45541fa9c0d7a6bbb57e">vmaBeginDefragmentation</a></div><div class="ttdeci">VkResult vmaBeginDefragmentation(VmaAllocator allocator, const VmaDefragmentationInfo *pInfo, VmaDefragmentationContext *pContext)</div><div class="ttdoc">Begins defragmentation process.</div></div>
<div class="ttc" id="agroup__group__alloc_html_gaded05a445742a00718ee766144c5c226"><div class="ttname"><a href="group__group__alloc.html#gaded05a445742a00718ee766144c5c226">vmaEndDefragmentationPass</a></div><div class="ttdeci">VkResult vmaEndDefragmentationPass(VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationPassMoveInfo *pPassInfo)</div><div class="ttdoc">Ends single defragmentation pass.</div></div>
<div class="ttc" id="agroup__group__alloc_html_gga6552a65b71d16f378c6994b3ceaef50ca2e6469bcf5a094776ceb5d118263f04b"><div class="ttname"><a href="group__group__alloc.html#gga6552a65b71d16f378c6994b3ceaef50ca2e6469bcf5a094776ceb5d118263f04b">VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT</a></div><div class="ttdeci">@ VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:700</div></div>
<div class="ttc" id="astruct_vma_defragmentation_context_html"><div class="ttname"><a href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a></div><div class="ttdoc">An opaque object that represents started defragmentation process.</div></div>
<div class="ttc" id="astruct_vma_defragmentation_info_html"><div class="ttname"><a href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a></div><div class="ttdoc">Parameters for defragmentation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1381</div></div>
<div class="ttc" id="astruct_vma_defragmentation_info_html_a18dd2097d8ab2976cdc7dd3e7b978bd4"><div class="ttname"><a href="struct_vma_defragmentation_info.html#a18dd2097d8ab2976cdc7dd3e7b978bd4">VmaDefragmentationInfo::pool</a></div><div class="ttdeci">VmaPool pool</div><div class="ttdoc">Custom pool to be defragmented.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1388</div></div>
<div class="ttc" id="astruct_vma_defragmentation_info_html_a3e23080c978ecf3abb3180f5b2069da7"><div class="ttname"><a href="struct_vma_defragmentation_info.html#a3e23080c978ecf3abb3180f5b2069da7">VmaDefragmentationInfo::flags</a></div><div class="ttdeci">VmaDefragmentationFlags flags</div><div class="ttdoc">Use combination of VmaDefragmentationFlagBits.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1383</div></div>
<div class="ttc" id="astruct_vma_defragmentation_pass_move_info_html"><div class="ttname"><a href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a></div><div class="ttdoc">Parameters for incremental defragmentation steps.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1421</div></div>
<div class="ttc" id="astruct_vma_defragmentation_pass_move_info_html_a1b3e18c23f9691f35baf183e615c4408"><div class="ttname"><a href="struct_vma_defragmentation_pass_move_info.html#a1b3e18c23f9691f35baf183e615c4408">VmaDefragmentationPassMoveInfo::moveCount</a></div><div class="ttdeci">uint32_t moveCount</div><div class="ttdoc">Number of elements in the pMoves array.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1423</div></div>
</div><!-- fragment --><p >You can defragment a specific custom pool by setting <a class="el" href="struct_vma_defragmentation_info.html#a18dd2097d8ab2976cdc7dd3e7b978bd4" title="Custom pool to be defragmented.">VmaDefragmentationInfo::pool</a> (like in the example above) or all the default pools by setting this member to null.</p>
<p >Unlike in previous iterations of the defragmentation API, there is no list of "movable" allocations passed as a parameter. Defragmentation algorithm tries to move all suitable allocations. You can, however, refuse to move some of them inside a defragmentation pass, by setting <code>pass.pMoves[i].operation</code> to <a class="el" href="group__group__alloc.html#ggada9e3861caf96f08894b0bcc160ec257ad25bc6f816b226b4fd5170e845f218d2" title="Set this value if you cannot move the allocation. New place reserved dstMemory + dstOffset will be fr...">VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE</a>. However, this is not recommended and may result in suboptimal packing of the allocations after defragmentation. If you cannot ensure any allocation can be moved, it is better to keep movable allocations separate in a custom pool.</p>
<p >You can also decide to destroy an allocation instead of moving it. You should then set <code>pass.pMoves[i].operation</code> to <a class="el" href="group__group__alloc.html#ggada9e3861caf96f08894b0bcc160ec257a9786f8492a9be2c03bd26395e352ab85" title="Set this value if you decide to abandon the allocation and you destroyed the buffer/image....">VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY</a>.</p>
<p >You can perform the defragmentation incrementally to limit the number of allocations and bytes to be moved in each pass, e.g. to call it in sync with render frames and not to experience too big hitches. See members: <a class="el" href="struct_vma_defragmentation_info.html#a637ada77b02179a27fa92290000afac4" title="Maximum numbers of bytes that can be copied during single pass, while moving allocations to different...">VmaDefragmentationInfo::maxBytesPerPass</a>, <a class="el" href="struct_vma_defragmentation_info.html#ac2db29d309bebc4f7d55041416e9694b" title="Maximum number of allocations that can be moved during single pass to a different place.">VmaDefragmentationInfo::maxAllocationsPerPass</a>.</p>
<p >It is also safe to perform the defragmentation asynchronously to render frames and other Vulkan and VMA usage, possibly from multiple threads, with the exception that allocations returned in <a class="el" href="struct_vma_defragmentation_pass_move_info.html#adfa7a4994afd9b940e7f1dfaf436a725" title="Array of moves to be performed by the user in the current defragmentation pass.">VmaDefragmentationPassMoveInfo::pMoves</a> shouldn't be destroyed until the defragmentation pass is ended. </p>
</div></div><!-- contents -->
</div><!-- PageDoc -->
<!-- start footer part -->