Improvements in documentation. Moved general description to README.md.

This commit is contained in:
Adam Sawicki 2017-09-25 15:07:34 +02:00
parent eaf60ee784
commit 19d74084f3
7 changed files with 199 additions and 202 deletions

View File

@ -10,8 +10,51 @@ This is a README file for Vulkan Memory Allocator library and accompanying sampl
**Build status:** **Build status:**
Windows: [![Build status](https://ci.appveyor.com/api/projects/status/4vlcrb0emkaio2pn/branch/master?svg=true)](https://ci.appveyor.com/project/adam-sawicki-amd/vulkanmemoryallocator/branch/master) - Windows: [![Build status](https://ci.appveyor.com/api/projects/status/4vlcrb0emkaio2pn/branch/master?svg=true)](https://ci.appveyor.com/project/adam-sawicki-amd/vulkanmemoryallocator/branch/master)
Linux: [![Build Status](https://travis-ci.org/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.svg?branch=master)](https://travis-ci.org/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) - Linux: [![Build Status](https://travis-ci.org/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.svg?branch=master)](https://travis-ci.org/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)
# Problem
Memory allocation and resource (buffer and image) creation in Vulkan is difficult (comparing to older graphics API-s, like D3D11 or OpenGL) for several reasons:
- It requires a lot of boilerplate code, just like everything else in Vulkan, because it is a low-level and high-performance API.
- There is additional level of indirection: `VkDeviceMemory` is allocated separately from creating `VkBuffer`/`VkImage` and they must be bound together. The binding cannot be changed later - resource must be recreated.
- Driver must be queried for supported memory heaps and memory types. Different IHVs provide different types of it.
- It is recommended practice to allocate bigger chunks of memory and assign parts of them to particular resources.
# Features
This library can help game developers to manage memory allocations and resource creation by offering some higher-level functions. Features of the library are divided into several layers, low level to high level:
1. Functions that help to choose correct and optimal memory type based on intended usage of the memory.
- Required or preferred traits of the memory are expressed using higher-level description comparing to Vulkan flags.
2. Functions that allocate memory blocks, reserve and return parts of them (`VkDeviceMemory` + offset + size) to the user.
- Library keeps track of allocated memory blocks, used and unused ranges inside them, finds best matching unused ranges for new allocations, takes all the rules of alignment into consideration.
3. Functions that can create an image/buffer, allocate memory for it and bind them together - all in one call.
Additional features:
- Thread-safety: Library is designed to be used by multithreaded code.
- Configuration: Fill optional members of CreateInfo structure to provide custom CPU memory allocator and other parameters.
- Customization: Predefine appropriate macros to provide your own implementation of all external facilities used by the library, from assert, mutex, and atomic, to vector and linked list.
- Support for persistently mapped memory: Just allocate memory with appropriate flag and you get access to mapped pointer.
- Custom memory pools: Create a pool with desired parameters (e.g. fixed or limited maximum size) and allocate memory out of it.
- Defragmentation: Call one function and let the library move data around to free some memory blocks and make your allocations better compacted.
- Lost allocations: Allocate memory with appropriate flags and let the library remove allocations that are not used for many frames to make room for new ones.
- Statistics: Obtain detailed statistics about the amount of memory used, unused, number of allocated blocks, number of allocations etc. - globally, per memory heap, and per memory type.
- JSON dump: Obtain a string in JSON format with detailed map of internal state, including list of allocations and gaps between them.
# Prequisites
- Self-contained C++ library in single header file. No external dependencies other than standard C and C++ library and of course Vulkan.
- Public interface in C, in same convention as Vulkan API. Implementation in C++.
- Interface documented using Doxygen-style comments.
- Platform-independent, but developed and tested on Windows using Visual Studio.
- Error handling implemented by returning `VkResult` error codes - same way as in Vulkan.
# Read more
See [Vulkan Memory Allocator Documentation](https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/).
# Other software # Other software

View File

@ -615,7 +615,7 @@ Functions</h2></td></tr>
</ul> </ul>
<p>The function also frees empty <code>VkDeviceMemory</code> blocks.</p> <p>The function also frees empty <code>VkDeviceMemory</code> blocks.</p>
<p>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 into deviceMemory object to the beginning of this allocation, in bytes. (deviceMemory, offset) pair is unique to this allocation. ">VmaAllocationInfo::offset</a> changes. You must query them again using <a class="el" href="group__layer2.html#ga86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation. ">vmaGetAllocationInfo()</a> if you need them.</p> <p>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 into deviceMemory object to the beginning of this allocation, in bytes. (deviceMemory, offset) pair is unique to this allocation. ">VmaAllocationInfo::offset</a> changes. You must query them again using <a class="el" href="group__layer2.html#ga86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation. ">vmaGetAllocationInfo()</a> if you need them.</p>
<p>If an allocation has been moved, data in memory is copied to new place automatically, but if it was bound to a buffer or an image, you must destroy that object yourself, create new one and bind it to the new memory pointed by the allocation. You must use <code>vkDestroyBuffer()</code>, <code>vkDestroyImage()</code>, <code>vkCreateBuffer()</code>, <code>vkCreateImage()</code> for that purpose and NOT <a class="el" href="group__layer3.html#ga0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer()</a>, <a class="el" href="group__layer3.html#gae50d2cb3b4a3bfd4dd40987234e50e7e">vmaDestroyImage()</a>, <a class="el" href="group__layer3.html#gac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>, <a class="el" href="group__layer3.html#ga02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer(). ">vmaCreateImage()</a>! Example:</p> <p>If an allocation has been moved, data in memory is copied to new place automatically, but if it was bound to a buffer or an image, you must destroy that object yourself, create new one and bind it to the new memory pointed by the allocation. You must use <code>vkDestroyBuffer()</code>, <code>vkDestroyImage()</code>, <code>vkCreateBuffer()</code>, <code>vkCreateImage()</code> for that purpose and NOT <a class="el" href="group__layer3.html#ga0d9f4e4ba5bf9aab1f1c746387753d77" title="Destroys Vulkan buffer and frees allocated memory. ">vmaDestroyBuffer()</a>, <a class="el" href="group__layer3.html#gae50d2cb3b4a3bfd4dd40987234e50e7e" title="Destroys Vulkan image and frees allocated memory. ">vmaDestroyImage()</a>, <a class="el" href="group__layer3.html#gac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>, <a class="el" href="group__layer3.html#ga02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer(). ">vmaCreateImage()</a>! Example:</p>
<pre class="fragment">VkDevice device = ...; <pre class="fragment">VkDevice device = ...;
VmaAllocator allocator = ...; VmaAllocator allocator = ...;
std::vector&lt;VkBuffer&gt; buffers = ...; std::vector&lt;VkBuffer&gt; buffers = ...;
@ -968,7 +968,7 @@ for(size_t i = 0; i &lt; allocations.size(); ++i)
</div><div class="memdoc"> </div><div class="memdoc">
<p>Unmaps persistently mapped memory of types that are <code>HOST_COHERENT</code> and <code>DEVICE_LOCAL</code>. </p> <p>Unmaps persistently mapped memory of types that are <code>HOST_COHERENT</code> and <code>DEVICE_LOCAL</code>. </p>
<p>This is optional performance optimization. On Windows you should call it before every call to <code>vkQueueSubmit</code> and <code>vkQueuePresent</code>. After which you can remap the allocations again using <a class="el" href="group__layer2.html#ga03366170bb8e186605518d2f5d65b85a" title="Maps back persistently mapped memory of types that are HOST_COHERENT and DEVICE_LOCAL. ">vmaMapPersistentlyMappedMemory()</a>. This is because of the internal behavior of WDDM. Example:</p> <p>This is optional performance optimization. On AMD GPUs on Windows, Vulkan memory from the type that has both <code>DEVICE_LOCAL</code> and <code>HOST_VISIBLE</code> flags should not be mapped for the time of any call to <code>vkQueueSubmit()</code> or <code>vkQueuePresent()</code>. Although legal, that would cause performance degradation because WDDM migrates such memory to system RAM. To ensure this, you can unmap all persistently mapped memory using this function. Example:</p>
<pre class="fragment">vmaUnmapPersistentlyMappedMemory(allocator); <pre class="fragment">vmaUnmapPersistentlyMappedMemory(allocator);
vkQueueSubmit(...) vkQueueSubmit(...)
vmaMapPersistentlyMappedMemory(allocator); vmaMapPersistentlyMappedMemory(allocator);

View File

@ -70,11 +70,13 @@ Functions</h2></td></tr>
<tr class="memitem:gac72ee55598617e8eecca384e746bab51"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#gac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a> (VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, VkBuffer *pBuffer, VmaAllocation *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr> <tr class="memitem:gac72ee55598617e8eecca384e746bab51"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#gac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a> (VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, VkBuffer *pBuffer, VmaAllocation *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr>
<tr class="separator:gac72ee55598617e8eecca384e746bab51"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:gac72ee55598617e8eecca384e746bab51"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga0d9f4e4ba5bf9aab1f1c746387753d77"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#ga0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a> (VmaAllocator allocator, VkBuffer buffer, VmaAllocation allocation)</td></tr> <tr class="memitem:ga0d9f4e4ba5bf9aab1f1c746387753d77"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#ga0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a> (VmaAllocator allocator, VkBuffer buffer, VmaAllocation allocation)</td></tr>
<tr class="memdesc:ga0d9f4e4ba5bf9aab1f1c746387753d77"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroys Vulkan buffer and frees allocated memory. <a href="#ga0d9f4e4ba5bf9aab1f1c746387753d77">More...</a><br /></td></tr>
<tr class="separator:ga0d9f4e4ba5bf9aab1f1c746387753d77"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga0d9f4e4ba5bf9aab1f1c746387753d77"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga02a94f25679275851a53e82eacbcfc73"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#ga02a94f25679275851a53e82eacbcfc73">vmaCreateImage</a> (VmaAllocator allocator, const VkImageCreateInfo *pImageCreateInfo, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, VkImage *pImage, VmaAllocation *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr> <tr class="memitem:ga02a94f25679275851a53e82eacbcfc73"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#ga02a94f25679275851a53e82eacbcfc73">vmaCreateImage</a> (VmaAllocator allocator, const VkImageCreateInfo *pImageCreateInfo, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, VkImage *pImage, VmaAllocation *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr>
<tr class="memdesc:ga02a94f25679275851a53e82eacbcfc73"><td class="mdescLeft">&#160;</td><td class="mdescRight">Function similar to <a class="el" href="group__layer3.html#gac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>. <a href="#ga02a94f25679275851a53e82eacbcfc73">More...</a><br /></td></tr> <tr class="memdesc:ga02a94f25679275851a53e82eacbcfc73"><td class="mdescLeft">&#160;</td><td class="mdescRight">Function similar to <a class="el" href="group__layer3.html#gac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>. <a href="#ga02a94f25679275851a53e82eacbcfc73">More...</a><br /></td></tr>
<tr class="separator:ga02a94f25679275851a53e82eacbcfc73"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga02a94f25679275851a53e82eacbcfc73"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#gae50d2cb3b4a3bfd4dd40987234e50e7e">vmaDestroyImage</a> (VmaAllocator allocator, VkImage image, VmaAllocation allocation)</td></tr> <tr class="memitem:gae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#gae50d2cb3b4a3bfd4dd40987234e50e7e">vmaDestroyImage</a> (VmaAllocator allocator, VkImage image, VmaAllocation allocation)</td></tr>
<tr class="memdesc:gae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroys Vulkan image and frees allocated memory. <a href="#gae50d2cb3b4a3bfd4dd40987234e50e7e">More...</a><br /></td></tr>
<tr class="separator:gae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:gae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table> </table>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2> <a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
@ -143,7 +145,7 @@ Functions</h2></td></tr>
<li>Binds the buffer with the memory.</li> <li>Binds the buffer with the memory.</li>
</ol> </ol>
<p>If any of these operations fail, buffer and allocation are not created, returned value is negative error code, *pBuffer and *pAllocation are null.</p> <p>If any of these operations fail, buffer and allocation are not created, returned value is negative error code, *pBuffer and *pAllocation are null.</p>
<p>If the function succeeded, you must destroy both buffer and allocation when you no longer need them using either convenience function <a class="el" href="group__layer3.html#ga0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer()</a> or separately, using vkDestroyBuffer() and <a class="el" href="group__layer2.html#ga11f0fbc034fa81a4efedd73d61ce7568" title="Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage(). ">vmaFreeMemory()</a>. </p> <p>If the function succeeded, you must destroy both buffer and allocation when you no longer need them using either convenience function <a class="el" href="group__layer3.html#ga0d9f4e4ba5bf9aab1f1c746387753d77" title="Destroys Vulkan buffer and frees allocated memory. ">vmaDestroyBuffer()</a> or separately, using vkDestroyBuffer() and <a class="el" href="group__layer2.html#ga11f0fbc034fa81a4efedd73d61ce7568" title="Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage(). ">vmaFreeMemory()</a>. </p>
</div> </div>
</div> </div>
@ -233,6 +235,10 @@ Functions</h2></td></tr>
</table> </table>
</div><div class="memdoc"> </div><div class="memdoc">
<p>Destroys Vulkan buffer and frees allocated memory. </p>
<p>This is just a convenience function equivalent to:</p>
<pre class="fragment">vkDestroyBuffer(device, buffer, allocationCallbacks);
vmaFreeMemory(allocator, allocation);</pre>
</div> </div>
</div> </div>
<a id="gae50d2cb3b4a3bfd4dd40987234e50e7e"></a> <a id="gae50d2cb3b4a3bfd4dd40987234e50e7e"></a>
@ -267,6 +273,10 @@ Functions</h2></td></tr>
</table> </table>
</div><div class="memdoc"> </div><div class="memdoc">
<p>Destroys Vulkan image and frees allocated memory. </p>
<p>This is just a convenience function equivalent to:</p>
<pre class="fragment">vkDestroyImage(device, image, allocationCallbacks);
vmaFreeMemory(allocator, allocation);</pre>
</div> </div>
</div> </div>
</div><!-- contents --> </div><!-- contents -->

View File

@ -63,10 +63,7 @@ $(function() {
</div><!--header--> </div><!--header-->
<div class="contents"> <div class="contents">
<div class="toc"><h3>Table of Contents</h3> <div class="toc"><h3>Table of Contents</h3>
<ul><li class="level1"><a href="#problem">Problem statement</a></li> <ul><li class="level1"><a href="#user_guide">User guide</a><ul><li class="level2"><a href="#quick_start">Quick start</a></li>
<li class="level1"><a href="#features">Features</a></li>
<li class="level1"><a href="#prequisites">Prequisites</a></li>
<li class="level1"><a href="#user_guide">User guide</a><ul><li class="level2"><a href="#quick_start">Quick start</a></li>
<li class="level2"><a href="#persistently_mapped_memory">Persistently mapped memory</a></li> <li class="level2"><a href="#persistently_mapped_memory">Persistently mapped memory</a></li>
<li class="level2"><a href="#custom_memory_pools">Custom memory pools</a></li> <li class="level2"><a href="#custom_memory_pools">Custom memory pools</a></li>
<li class="level2"><a href="#defragmentation">Defragmentation</a></li> <li class="level2"><a href="#defragmentation">Defragmentation</a></li>
@ -85,38 +82,6 @@ $(function() {
<div class="textblock"><p><b>Version 2.0.0-alpha.3</b> (2017-09-12)</p> <div class="textblock"><p><b>Version 2.0.0-alpha.3</b> (2017-09-12)</p>
<p>Members grouped: see <a href="modules.html"><b>Modules</b></a>.</p> <p>Members grouped: see <a href="modules.html"><b>Modules</b></a>.</p>
<p>All members: see <a class="el" href="vk__mem__alloc_8h.html">vk_mem_alloc.h</a>.</p> <p>All members: see <a class="el" href="vk__mem__alloc_8h.html">vk_mem_alloc.h</a>.</p>
<h1><a class="anchor" id="problem"></a>
Problem statement</h1>
<p>Memory allocation and resource (buffer and image) creation in Vulkan is difficult (comparing to older graphics API-s, like D3D11 or OpenGL) for several reasons:</p>
<ul>
<li>It requires a lot of boilerplate code, just like everything else in Vulkan, because it is a low-level and high-performance API.</li>
<li>There is additional level of indirection: <code>VkDeviceMemory</code> is allocated separately from creating <code>VkBuffer</code>/<code>VkImage</code> and they must be bound together. The binding cannot be changed later - resource must be recreated.</li>
<li>Driver must be queried for supported memory heaps and memory types. Different IHV-s provide different types of it.</li>
<li>It is recommended practice to allocate bigger chunks of memory and assign parts of them to particular resources.</li>
</ul>
<h1><a class="anchor" id="features"></a>
Features</h1>
<p>This library is helps game developers to manage memory allocations and resource creation by offering some higher-level functions. Features of the library could be divided into several layers, low level to high level:</p>
<ol type="1">
<li>Functions that help to choose correct and optimal memory type based on intended usage of the memory.<ul>
<li>Required or preferred traits of the memory are expressed using higher-level description comparing to Vulkan flags.</li>
</ul>
</li>
<li>Functions that allocate memory blocks, reserve and return parts of them (<code>VkDeviceMemory</code> + offset + size) to the user.<ul>
<li>Library keeps track of allocated memory blocks, used and unused ranges inside them, finds best matching unused ranges for new allocations, takes all the rules of alignment into consideration.</li>
</ul>
</li>
<li>Functions that can create an image/buffer, allocate memory for it and bind them together - all in one call.</li>
</ol>
<h1><a class="anchor" id="prequisites"></a>
Prequisites</h1>
<ul>
<li>Self-contained C++ library in single header file. No external dependencies other than standard C and C++ library and of course Vulkan.</li>
<li>Public interface in C, in same convention as Vulkan API. Implementation in C++.</li>
<li>Interface documented using Doxygen-style comments.</li>
<li>Platform-independent, but developed and tested on Windows using Visual Studio.</li>
<li>Error handling implemented by returning <code>VkResult</code> error codes - same way as in Vulkan.</li>
</ul>
<h1><a class="anchor" id="user_guide"></a> <h1><a class="anchor" id="user_guide"></a>
User guide</h1> User guide</h1>
<h2><a class="anchor" id="quick_start"></a> <h2><a class="anchor" id="quick_start"></a>
@ -188,7 +153,7 @@ if((memFlags &amp; VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
memRange.size = allocInfo.size; memRange.size = allocInfo.size;
vkFlushMappedMemoryRanges(device, 1, &amp;memRange); vkFlushMappedMemoryRanges(device, 1, &amp;memRange);
} }
</pre><p>For performance reasons it is also recommended to unmap Vulkan memory for the time of call to <code>vkQueueSubmit()</code> or <code>vkQueuePresent()</code>. You can do it for all persistently mapped memory using just one function call. For details, see function <a class="el" href="group__layer2.html#ga26b87244491c1fe77f11fe9ab5779c27" title="Unmaps persistently mapped memory of types that are HOST_COHERENT and DEVICE_LOCAL. ">vmaUnmapPersistentlyMappedMemory()</a>, <a class="el" href="group__layer2.html#ga03366170bb8e186605518d2f5d65b85a" title="Maps back persistently mapped memory of types that are HOST_COHERENT and DEVICE_LOCAL. ">vmaMapPersistentlyMappedMemory()</a>.</p> </pre><p>On AMD GPUs on Windows, Vulkan memory from the type that has both <code>DEVICE_LOCAL</code> and <code>HOST_VISIBLE</code> flags should not be mapped for the time of any call to <code>vkQueueSubmit()</code> or <code>vkQueuePresent()</code>. Although legal, that would cause performance degradation because WDDM migrates such memory to system RAM. To ensure this, you can unmap all persistently mapped memory using just one function call. For details, see function <a class="el" href="group__layer2.html#ga26b87244491c1fe77f11fe9ab5779c27" title="Unmaps persistently mapped memory of types that are HOST_COHERENT and DEVICE_LOCAL. ">vmaUnmapPersistentlyMappedMemory()</a>, <a class="el" href="group__layer2.html#ga03366170bb8e186605518d2f5d65b85a" title="Maps back persistently mapped memory of types that are HOST_COHERENT and DEVICE_LOCAL. ">vmaMapPersistentlyMappedMemory()</a>.</p>
<h2><a class="anchor" id="custom_memory_pools"></a> <h2><a class="anchor" id="custom_memory_pools"></a>
Custom memory pools</h2> Custom memory pools</h2>
<p>The library automatically creates and manages default memory pool for each memory type available on the device. A pool contains a number of <code>VkDeviceMemory</code> blocks. You can create custom pool and allocate memory out of it. It can be useful if you want to:</p> <p>The library automatically creates and manages default memory pool for each memory type available on the device. A pool contains a number of <code>VkDeviceMemory</code> blocks. You can create custom pool and allocate memory out of it. It can be useful if you want to:</p>

View File

@ -279,11 +279,13 @@ Functions</h2></td></tr>
<tr class="memitem:gac72ee55598617e8eecca384e746bab51"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#gac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a> (VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, VkBuffer *pBuffer, VmaAllocation *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr> <tr class="memitem:gac72ee55598617e8eecca384e746bab51"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#gac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a> (VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, VkBuffer *pBuffer, VmaAllocation *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr>
<tr class="separator:gac72ee55598617e8eecca384e746bab51"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:gac72ee55598617e8eecca384e746bab51"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga0d9f4e4ba5bf9aab1f1c746387753d77"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#ga0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a> (VmaAllocator allocator, VkBuffer buffer, VmaAllocation allocation)</td></tr> <tr class="memitem:ga0d9f4e4ba5bf9aab1f1c746387753d77"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#ga0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a> (VmaAllocator allocator, VkBuffer buffer, VmaAllocation allocation)</td></tr>
<tr class="memdesc:ga0d9f4e4ba5bf9aab1f1c746387753d77"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroys Vulkan buffer and frees allocated memory. <a href="group__layer3.html#ga0d9f4e4ba5bf9aab1f1c746387753d77">More...</a><br /></td></tr>
<tr class="separator:ga0d9f4e4ba5bf9aab1f1c746387753d77"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga0d9f4e4ba5bf9aab1f1c746387753d77"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga02a94f25679275851a53e82eacbcfc73"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#ga02a94f25679275851a53e82eacbcfc73">vmaCreateImage</a> (VmaAllocator allocator, const VkImageCreateInfo *pImageCreateInfo, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, VkImage *pImage, VmaAllocation *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr> <tr class="memitem:ga02a94f25679275851a53e82eacbcfc73"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#ga02a94f25679275851a53e82eacbcfc73">vmaCreateImage</a> (VmaAllocator allocator, const VkImageCreateInfo *pImageCreateInfo, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, VkImage *pImage, VmaAllocation *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr>
<tr class="memdesc:ga02a94f25679275851a53e82eacbcfc73"><td class="mdescLeft">&#160;</td><td class="mdescRight">Function similar to <a class="el" href="group__layer3.html#gac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>. <a href="group__layer3.html#ga02a94f25679275851a53e82eacbcfc73">More...</a><br /></td></tr> <tr class="memdesc:ga02a94f25679275851a53e82eacbcfc73"><td class="mdescLeft">&#160;</td><td class="mdescRight">Function similar to <a class="el" href="group__layer3.html#gac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>. <a href="group__layer3.html#ga02a94f25679275851a53e82eacbcfc73">More...</a><br /></td></tr>
<tr class="separator:ga02a94f25679275851a53e82eacbcfc73"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga02a94f25679275851a53e82eacbcfc73"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#gae50d2cb3b4a3bfd4dd40987234e50e7e">vmaDestroyImage</a> (VmaAllocator allocator, VkImage image, VmaAllocation allocation)</td></tr> <tr class="memitem:gae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__layer3.html#gae50d2cb3b4a3bfd4dd40987234e50e7e">vmaDestroyImage</a> (VmaAllocator allocator, VkImage image, VmaAllocation allocation)</td></tr>
<tr class="memdesc:gae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroys Vulkan image and frees allocated memory. <a href="group__layer3.html#gae50d2cb3b4a3bfd4dd40987234e50e7e">More...</a><br /></td></tr>
<tr class="separator:gae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:gae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table> </table>
</div><!-- contents --> </div><!-- contents -->

File diff suppressed because one or more lines are too long

View File

@ -33,51 +33,6 @@ Members grouped: see <a href="modules.html"><b>Modules</b></a>.
All members: see vk_mem_alloc.h. All members: see vk_mem_alloc.h.
\section problem Problem statement
Memory allocation and resource (buffer and image) creation in Vulkan is
difficult (comparing to older graphics API-s, like D3D11 or OpenGL) for several
reasons:
- It requires a lot of boilerplate code, just like everything else in Vulkan,
because it is a low-level and high-performance API.
- There is additional level of indirection: `VkDeviceMemory` is allocated
separately from creating `VkBuffer`/`VkImage` and they must be bound together. The
binding cannot be changed later - resource must be recreated.
- Driver must be queried for supported memory heaps and memory types. Different
IHV-s provide different types of it.
- It is recommended practice to allocate bigger chunks of memory and assign
parts of them to particular resources.
\section features Features
This library is helps game developers to manage memory allocations and resource
creation by offering some higher-level functions. Features of the library could
be divided into several layers, low level to high level:
-# Functions that help to choose correct and optimal memory type based on
intended usage of the memory.
- Required or preferred traits of the memory are expressed using higher-level
description comparing to Vulkan flags.
-# Functions that allocate memory blocks, reserve and return parts of them
(`VkDeviceMemory` + offset + size) to the user.
- Library keeps track of allocated memory blocks, used and unused ranges
inside them, finds best matching unused ranges for new allocations, takes
all the rules of alignment into consideration.
-# Functions that can create an image/buffer, allocate memory for it and bind
them together - all in one call.
\section prequisites Prequisites
- Self-contained C++ library in single header file. No external dependencies
other than standard C and C++ library and of course Vulkan.
- Public interface in C, in same convention as Vulkan API. Implementation in
C++.
- Interface documented using Doxygen-style comments.
- Platform-independent, but developed and tested on Windows using Visual Studio.
- Error handling implemented by returning `VkResult` error codes - same way as in
Vulkan.
\section user_guide User guide \section user_guide User guide
\subsection quick_start Quick start \subsection quick_start Quick start
@ -181,10 +136,13 @@ not, you should call `vkInvalidateMappedMemoryRanges()` before reading and
vkFlushMappedMemoryRanges(device, 1, &memRange); vkFlushMappedMemoryRanges(device, 1, &memRange);
} }
For performance reasons it is also recommended to unmap Vulkan memory for the On AMD GPUs on Windows, Vulkan memory from the type that has both `DEVICE_LOCAL`
time of call to `vkQueueSubmit()` or `vkQueuePresent()`. You can do it for all and `HOST_VISIBLE` flags should not be mapped for the time of any call to
persistently mapped memory using just one function call. For details, see `vkQueueSubmit()` or `vkQueuePresent()`. Although legal, that would cause
function vmaUnmapPersistentlyMappedMemory(), vmaMapPersistentlyMappedMemory(). performance degradation because WDDM migrates such memory to system RAM.
To ensure this, you can unmap all persistently mapped memory using just one
function call. For details, see function
vmaUnmapPersistentlyMappedMemory(), vmaMapPersistentlyMappedMemory().
\subsection custom_memory_pools Custom memory pools \subsection custom_memory_pools Custom memory pools
@ -1058,10 +1016,13 @@ void vmaUnmapMemory(
/** \brief Unmaps persistently mapped memory of types that are `HOST_COHERENT` and `DEVICE_LOCAL`. /** \brief Unmaps persistently mapped memory of types that are `HOST_COHERENT` and `DEVICE_LOCAL`.
This is optional performance optimization. On Windows you should call it before This is optional performance optimization.
every call to `vkQueueSubmit` and `vkQueuePresent`. After which you can remap the On AMD GPUs on Windows, Vulkan memory from the type that has both `DEVICE_LOCAL`
allocations again using vmaMapPersistentlyMappedMemory(). This is because of the and `HOST_VISIBLE` flags should not be mapped for the time of any call to
internal behavior of WDDM. Example: `vkQueueSubmit()` or `vkQueuePresent()`. Although legal, that would cause
performance degradation because WDDM migrates such memory to system RAM.
To ensure this, you can unmap all persistently mapped memory using this function.
Example:
vmaUnmapPersistentlyMappedMemory(allocator); vmaUnmapPersistentlyMappedMemory(allocator);
@ -1222,6 +1183,14 @@ VkResult vmaCreateBuffer(
VmaAllocation* pAllocation, VmaAllocation* pAllocation,
VmaAllocationInfo* pAllocationInfo); VmaAllocationInfo* pAllocationInfo);
/** \brief Destroys Vulkan buffer and frees allocated memory.
This is just a convenience function equivalent to:
vkDestroyBuffer(device, buffer, allocationCallbacks);
vmaFreeMemory(allocator, allocation);
*/
void vmaDestroyBuffer( void vmaDestroyBuffer(
VmaAllocator allocator, VmaAllocator allocator,
VkBuffer buffer, VkBuffer buffer,
@ -1236,6 +1205,14 @@ VkResult vmaCreateImage(
VmaAllocation* pAllocation, VmaAllocation* pAllocation,
VmaAllocationInfo* pAllocationInfo); VmaAllocationInfo* pAllocationInfo);
/** \brief Destroys Vulkan image and frees allocated memory.
This is just a convenience function equivalent to:
vkDestroyImage(device, image, allocationCallbacks);
vmaFreeMemory(allocator, allocation);
*/
void vmaDestroyImage( void vmaDestroyImage(
VmaAllocator allocator, VmaAllocator allocator,
VkImage image, VkImage image,