Skip to content

Commit dedab85

Browse files
Documented linear allocation algorithm. Added "Linear allocation algorithm" documentation chapter.
1 parent cba11e8 commit dedab85

19 files changed

Lines changed: 320 additions & 143 deletions
1.23 KB
Loading
1.94 KB
Loading
5.08 KB
Loading
3.28 KB
Loading
2.19 KB
Loading
2.6 KB
Loading
1.56 KB
Loading

docs/html/custom_memory_pools.html

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
<ol type="1">
7979
<li>Fill <a class="el" href="struct_vma_pool_create_info.html" title="Describes parameter of created VmaPool. ">VmaPoolCreateInfo</a> structure.</li>
8080
<li>Call <a class="el" href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50" title="Allocates Vulkan device memory and creates VmaPool object. ">vmaCreatePool()</a> to obtain <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool. ">VmaPool</a> handle.</li>
81-
<li>When making an allocation, set <a class="el" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150" title="Pool that this allocation should be created in. ">VmaAllocationCreateInfo::pool</a> to this handle. You don't need to specify any other parameters of this structure, like usage.</li>
81+
<li>When making an allocation, set <a class="el" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150" title="Pool that this allocation should be created in. ">VmaAllocationCreateInfo::pool</a> to this handle. You don't need to specify any other parameters of this structure, like <code>usage</code>.</li>
8282
</ol>
8383
<p>Example:</p>
8484
<div class="fragment"><div class="line"><span class="comment">// Create a pool that can have at most 2 blocks, 128 MiB each.</span></div><div class="line"><a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a> poolCreateInfo = {};</div><div class="line">poolCreateInfo.<a class="code" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">memoryTypeIndex</a> = ...</div><div class="line">poolCreateInfo.blockSize = 128ull * 1024 * 1024;</div><div class="line">poolCreateInfo.<a class="code" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">maxBlockCount</a> = 2;</div><div class="line"></div><div class="line"><a class="code" href="struct_vma_pool.html">VmaPool</a> pool;</div><div class="line"><a class="code" href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50">vmaCreatePool</a>(allocator, &amp;poolCreateInfo, &amp;pool);</div><div class="line"></div><div class="line"><span class="comment">// Allocate a buffer out of it.</span></div><div class="line">VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div><div class="line">bufCreateInfo.size = 1024;</div><div class="line">bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;</div><div class="line"></div><div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div><div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a> = pool;</div><div class="line"></div><div class="line">VkBuffer buf;</div><div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc;</div><div class="line"><a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div><div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &amp;bufCreateInfo, &amp;allocCreateInfo, &amp;buf, &amp;alloc, &amp;allocInfo);</div></div><!-- fragment --><p>You have to free all allocations made from this pool before destroying it.</p>
@@ -88,9 +88,55 @@
8888
<div class="fragment"><div class="line">VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div><div class="line">exampleBufCreateInfo.size = 1024; <span class="comment">// Whatever.</span></div><div class="line">exampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; <span class="comment">// Change if needed.</span></div><div class="line"></div><div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div><div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>; <span class="comment">// Change if needed.</span></div><div class="line"></div><div class="line">uint32_t memTypeIndex;</div><div class="line"><a class="code" href="vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888">vmaFindMemoryTypeIndexForBufferInfo</a>(allocator, &amp;exampleBufCreateInfo, &amp;allocCreateInfo, &amp;memTypeIndex);</div><div class="line"></div><div class="line"><a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a> poolCreateInfo = {};</div><div class="line">poolCreateInfo.<a class="code" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">memoryTypeIndex</a> = memTypeIndex;</div><div class="line"><span class="comment">// ...</span></div></div><!-- fragment --><p>When creating buffers/images allocated in that pool, provide following parameters:</p>
8989
<ul>
9090
<li><code>VkBufferCreateInfo</code>: Prefer to pass same parameters as above. Otherwise you risk creating resources in a memory type that is not suitable for them, which may result in undefined behavior. Using different <code>VK_BUFFER_USAGE_</code> flags may work, but you shouldn't create images in a pool intended for buffers or the other way around.</li>
91-
<li><a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>: You don't need to pass same parameters. Fill only <code>pool</code> member. Other members are ignored anyway. </li>
91+
<li><a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>: You don't need to pass same parameters. Fill only <code>pool</code> member. Other members are ignored anyway.</li>
9292
</ul>
93-
</div></div><!-- contents -->
93+
<h1><a class="anchor" id="linear_algorithm"></a>
94+
Linear allocation algorithm</h1>
95+
<p>Each Vulkan memory block managed by this library has accompanying metadata that keeps track of used and unused regions. By default, the metadata structure and algorithm tries to find best place for new allocations among free regions to optimize memory usage. This way you can allocate and free objects in any order.</p>
96+
<div class="image">
97+
<img src="../gfx/Linear_allocator_1_algo_default.png" alt="Default allocation algorithm"/>
98+
</div>
99+
<p>Sometimes there is a need to use simpler, linear allocation algorithm. You can create custom pool that uses such algorithm by adding flag <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726" title="Enables alternative, linear allocation algorithm in this pool. ">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a> to <a class="el" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446" title="Use combination of VmaPoolCreateFlagBits. ">VmaPoolCreateInfo::flags</a> while creating <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool. ">VmaPool</a> object. Then an alternative metadata management is used. It always creates new allocations after last one and doesn't reuse free regions after allocations freed in the middle. It results in better allocation performance and less memory consumed by metadata.</p>
100+
<div class="image">
101+
<img src="../gfx/Linear_allocator_2_algo_linear.png" alt="Linear allocation algorithm"/>
102+
</div>
103+
<p>With this one flag, you can create a custom pool that can be used in many ways: free-at-once, stack, double stack, and ring buffer. See below for details.</p>
104+
<p>Pools with linear algorithm must have only one memory block - <a class="el" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c" title="Maximum number of blocks that can be allocated in this pool. Optional. ">VmaPoolCreateInfo::maxBlockCount</a> must be 1.</p>
105+
<h2><a class="anchor" id="linear_algorithm_free_at_once"></a>
106+
Free-at-once</h2>
107+
<p>In a pool that uses linear algorithm, you still need to free all the allocations individually, e.g. by using <a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568" title="Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage(). ">vmaFreeMemory()</a> or <a class="el" href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77" title="Destroys Vulkan buffer and frees allocated memory. ">vmaDestroyBuffer()</a>. You can free them in any order. New allocations are always made after last one - free space in the middle is not reused. However, when you release all the allocation and the pool becomes empty, allocation starts from the beginning again. This way you can use linear algorithm to speed up creation of allocations that you are going to release all at once.</p>
108+
<div class="image">
109+
<img src="../gfx/Linear_allocator_3_free_at_once.png" alt="Free-at-once"/>
110+
</div>
111+
<h2><a class="anchor" id="linear_algorithm_stack"></a>
112+
Stack</h2>
113+
<p>When you free an allocation that was created last, its space can be reused. Thanks to this, if you always release allocations in the order opposite to their creation (LIFO - Last In First Out), you can achieve behavior of a stack.</p>
114+
<div class="image">
115+
<img src="../gfx/Linear_allocator_4_stack.png" alt="Stack"/>
116+
</div>
117+
<h2><a class="anchor" id="linear_algorithm_double_stack"></a>
118+
Double stack</h2>
119+
<p>The space reserved by a custom pool with linear algorithm may be used by two stacks:</p>
120+
<ul>
121+
<li>First, default one, growing up from offset 0.</li>
122+
<li>Second, "upper" one, growing down from the end towards lower offsets.</li>
123+
</ul>
124+
<p>To make allocation from upper stack, add flag <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df">VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT</a> to <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b" title="Use VmaAllocationCreateFlagBits enum. ">VmaAllocationCreateInfo::flags</a>.</p>
125+
<p>When the two stacks' ends meet so there is not enough space between them for a new allocation, such allocation fails with usual <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code> error.</p>
126+
<div class="image">
127+
<img src="../gfx/Linear_allocator_7_double_stack.png" alt="Double stack"/>
128+
</div>
129+
<h2><a class="anchor" id="linear_algorithm_ring_buffer"></a>
130+
Ring buffer</h2>
131+
<p>When you free some allocations from the beginning and there is not enough free space for a new one at the end of a pool, allocator's "cursor" wraps around to the beginning and starts allocation there. Thanks to this, if you always release allocations in the same order as you created them (FIFO - First In First Out), you can achieve behavior of a ring buffer / queue.</p>
132+
<div class="image">
133+
<img src="../gfx/Linear_allocator_5_ring_buffer.png" alt="Ring buffer"/>
134+
</div>
135+
<p>Pools with linear algorithm support lost allocations when used as ring buffer. If there is not enough free space for a new allocation, but existing allocations from the front of the queue can become lost, they become lost and the allocation succeeds.</p>
136+
<div class="image">
137+
<img src="../gfx/Linear_allocator_6_ring_buffer_lost.png" alt="Ring buffer with lost allocations"/>
138+
</div>
139+
</div></div><!-- contents -->
94140
<!-- start footer part -->
95141
<hr class="footer"/><address class="footer"><small>
96142
Generated by &#160;<a href="http://www.doxygen.org/index.html">

