mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
synced 2024-11-25 16:14:35 +00:00
Fixes and improvements in documentation
This commit is contained in:
parent
9ca6ecd2ae
commit
b0fce340b6
@ -60,6 +60,7 @@ Additional features:
|
||||
- Convert this JSON dump into a picture to visualize your memory. See [tools/VmaDumpVis](tools/VmaDumpVis/README.md).
|
||||
- Debugging incorrect memory usage: Enable initialization of all allocated memory with a bit pattern to detect usage of uninitialized or freed memory. Enable validation of a magic number before and after every allocation to detect out-of-bounds memory corruption.
|
||||
- Record and replay sequence of calls to library functions to a file to check correctness, measure performance, and gather statistics.
|
||||
- Support for interoperability with OpenGL.
|
||||
|
||||
# Prequisites
|
||||
|
||||
|
@ -71,7 +71,7 @@ $(function() {
|
||||
<div class="contents">
|
||||
<div class="textblock"><h1><a class="anchor" id="allocation_user_data"></a>
|
||||
Allocation user data</h1>
|
||||
<p>You can annotate allocations with your own information, e.g. for debugging purposes. To do that, fill <a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19" title="Custom general-purpose pointer that will be stored in VmaAllocation, can be read as VmaAllocationInfo...">VmaAllocationCreateInfo::pUserData</a> field when creating an allocation. It's an opaque <code>void*</code> pointer. You can use it e.g. as a pointer, some handle, index, key, ordinal number or any other value that would associate the allocation with your custom metadata.</p>
|
||||
<p>You can annotate allocations with your own information, e.g. for debugging purposes. To do that, fill <a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19" title="Custom general-purpose pointer that will be stored in VmaAllocation, can be read as VmaAllocationInfo...">VmaAllocationCreateInfo::pUserData</a> field when creating an allocation. It is an opaque <code>void*</code> pointer. You can use it e.g. as a pointer, some handle, index, key, ordinal number or any other value that would associate the allocation with your custom metadata.</p>
|
||||
<div class="fragment"><div class="line">VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div>
|
||||
<div class="line"><span class="comment">// Fill bufferInfo...</span></div>
|
||||
<div class="line"> </div>
|
||||
|
@ -133,7 +133,7 @@ Custom memory pools</h1>
|
||||
<p>If you allocate from custom memory pool, all the ways of specifying memory requirements described above are not applicable and the aforementioned members of <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> structure are ignored. Memory type is selected explicitly when creating the pool and then used to make all the allocations from that pool. For further details, see <a class="el" href="custom_memory_pools.html">Custom memory pools</a>.</p>
|
||||
<h1><a class="anchor" id="choosing_memory_type_dedicated_allocations"></a>
|
||||
Dedicated allocations</h1>
|
||||
<p>Memory for allocations is reserved out of larger block of <code>VkDeviceMemory</code> allocated from Vulkan internally. That's the main feature of this whole library. You can still request a separate memory block to be created for an allocation, just like you would do in a trivial solution without using any allocator. In that case, a buffer or image is always bound to that memory at offset 0. This is called a "dedicated allocation". You can explicitly request it by using flag <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f" title="Set this flag if the allocation should have its own memory block.">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a>. The library can also internally decide to use dedicated allocation in some cases, e.g.:</p>
|
||||
<p>Memory for allocations is reserved out of larger block of <code>VkDeviceMemory</code> allocated from Vulkan internally. That is the main feature of this whole library. You can still request a separate memory block to be created for an allocation, just like you would do in a trivial solution without using any allocator. In that case, a buffer or image is always bound to that memory at offset 0. This is called a "dedicated allocation". You can explicitly request it by using flag <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f" title="Set this flag if the allocation should have its own memory block.">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a>. The library can also internally decide to use dedicated allocation in some cases, e.g.:</p>
|
||||
<ul>
|
||||
<li>When the size of the allocation is large.</li>
|
||||
<li>When <a class="el" href="vk_khr_dedicated_allocation.html">VK_KHR_dedicated_allocation</a> extension is enabled and it reports that dedicated allocation is required or recommended for the resource.</li>
|
||||
|
@ -76,6 +76,7 @@ $(function() {
|
||||
<li>Enforce particular, fixed size of Vulkan memory blocks.</li>
|
||||
<li>Limit maximum amount of Vulkan memory allocated for that pool.</li>
|
||||
<li>Reserve minimum or fixed amount of Vulkan memory always preallocated for that pool.</li>
|
||||
<li>Use extra parameters for a set of your allocations that are available in <a class="el" href="struct_vma_pool_create_info.html" title="Describes parameter of created VmaPool.">VmaPoolCreateInfo</a> but not in <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> - e.g., custom minimum alignment, custom <code>pNext</code> chain.</li>
|
||||
</ul>
|
||||
<p>To use custom memory pools:</p>
|
||||
<ol type="1">
|
||||
@ -181,7 +182,7 @@ Ring buffer</h2>
|
||||
<p>Ring buffer is available only in pools with 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. Otherwise behavior is undefined.</p>
|
||||
<h1><a class="anchor" id="buddy_algorithm"></a>
|
||||
Buddy allocation algorithm</h1>
|
||||
<p>There is another allocation algorithm that can be used with custom pools, called "buddy". Its internal data structure is based on a tree of blocks, each having size that is a power of two and a half of its parent's size. When you want to allocate memory of certain size, a free node in the tree is located. If it's too large, it is recursively split into two halves (called "buddies"). However, if requested allocation size is not a power of two, the size of a tree node is aligned up to the nearest power of two and the remaining space is wasted. When two buddy nodes become free, they are merged back into one larger node.</p>
|
||||
<p>There is another allocation algorithm that can be used with custom pools, called "buddy". Its internal data structure is based on a tree of blocks, each having size that is a power of two and a half of its parent's size. When you want to allocate memory of certain size, a free node in the tree is located. If it is too large, it is recursively split into two halves (called "buddies"). However, if requested allocation size is not a power of two, the size of a tree node is aligned up to the nearest power of two and the remaining space is wasted. When two buddy nodes become free, they are merged back into one larger node.</p>
|
||||
<p><img src="../gfx/Buddy_allocator.png" alt="Buddy allocator" class="inline"/></p>
|
||||
<p>The advantage of buddy allocation algorithm over default algorithm is faster allocation and deallocation, as well as smaller external fragmentation. The disadvantage is more wasted space (internal fragmentation).</p>
|
||||
<p>For more information, please read <a href="https://en.wikipedia.org/wiki/Buddy_memory_allocation">"Buddy memory allocation" on Wikipedia</a> or other sources that describe this concept in general.</p>
|
||||
|
@ -99,7 +99,7 @@ Corruption detection</h1>
|
||||
<div class="line"><span class="preprocessor">#define VMA_DEBUG_DETECT_CORRUPTION 1</span></div>
|
||||
<div class="line"><span class="preprocessor">#include "vk_mem_alloc.h"</span></div>
|
||||
</div><!-- fragment --><p>When this feature is enabled, number of bytes specified as <code>VMA_DEBUG_MARGIN</code> (it must be multiply of 4) before and after every allocation is filled with a magic number. This idea is also know as "canary". Memory is automatically mapped and unmapped if necessary.</p>
|
||||
<p>This number is validated automatically when the allocation is destroyed. If it's not equal to the expected value, <code>VMA_ASSERT()</code> is executed. It clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation, which indicates a serious bug.</p>
|
||||
<p>This number is validated automatically when the allocation is destroyed. If it is not equal to the expected value, <code>VMA_ASSERT()</code> is executed. It clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation, which indicates a serious bug.</p>
|
||||
<p>You can also explicitly request checking margins of all allocations in all memory blocks that belong to specified memory types by using function <a class="el" href="vk__mem__alloc_8h.html#a49329a7f030dafcf82f7b73334c22e98" title="Checks magic number in margins around all allocations in given memory types (in both default and cust...">vmaCheckCorruption()</a>, or in memory blocks that belong to specified custom pool, by using function <a class="el" href="vk__mem__alloc_8h.html#ad535935619c7a549bf837e1bb0068f89" title="Checks magic number in margins around all allocations in given memory pool in search for corruptions.">vmaCheckPoolCorruption()</a>.</p>
|
||||
<p>Margin validation (corruption detection) works only for memory types that are <code>HOST_VISIBLE</code> and <code>HOST_COHERENT</code>. </p>
|
||||
</div></div><!-- contents -->
|
||||
|
@ -170,8 +170,8 @@ Defragmenting GPU memory</h1>
|
||||
<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a> = allocCount;</div>
|
||||
<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#ab6d288f29d028156cf73542d630a2e32">pAllocations</a> = allocations.data();</div>
|
||||
<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">pAllocationsChanged</a> = allocationsChanged.data();</div>
|
||||
<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">maxGpuBytesToMove</a> = VK_WHOLE_SIZE; <span class="comment">// Notice it's "GPU" this time.</span></div>
|
||||
<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">maxGpuAllocationsToMove</a> = UINT32_MAX; <span class="comment">// Notice it's "GPU" this time.</span></div>
|
||||
<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">maxGpuBytesToMove</a> = VK_WHOLE_SIZE; <span class="comment">// Notice it is "GPU" this time.</span></div>
|
||||
<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">maxGpuAllocationsToMove</a> = UINT32_MAX; <span class="comment">// Notice it is "GPU" this time.</span></div>
|
||||
<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">commandBuffer</a> = commandBuffer;</div>
|
||||
<div class="line"> </div>
|
||||
<div class="line"><a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> defragCtx;</div>
|
||||
@ -224,7 +224,7 @@ 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's provided by its public interface, declare your new class as a friend class e.g. in class <code>VmaBlockMetadata_Generic</code>.</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>
|
||||
|
@ -112,7 +112,7 @@ Features not supported</h1>
|
||||
<p>Features deliberately excluded from the scope of this library:</p>
|
||||
<ul>
|
||||
<li><b>Data transfer.</b> Uploading (streaming) and downloading data of buffers and images between CPU and GPU memory and related synchronization is responsibility of the user. Defining some "texture" object that would automatically stream its data from a staging copy in CPU memory to GPU memory would rather be a feature of another, higher-level library implemented on top of VMA.</li>
|
||||
<li><b>Recreation of buffers and images.</b> Although the library has functions for buffer and image creation (<a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>, <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a>), you need to recreate these objects yourself after defragmentation. That's because the big structures <code>VkBufferCreateInfo</code>, <code>VkImageCreateInfo</code> are not stored in <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> object.</li>
|
||||
<li><b>Recreation of buffers and images.</b> Although the library has functions for buffer and image creation (<a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>, <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a>), you need to recreate these objects yourself after defragmentation. That is because the big structures <code>VkBufferCreateInfo</code>, <code>VkImageCreateInfo</code> are not stored in <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> object.</li>
|
||||
<li><b>Handling CPU memory allocation failures.</b> When dynamically creating small C++ objects in CPU memory (not Vulkan memory), allocation failures are not checked and handled gracefully, because that would complicate code significantly and is usually not needed in desktop PC applications anyway. Success of an allocation is just checked with an assert.</li>
|
||||
<li><b>Code free of any compiler warnings.</b> Maintaining the library to compile and work correctly on so many different platforms is hard enough. Being free of any warnings, on any version of any compiler, is simply not feasible. There are many preprocessor macros that make some variables unused, function parameters unreferenced, or conditional expressions constant in some configurations. The code of this library should not be bigger or more complicated just to silence these warnings. It is recommended to disable such warnings instead.</li>
|
||||
<li>This is a C++ library with C interface. <b>Bindings or ports to any other programming languages</b> are welcome as external projects but are not going to be included into this repository. </li>
|
||||
|
@ -70,12 +70,12 @@ $(function() {
|
||||
</div><!--header-->
|
||||
<div class="contents">
|
||||
<div class="textblock"><p>If your game oversubscribes video memory, if may work OK in previous-generation graphics APIs (DirectX 9, 10, 11, OpenGL) because resources are automatically paged to system RAM. In Vulkan you can't do it because when you run out of memory, an allocation just fails. If you have more data (e.g. textures) that can fit into VRAM and you don't need it all at once, you may want to upload them to GPU on demand and "push out" ones that are not used for a long time to make room for the new ones, effectively using VRAM (or a cartain memory pool) as a form of cache. Vulkan Memory Allocator can help you with that by supporting a concept of "lost allocations".</p>
|
||||
<p>To create an allocation that can become lost, include <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag in <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b" title="Use VmaAllocationCreateFlagBits enum.">VmaAllocationCreateInfo::flags</a>. Before using a buffer or image bound to such allocation in every new frame, you need to query it if it's not lost. To check it, call <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a" title="Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.">vmaTouchAllocation()</a>. If the allocation is lost, you should not use it or buffer/image bound to it. You mustn't forget to destroy this allocation and this buffer/image. <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> can also be used for checking status of the allocation. Allocation is lost when returned <a class="el" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67" title="Handle to Vulkan memory object.">VmaAllocationInfo::deviceMemory</a> == <code>VK_NULL_HANDLE</code>.</p>
|
||||
<p>To create an allocation that can become lost, include <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag in <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b" title="Use VmaAllocationCreateFlagBits enum.">VmaAllocationCreateInfo::flags</a>. Before using a buffer or image bound to such allocation in every new frame, you need to query it if it is not lost. To check it, call <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a" title="Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.">vmaTouchAllocation()</a>. If the allocation is lost, you should not use it or buffer/image bound to it. You mustn't forget to destroy this allocation and this buffer/image. <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> can also be used for checking status of the allocation. Allocation is lost when returned <a class="el" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67" title="Handle to Vulkan memory object.">VmaAllocationInfo::deviceMemory</a> == <code>VK_NULL_HANDLE</code>.</p>
|
||||
<p>To create an allocation that can make some other allocations lost to make room for it, use <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a> flag. You will usually use both flags <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a> and <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> at the same time.</p>
|
||||
<p>Warning! Current implementation uses quite naive, brute force algorithm, which can make allocation calls that use <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a> flag quite slow. A new, more optimal algorithm and data structure to speed this up is planned for the future.</p>
|
||||
<p><b>Q: When interleaving creation of new allocations with usage of existing ones, how do you make sure that an allocation won't become lost while it's used in the current frame?</b></p>
|
||||
<p>It is ensured because <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a" title="Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.">vmaTouchAllocation()</a> / <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> not only returns allocation status/parameters and checks whether it's not lost, but when it's not, it also atomically marks it as used in the current frame, which makes it impossible to become lost in that frame. It uses lockless algorithm, so it works fast and doesn't involve locking any internal mutex.</p>
|
||||
<p><b>Q: What if my allocation may still be in use by the GPU when it's rendering a previous frame while I already submit new frame on the CPU?</b></p>
|
||||
<p><b>Q: When interleaving creation of new allocations with usage of existing ones, how do you make sure that an allocation won't become lost while it is used in the current frame?</b></p>
|
||||
<p>It is ensured because <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a" title="Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.">vmaTouchAllocation()</a> / <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> not only returns allocation status/parameters and checks whether it is not lost, but when it is not, it also atomically marks it as used in the current frame, which makes it impossible to become lost in that frame. It uses lockless algorithm, so it works fast and doesn't involve locking any internal mutex.</p>
|
||||
<p><b>Q: What if my allocation may still be in use by the GPU when it is rendering a previous frame while I already submit new frame on the CPU?</b></p>
|
||||
<p>You can make sure that allocations "touched" by <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a" title="Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.">vmaTouchAllocation()</a> / <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> will not become lost for a number of additional frames back from the current one by specifying this number as <a class="el" href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7" title="Maximum number of additional frames that are in use at the same time as current frame.">VmaAllocatorCreateInfo::frameInUseCount</a> (for default memory pool) and <a class="el" href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa" title="Maximum number of additional frames that are in use at the same time as current frame.">VmaPoolCreateInfo::frameInUseCount</a> (for custom pool).</p>
|
||||
<p><b>Q: How do you inform the library when new frame starts?</b></p>
|
||||
<p>You need to call function <a class="el" href="vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236" title="Sets index of the current frame.">vmaSetCurrentFrameIndex()</a>.</p>
|
||||
@ -97,7 +97,7 @@ $(function() {
|
||||
<div class="line"> <span class="comment">// Check if its allocation is not lost + mark it as used in current frame.</span></div>
|
||||
<div class="line"> <span class="keywordflow">if</span>(<a class="code" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a">vmaTouchAllocation</a>(allocator, m_Alloc))</div>
|
||||
<div class="line"> {</div>
|
||||
<div class="line"> <span class="comment">// It's all OK - safe to use m_Buf.</span></div>
|
||||
<div class="line"> <span class="comment">// It is all OK - safe to use m_Buf.</span></div>
|
||||
<div class="line"> <span class="keywordflow">return</span>;</div>
|
||||
<div class="line"> }</div>
|
||||
<div class="line"> }</div>
|
||||
|
@ -72,7 +72,7 @@ $(function() {
|
||||
<div class="textblock"><p>To "map memory" in Vulkan means to obtain a CPU pointer to <code>VkDeviceMemory</code>, to be able to read from it or write to it in CPU code. Mapping is possible only of memory allocated from a memory type that has <code>VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT</code> flag. Functions <code>vkMapMemory()</code>, <code>vkUnmapMemory()</code> are designed for this purpose. You can use them directly with memory allocated by this library, but it is not recommended because of following issue: Mapping the same <code>VkDeviceMemory</code> block multiple times is illegal - only one mapping at a time is allowed. This includes mapping disjoint regions. Mapping is not reference-counted internally by Vulkan. Because of this, Vulkan Memory Allocator provides following facilities:</p>
|
||||
<h1><a class="anchor" id="memory_mapping_mapping_functions"></a>
|
||||
Mapping functions</h1>
|
||||
<p>The library provides following functions for mapping of a specific <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a>: <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a>, <a class="el" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45" title="Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().">vmaUnmapMemory()</a>. They are safer and more convenient to use than standard Vulkan functions. You can map an allocation multiple times simultaneously - mapping is reference-counted internally. You can also map different allocations simultaneously regardless of whether they use the same <code>VkDeviceMemory</code> block. The way it's implemented is that the library always maps entire memory block, not just region of the allocation. For further details, see description of <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a> function. Example:</p>
|
||||
<p>The library provides following functions for mapping of a specific <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a>: <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a>, <a class="el" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45" title="Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().">vmaUnmapMemory()</a>. They are safer and more convenient to use than standard Vulkan functions. You can map an allocation multiple times simultaneously - mapping is reference-counted internally. You can also map different allocations simultaneously regardless of whether they use the same <code>VkDeviceMemory</code> block. The way it is implemented is that the library always maps entire memory block, not just region of the allocation. For further details, see description of <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a> function. Example:</p>
|
||||
<div class="fragment"><div class="line"><span class="comment">// Having these objects initialized:</span></div>
|
||||
<div class="line"> </div>
|
||||
<div class="line"><span class="keyword">struct </span>ConstantBuffer</div>
|
||||
@ -188,7 +188,7 @@ Finding out if memory is mappable</h1>
|
||||
<div class="line"><span class="keywordflow">if</span>(allocInfo.<a class="code" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a> != <span class="keyword">nullptr</span>)</div>
|
||||
<div class="line">{</div>
|
||||
<div class="line"> <span class="comment">// Allocation ended up in mappable memory.</span></div>
|
||||
<div class="line"> <span class="comment">// It's persistently mapped. You can access it directly.</span></div>
|
||||
<div class="line"> <span class="comment">// It is persistently mapped. You can access it directly.</span></div>
|
||||
<div class="line"> memcpy(allocInfo.<a class="code" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a>, &constantBufferData, <span class="keyword">sizeof</span>(constantBufferData));</div>
|
||||
<div class="line">}</div>
|
||||
<div class="line"><span class="keywordflow">else</span></div>
|
||||
|
@ -73,13 +73,13 @@ $(function() {
|
||||
<h1><a class="anchor" id="opengl_interop_exporting_memory"></a>
|
||||
Exporting memory</h1>
|
||||
<p>If you want to attach <code>VkExportMemoryAllocateInfoKHR</code> structure to <code>pNext</code> chain of memory allocations made by the library:</p>
|
||||
<p>It is recommended to create a <a class="el" href="custom_memory_pools.html">Custom memory pools</a> for such allocations. Define and fill in your <code>VkExportMemoryAllocateInfoKHR</code> structure and attach it to <a class="el" href="struct_vma_pool_create_info.html#af0f8c58f51a2a7a0a389dc79565044d7" title="Additional pNext chain to be attached to VkMemoryAllocateInfo used for every allocation made by this ...">VmaPoolCreateInfo::pMemoryAllocateNext</a> while creating the custom pool. Please note that the structure must remain alive and unchanged for the whole lifetime of the <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a>, not only while creating it, as no copy of the structure is made, but its original pointer is used for each allocation instead.</p>
|
||||
<p>It is recommended to create <a class="el" href="custom_memory_pools.html">Custom memory pools</a> for such allocations. Define and fill in your <code>VkExportMemoryAllocateInfoKHR</code> structure and attach it to <a class="el" href="struct_vma_pool_create_info.html#af0f8c58f51a2a7a0a389dc79565044d7" title="Additional pNext chain to be attached to VkMemoryAllocateInfo used for every allocation made by this ...">VmaPoolCreateInfo::pMemoryAllocateNext</a> while creating the custom pool. Please note that the structure must remain alive and unchanged for the whole lifetime of the <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a>, not only while creating it, as no copy of the structure is made, but its original pointer is used for each allocation instead.</p>
|
||||
<p>If you want to export all memory allocated by the library from certain memory types, also dedicated allocations or other allocations made from default pools, an alternative solution is to fill in <a class="el" href="struct_vma_allocator_create_info.html#ae8f0db05e5cb4c43d7713bf4a49a736b" title="Either null or a pointer to an array of external memory handle types for each Vulkan memory type.">VmaAllocatorCreateInfo::pTypeExternalMemoryHandleTypes</a>. It should point to an array with <code>VkExternalMemoryHandleTypeFlagsKHR</code> to be automatically passed by the library through <code>VkExportMemoryAllocateInfoKHR</code> on each allocation made from a specific memory type. This is currently the only method to use if you need exported dedicated allocations, as they cannot be created out of custom pools. This will change in future versions of the library though.</p>
|
||||
<p>You should not mix these two methods in a way that allows to apply both to the same memory type. Otherwise, <code>VkExportMemoryAllocateInfoKHR</code> structure would be attached twice to the <code>pNext</code> chain of <code>VkMemoryAllocateInfo</code>.</p>
|
||||
<h1><a class="anchor" id="opengl_interop_custom_alignment"></a>
|
||||
Custom alignment</h1>
|
||||
<p>Buffers or images exported to a different API like OpenGL may require a different alignment, higher than the one used by the library automatically, queried from functions like <code>vkGetBufferMemoryRequirements</code>. To impose such alignment:</p>
|
||||
<p>It is recommended to create a <a class="el" href="custom_memory_pools.html">Custom memory pools</a> for such allocations. Set <a class="el" href="struct_vma_pool_create_info.html#ade3eca546f0c6ab4e8fbf20eb6d854cb" title="Additional minimum alignment to be used for all allocations created from this pool....">VmaPoolCreateInfo::minAllocationAlignment</a> member to the minimum alignment required for each allocation to be made out of this pool. The alignment actually used will be the maximum of this member and the alignment returned for the specific buffer or image from a function like <code>vkGetBufferMemoryRequirements</code>, which is called by VMA automatically.</p>
|
||||
<p>It is recommended to create <a class="el" href="custom_memory_pools.html">Custom memory pools</a> for such allocations. Set <a class="el" href="struct_vma_pool_create_info.html#ade3eca546f0c6ab4e8fbf20eb6d854cb" title="Additional minimum alignment to be used for all allocations created from this pool....">VmaPoolCreateInfo::minAllocationAlignment</a> member to the minimum alignment required for each allocation to be made out of this pool. The alignment actually used will be the maximum of this member and the alignment returned for the specific buffer or image from a function like <code>vkGetBufferMemoryRequirements</code>, which is called by VMA automatically.</p>
|
||||
<p>If you want to create a buffer with a specific minimum alignment out of default pools, use special function <a class="el" href="vk__mem__alloc_8h.html#aa06a690013a0d01e60894ac378083834" title="Creates a buffer with additional minimum alignment.">vmaCreateBufferWithAlignment()</a>, which takes additional parameter <code>minAlignment</code>. This is currently the only method to use if you need exported dedicated allocations, as they cannot be created out of custom pools. This will change in future versions of the library though.</p>
|
||||
<p>Note the problem of alignment affects only resources placed inside bigger <code>VkDeviceMemory</code> blocks and not dedicated allocations, as these, by definition, always have alignment = 0 because the resource is bound to the beginning of its dedicated block. Contrary to Direct3D 12, Vulkan doesn't have a concept of alignment of the entire memory block passed on its allocation. </p>
|
||||
</div></div><!-- contents -->
|
||||
|
@ -83,7 +83,7 @@ Usage</h1>
|
||||
<div class="fragment"><div class="line"><span class="preprocessor">#define VMA_RECORDING_ENABLED 1</span></div>
|
||||
</div><!-- fragment --><p><b>To record sequence of calls to a file:</b> Fill in <a class="el" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee" title="Parameters for recording of VMA calls. Can be null.">VmaAllocatorCreateInfo::pRecordSettings</a> member while creating <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object. File is opened and written during whole lifetime of the allocator.</p>
|
||||
<p><b>To replay file:</b> Use VmaReplay - standalone command-line program. Precompiled binary can be found in "bin" directory. Its source can be found in "src/VmaReplay" directory. Its project is generated by Premake. Command line syntax is printed when the program is launched without parameters. Basic usage: </p><pre class="fragment">VmaReplay.exe MyRecording.csv
|
||||
</pre><p> <b>Documentation of file format</b> can be found in file: "docs/Recording file format.md". It's a human-readable, text file in CSV format (Comma Separated Values).</p>
|
||||
</pre><p> <b>Documentation of file format</b> can be found in file: "docs/Recording file format.md". It is a human-readable, text file in CSV format (Comma Separated Values).</p>
|
||||
<h1><a class="anchor" id="record_and_replay_additional_considerations"></a>
|
||||
Additional considerations</h1>
|
||||
<ul>
|
||||
|
@ -69,7 +69,7 @@ $(function() {
|
||||
<div class="title">Staying within budget </div> </div>
|
||||
</div><!--header-->
|
||||
<div class="contents">
|
||||
<div class="textblock"><p>When developing a graphics-intensive game or program, it is important to avoid allocating more GPU memory than it's physically available. When the memory is over-committed, various bad things can happen, depending on the specific GPU, graphics driver, and operating system:</p>
|
||||
<div class="textblock"><p>When developing a graphics-intensive game or program, it is important to avoid allocating more GPU memory than it is physically available. When the memory is over-committed, various bad things can happen, depending on the specific GPU, graphics driver, and operating system:</p>
|
||||
<ul>
|
||||
<li>It may just work without any problems.</li>
|
||||
<li>The application may slow down because some memory blocks are moved to system RAM and the GPU has to access them through PCI Express bus.</li>
|
||||
|
@ -1130,7 +1130,7 @@ Functions</h2></td></tr>
|
||||
<p>Using this flag may increase performance because internal mutexes are not used. </p>
|
||||
</td></tr>
|
||||
<tr><td class="fieldname"><a id="a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878"></a>VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT </td><td class="fielddoc"><p>Enables usage of VK_KHR_dedicated_allocation extension. </p>
|
||||
<p>The flag works only if <a class="el" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285" title="Optional. The highest version of Vulkan that the application is designed to use.">VmaAllocatorCreateInfo::vulkanApiVersion</a> <code>== VK_API_VERSION_1_0</code>. When it's <code>VK_API_VERSION_1_1</code>, the flag is ignored because the extension has been promoted to Vulkan 1.1.</p>
|
||||
<p>The flag works only if <a class="el" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285" title="Optional. The highest version of Vulkan that the application is designed to use.">VmaAllocatorCreateInfo::vulkanApiVersion</a> <code>== VK_API_VERSION_1_0</code>. When it is <code>VK_API_VERSION_1_1</code>, the flag is ignored because the extension has been promoted to Vulkan 1.1.</p>
|
||||
<p>Using this extension will automatically allocate dedicated blocks of memory for some buffers and images instead of suballocating place for them out of bigger memory blocks (as if you explicitly used <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f" title="Set this flag if the allocation should have its own memory block.">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a> flag) when it is recommended by the driver. It may improve performance on some GPUs.</p>
|
||||
<p>You may set this flag only if you found out that following device extensions are supported, you enabled them while creating Vulkan device passed as <a class="el" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500" title="Vulkan device.">VmaAllocatorCreateInfo::device</a>, and you want them to be used internally by this library:</p>
|
||||
<ul>
|
||||
@ -1143,7 +1143,7 @@ Functions</h2></td></tr>
|
||||
</blockquote>
|
||||
</td></tr>
|
||||
<tr><td class="fieldname"><a id="a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee"></a>VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT </td><td class="fielddoc"><p>Enables usage of VK_KHR_bind_memory2 extension.</p>
|
||||
<p>The flag works only if <a class="el" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285" title="Optional. The highest version of Vulkan that the application is designed to use.">VmaAllocatorCreateInfo::vulkanApiVersion</a> <code>== VK_API_VERSION_1_0</code>. When it's <code>VK_API_VERSION_1_1</code>, the flag is ignored because the extension has been promoted to Vulkan 1.1.</p>
|
||||
<p>The flag works only if <a class="el" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285" title="Optional. The highest version of Vulkan that the application is designed to use.">VmaAllocatorCreateInfo::vulkanApiVersion</a> <code>== VK_API_VERSION_1_0</code>. When it is <code>VK_API_VERSION_1_1</code>, the flag is ignored because the extension has been promoted to Vulkan 1.1.</p>
|
||||
<p>You may set this flag only if you found out that this device extension is supported, you enabled it while creating Vulkan device passed as <a class="el" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500" title="Vulkan device.">VmaAllocatorCreateInfo::device</a>, and you want it to be used internally by this library.</p>
|
||||
<p>The extension provides functions <code>vkBindBufferMemory2KHR</code> and <code>vkBindImageMemory2KHR</code>, which allow to pass a chain of <code>pNext</code> structures while binding. This flag is required if you use <code>pNext</code> parameter in <a class="el" href="vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a" title="Binds buffer to allocation with additional parameters.">vmaBindBufferMemory2()</a> or <a class="el" href="vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc" title="Binds image to allocation with additional parameters.">vmaBindImageMemory2()</a>. </p>
|
||||
</td></tr>
|
||||
@ -3531,7 +3531,7 @@ Functions</h2></td></tr>
|
||||
</div><div class="memdoc">
|
||||
|
||||
<p>Returns <code>VK_TRUE</code> if allocation is not lost and atomically marks it as used in current frame. </p>
|
||||
<p>If the allocation has been created with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag, this function returns <code>VK_TRUE</code> if it's not in lost state, so it can still be used. It then also atomically "touches" the allocation - marks it as used in current frame, so that you can be sure it won't become lost in current frame or next <code>frameInUseCount</code> frames.</p>
|
||||
<p>If the allocation has been created with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag, this function returns <code>VK_TRUE</code> if it is not in lost state, so it can still be used. It then also atomically "touches" the allocation - marks it as used in current frame, so that you can be sure it won't become lost in current frame or next <code>frameInUseCount</code> frames.</p>
|
||||
<p>If the allocation is in lost state, the function returns <code>VK_FALSE</code>. Memory of such allocation, as well as buffer or image bound to it, should not be used. Lost allocation and the buffer/image still need to be destroyed.</p>
|
||||
<p>If the allocation has been created without <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag, this function always returns <code>VK_TRUE</code>. </p>
|
||||
|
||||
|
@ -83,7 +83,7 @@ $(function() {
|
||||
<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">vmaCreateAllocator</a>(&allocatorInfo, &allocator);</div>
|
||||
<div class="ttc" id="avk__mem__alloc_8h_html_a200692051ddb34240248234f5f4c17bb"><div class="ttname"><a href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">vmaCreateAllocator</a></div><div class="ttdeci">VkResult vmaCreateAllocator(const VmaAllocatorCreateInfo *pCreateInfo, VmaAllocator *pAllocator)</div><div class="ttdoc">Creates Allocator object.</div></div>
|
||||
<div class="ttc" id="avk__mem__alloc_8h_html_a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878">VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT</div><div class="ttdoc">Enables usage of VK_KHR_dedicated_allocation extension.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:358</div></div>
|
||||
</div><!-- fragment --><p>That's all. The extension will be automatically used whenever you create a buffer using <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a> or image using <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a>.</p>
|
||||
</div><!-- fragment --><p>That is all. The extension will be automatically used whenever you create a buffer using <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a> or image using <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a>.</p>
|
||||
<p>When using the extension together with Vulkan Validation Layer, you will receive warnings like this: </p><pre class="fragment">vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer.
|
||||
</pre><p> It is OK, you should just ignore it. It happens because you use function <code>vkGetBufferMemoryRequirements2KHR()</code> instead of standard <code>vkGetBufferMemoryRequirements()</code>, while the validation layer seems to be unaware of it.</p>
|
||||
<p>To learn more about this extension, see:</p>
|
||||
|
@ -18535,6 +18535,8 @@ It can be useful if you want to:
|
||||
- Enforce particular, fixed size of Vulkan memory blocks.
|
||||
- Limit maximum amount of Vulkan memory allocated for that pool.
|
||||
- Reserve minimum or fixed amount of Vulkan memory always preallocated for that pool.
|
||||
- Use extra parameters for a set of your allocations that are available in #VmaPoolCreateInfo but not in
|
||||
#VmaAllocationCreateInfo - e.g., custom minimum alignment, custom `pNext` chain.
|
||||
|
||||
To use custom memory pools:
|
||||
|
||||
@ -19351,7 +19353,7 @@ VMA provides some features that help with interoperability with OpenGL.
|
||||
|
||||
If you want to attach `VkExportMemoryAllocateInfoKHR` structure to `pNext` chain of memory allocations made by the library:
|
||||
|
||||
It is recommended to create a \ref custom_memory_pools for such allocations.
|
||||
It is recommended to create \ref custom_memory_pools for such allocations.
|
||||
Define and fill in your `VkExportMemoryAllocateInfoKHR` structure and attach it to VmaPoolCreateInfo::pMemoryAllocateNext
|
||||
while creating the custom pool.
|
||||
Please note that the structure must remain alive and unchanged for the whole lifetime of the #VmaPool,
|
||||
@ -19376,7 +19378,7 @@ Buffers or images exported to a different API like OpenGL may require a differen
|
||||
higher than the one used by the library automatically, queried from functions like `vkGetBufferMemoryRequirements`.
|
||||
To impose such alignment:
|
||||
|
||||
It is recommended to create a \ref custom_memory_pools for such allocations.
|
||||
It is recommended to create \ref custom_memory_pools for such allocations.
|
||||
Set VmaPoolCreateInfo::minAllocationAlignment member to the minimum alignment required for each allocation
|
||||
to be made out of this pool.
|
||||
The alignment actually used will be the maximum of this member and the alignment returned for the specific buffer or image
|
||||
|
Loading…
Reference in New Issue
Block a user