docs/html/debugging_memory_usage.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@
6969
<div class="textblock"><p>If you suspect a bug with memory usage, like usage of uninitialized memory or memory being overwritten out of bounds of an allocation, you can use debug features of this library to verify this.</p>
7070
<h1><a class="anchor" id="debugging_memory_usage_initialization"></a>
7171
Memory initialization</h1>
72-
<p>If you experience a bug with incorrect data in your program and you suspect uninitialized memory to be used, you can enable automatic memory initialization to verify this. To do it, define macro <code>VMA_DEBUG_INITIALIZE_ALLOCATIONS</code> to 1.</p>
72+
<p>If you experience a bug with incorrect and nondeterministic data in your program and you suspect uninitialized memory to be used, you can enable automatic memory initialization to verify this. To do it, define macro <code>VMA_DEBUG_INITIALIZE_ALLOCATIONS</code> to 1.</p>
7373
<div class="fragment"><div class="line"><span class="preprocessor">#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1</span></div><div class="line"><span class="preprocessor">#include &quot;vk_mem_alloc.h&quot;</span></div></div><!-- fragment --><p>It makes memory of all new allocations initialized to bit pattern <code>0xDCDCDCDC</code>. Before an allocation is destroyed, its memory is filled with bit pattern <code>0xEFEFEFEF</code>. Memory is automatically mapped and unmapped if necessary.</p>
7474
<p>If you find these values while debugging your program, good chances are that you incorrectly read Vulkan memory that is allocated but not initialized, or already freed, respectively.</p>
75-
<p>Memory initialization works only with memory types that are <code>HOST_VISIBLE</code>. It works also with dedicated allocations. It doesn't work with allocations created with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag, as these they cannot be mapped.</p>
75+
<p>Memory initialization works only with memory types that are <code>HOST_VISIBLE</code>. It works also with dedicated allocations. It doesn't work with allocations created with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag, as they cannot be mapped.</p>
7676
<h1><a class="anchor" id="debugging_memory_usage_margins"></a>
7777
Margins</h1>
7878
<p>By default, allocations are laid out in memory blocks next to each other if possible (considering required alignment, <code>bufferImageGranularity</code>, and <code>nonCoherentAtomSize</code>).</p>

docs/html/globals.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ <h3><a id="index_v"></a>- v -</h3><ul>
8989
<li>VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT
9090
: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff">vk_mem_alloc.h</a>
9191
</li>
92+
<li>VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT
93+
: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df">vk_mem_alloc.h</a>
94+
</li>
9295
<li>VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT
9396
: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">vk_mem_alloc.h</a>
9497
</li>
@@ -128,6 +131,9 @@ <h3><a id="index_v"></a>- v -</h3><ul>
128131
<li>VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT
129132
: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a9f1a499508a8edb4e8ba40aa0290a3d2">vk_mem_alloc.h</a>
130133
</li>
134+
<li>VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT
135+
: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">vk_mem_alloc.h</a>
136+
</li>
131137
<li>VMA_RECORD_FLAG_BITS_MAX_ENUM
132138
: <a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a20dd17d69966dbffa054739d6090b85e">vk_mem_alloc.h</a>
133139
</li>

0 commit comments

Comments
 (0)