Added feature: VmaAllocatorCreateInfo::pHeapSizeLimit.

This commit is contained in:
Adam Sawicki 2017-09-19 11:38:01 +02:00
parent a89a26c452
commit 118049cda8
12 changed files with 273 additions and 139 deletions

Binary file not shown.

View File

@ -170,6 +170,9 @@ $(function() {
<li>pfnFree
: <a class="el" href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">VmaDeviceMemoryCallbacks</a>
</li>
<li>pHeapSizeLimit
: <a class="el" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">VmaAllocatorCreateInfo</a>
</li>
<li>physicalDevice
: <a class="el" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">VmaAllocatorCreateInfo</a>
</li>

View File

@ -170,6 +170,9 @@ $(function() {
<li>pfnFree
: <a class="el" href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">VmaDeviceMemoryCallbacks</a>
</li>
<li>pHeapSizeLimit
: <a class="el" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">VmaAllocatorCreateInfo</a>
</li>
<li>physicalDevice
: <a class="el" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">VmaAllocatorCreateInfo</a>
</li>

View File

@ -73,7 +73,9 @@ $(function() {
<li class="level2"><a href="#lost_allocations">Lost allocations</a></li>
</ul>
</li>
<li class="level1"><a href="#configuration">Configuration</a><ul><li class="level2"><a href="#custom_memory_allocator">Custom memory allocator</a></li>
<li class="level1"><a href="#configuration">Configuration</a><ul><li class="level2"><a href="#custom_memory_allocator">Custom host memory allocator</a></li>
<li class="level2"><a href="#allocation_callbacks">Device memory allocation callbacks</a></li>
<li class="level2"><a href="#heap_memory_limit">Device heap memory limit</a></li>
</ul>
</li>
<li class="level1"><a href="#thread_safety">Thread safety</a></li>
@ -295,10 +297,16 @@ void MyBuffer::EnsureBuffer()
</ol>
<h1><a class="anchor" id="configuration"></a>
Configuration</h1>
<p>Please check "CONFIGURATION SECTION" in the code to find macros that you can define before each <code>#include</code> of this file or change directly in this file to provide your own implementation of basic facilities like assert, min and max functions, mutex etc. C++ STL is used by default, but changing these allows you to get rid of any STL usage if you want, as many game developers tend to do.</p>
<p>Please check "CONFIGURATION SECTION" in the code to find macros that you can define before each <code>#include</code> of this file or change directly in this file to provide your own implementation of basic facilities like assert, <code>min()</code> and <code>max()</code> functions, mutex etc. C++ STL is used by default, but changing these allows you to get rid of any STL usage if you want, as many game developers tend to do.</p>
<h2><a class="anchor" id="custom_memory_allocator"></a>
Custom memory allocator</h2>
<p>You can use custom memory allocator by filling optional member <a class="el" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d" title="Custom CPU memory allocation callbacks. ">VmaAllocatorCreateInfo::pAllocationCallbacks</a>. These functions will be passed to Vulkan, as well as used by the library itself to make any CPU-side allocations.</p>
Custom host memory allocator</h2>
<p>If you use custom allocator for CPU memory rather than default operator <code>new</code> and <code>delete</code> from C++, you can make this library using your allocator as well by filling optional member <a class="el" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d" title="Custom CPU memory allocation callbacks. ">VmaAllocatorCreateInfo::pAllocationCallbacks</a>. These functions will be passed to Vulkan, as well as used by the library itself to make any CPU-side allocations.</p>
<h2><a class="anchor" id="allocation_callbacks"></a>
Device memory allocation callbacks</h2>
<p>The library makes calls to <code>vkAllocateMemory()</code> and <code>vkFreeMemory()</code> internally. You can setup callbacks to be informed about these calls, e.g. for the purpose of gathering some statistics. To do it, fill optional member <a class="el" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e" title="Informative callbacks for vkAllocateMemory, vkFreeMemory. ">VmaAllocatorCreateInfo::pDeviceMemoryCallbacks</a>.</p>
<h2><a class="anchor" id="heap_memory_limit"></a>
Device heap memory limit</h2>
<p>If you want to test how your program behaves with limited amount of Vulkan device memory available (without switching your graphics card to one that really has smaller VRAM), you can use a feature of this library intended for this purpose. To do it, fill optional member <a class="el" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b" title="Either NULL or a pointer to an array of limits on maximum number of bytes that can be allocated out o...">VmaAllocatorCreateInfo::pHeapSizeLimit</a>.</p>
<h1><a class="anchor" id="thread_safety"></a>
Thread safety</h1>
<ul>

View File

@ -6,6 +6,7 @@ var searchData=
['pfn_5fvmafreedevicememoryfunction',['PFN_vmaFreeDeviceMemoryFunction',['../group__general.html#gaef2545dc2e9dd4f29ab9ba6ac6fe2f49',1,'vk_mem_alloc.h']]],
['pfnallocate',['pfnAllocate',['../struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb',1,'VmaDeviceMemoryCallbacks']]],
['pfnfree',['pfnFree',['../struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c',1,'VmaDeviceMemoryCallbacks']]],
['pheapsizelimit',['pHeapSizeLimit',['../struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b',1,'VmaAllocatorCreateInfo']]],
['physicaldevice',['physicalDevice',['../struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156',1,'VmaAllocatorCreateInfo']]],
['pmappeddata',['pMappedData',['../struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2',1,'VmaAllocationInfo']]],
['pool',['pool',['../struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150',1,'VmaAllocationCreateInfo']]],

View File

@ -1,7 +1,7 @@
var searchData=
[
['unusedbytes',['UnusedBytes',['../struct_vma_stat_info.html#a394d2aef4348cb58abf73764804b4f2d',1,'VmaStatInfo']]],
['unusedrangecount',['UnusedRangeCount',['../struct_vma_stat_info.html#a56c4fb4dba646479180b601854cde2a6',1,'VmaStatInfo::UnusedRangeCount()'],['../struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4',1,'VmaPoolStats::unusedRangeCount()']]],
['unusedrangecount',['unusedRangeCount',['../struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4',1,'VmaPoolStats::unusedRangeCount()'],['../struct_vma_stat_info.html#a56c4fb4dba646479180b601854cde2a6',1,'VmaStatInfo::UnusedRangeCount()']]],
['unusedrangesizeavg',['UnusedRangeSizeAvg',['../struct_vma_stat_info.html#a88ad9bdc2b3a98964a4d0c338c0c9060',1,'VmaStatInfo']]],
['unusedrangesizemax',['UnusedRangeSizeMax',['../struct_vma_stat_info.html#a10c52c0841f01ca704e8ddb1ea6a635d',1,'VmaStatInfo']]],
['unusedrangesizemin',['UnusedRangeSizeMin',['../struct_vma_stat_info.html#a07c508f42a4d3424bd0c259784a7f2d6',1,'VmaStatInfo']]],

View File

@ -4,6 +4,7 @@ var searchData=
['pdevicememorycallbacks',['pDeviceMemoryCallbacks',['../struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e',1,'VmaAllocatorCreateInfo']]],
['pfnallocate',['pfnAllocate',['../struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb',1,'VmaDeviceMemoryCallbacks']]],
['pfnfree',['pfnFree',['../struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c',1,'VmaDeviceMemoryCallbacks']]],
['pheapsizelimit',['pHeapSizeLimit',['../struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b',1,'VmaAllocatorCreateInfo']]],
['physicaldevice',['physicalDevice',['../struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156',1,'VmaAllocatorCreateInfo']]],
['pmappeddata',['pMappedData',['../struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2',1,'VmaAllocationInfo']]],
['pool',['pool',['../struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150',1,'VmaAllocationCreateInfo']]],

View File

@ -1,7 +1,7 @@
var searchData=
[
['unusedbytes',['UnusedBytes',['../struct_vma_stat_info.html#a394d2aef4348cb58abf73764804b4f2d',1,'VmaStatInfo']]],
['unusedrangecount',['UnusedRangeCount',['../struct_vma_stat_info.html#a56c4fb4dba646479180b601854cde2a6',1,'VmaStatInfo::UnusedRangeCount()'],['../struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4',1,'VmaPoolStats::unusedRangeCount()']]],
['unusedrangecount',['unusedRangeCount',['../struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4',1,'VmaPoolStats::unusedRangeCount()'],['../struct_vma_stat_info.html#a56c4fb4dba646479180b601854cde2a6',1,'VmaStatInfo::UnusedRangeCount()']]],
['unusedrangesizeavg',['UnusedRangeSizeAvg',['../struct_vma_stat_info.html#a88ad9bdc2b3a98964a4d0c338c0c9060',1,'VmaStatInfo']]],
['unusedrangesizemax',['UnusedRangeSizeMax',['../struct_vma_stat_info.html#a10c52c0841f01ca704e8ddb1ea6a635d',1,'VmaStatInfo']]],
['unusedrangesizemin',['UnusedRangeSizeMin',['../struct_vma_stat_info.html#a07c508f42a4d3424bd0c259784a7f2d6',1,'VmaStatInfo']]],

View File

@ -70,9 +70,10 @@ $(function() {
<tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7">frameInUseCount</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d">pAllocationCallbacks</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e">pDeviceMemoryCallbacks</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">physicalDevice</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">preferredLargeHeapBlockSize</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#ab435423d84d5ab26e2c347c51771f90a">preferredSmallHeapBlockSize</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">pHeapSizeLimit</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">physicalDevice</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">preferredLargeHeapBlockSize</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#ab435423d84d5ab26e2c347c51771f90a">preferredSmallHeapBlockSize</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
</table></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>

View File

@ -83,10 +83,10 @@ Public Attributes</h2></td></tr>
<tr class="memdesc:ad924ddd77b04039c88d0c09b0ffcd500"><td class="mdescLeft">&#160;</td><td class="mdescRight">Vulkan device. <a href="#ad924ddd77b04039c88d0c09b0ffcd500">More...</a><br /></td></tr>
<tr class="separator:ad924ddd77b04039c88d0c09b0ffcd500"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a8e4714298e3121cdd8b214a1ae7a637a"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">preferredLargeHeapBlockSize</a></td></tr>
<tr class="memdesc:a8e4714298e3121cdd8b214a1ae7a637a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Size of a single memory block to allocate for resources. <a href="#a8e4714298e3121cdd8b214a1ae7a637a">More...</a><br /></td></tr>
<tr class="memdesc:a8e4714298e3121cdd8b214a1ae7a637a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Preferred size of a single <code>VkDeviceMemory</code> block to be allocated from large heaps. <a href="#a8e4714298e3121cdd8b214a1ae7a637a">More...</a><br /></td></tr>
<tr class="separator:a8e4714298e3121cdd8b214a1ae7a637a"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ab435423d84d5ab26e2c347c51771f90a"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#ab435423d84d5ab26e2c347c51771f90a">preferredSmallHeapBlockSize</a></td></tr>
<tr class="memdesc:ab435423d84d5ab26e2c347c51771f90a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Size of a single memory block to allocate for resources from a small heap &lt;= 512 MB. <a href="#ab435423d84d5ab26e2c347c51771f90a">More...</a><br /></td></tr>
<tr class="memdesc:ab435423d84d5ab26e2c347c51771f90a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Preferred size of a single <code>VkDeviceMemory</code> block to be allocated from small heaps &lt;= 512 MB. <a href="#ab435423d84d5ab26e2c347c51771f90a">More...</a><br /></td></tr>
<tr class="separator:ab435423d84d5ab26e2c347c51771f90a"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a6e409087e3be55400d0e4ccbe43c608d"><td class="memItemLeft" align="right" valign="top">const VkAllocationCallbacks *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d">pAllocationCallbacks</a></td></tr>
<tr class="memdesc:a6e409087e3be55400d0e4ccbe43c608d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Custom CPU memory allocation callbacks. <a href="#a6e409087e3be55400d0e4ccbe43c608d">More...</a><br /></td></tr>
@ -97,6 +97,9 @@ Public Attributes</h2></td></tr>
<tr class="memitem:a21ea188dd212b8171cb9ecbed4a2a3a7"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7">frameInUseCount</a></td></tr>
<tr class="memdesc:a21ea188dd212b8171cb9ecbed4a2a3a7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Maximum number of additional frames that are in use at the same time as current frame. <a href="#a21ea188dd212b8171cb9ecbed4a2a3a7">More...</a><br /></td></tr>
<tr class="separator:a21ea188dd212b8171cb9ecbed4a2a3a7"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a31c192aa6cbffa33279f6d9f0c47c44b"><td class="memItemLeft" align="right" valign="top">const VkDeviceSize *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">pHeapSizeLimit</a></td></tr>
<tr class="memdesc:a31c192aa6cbffa33279f6d9f0c47c44b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Either NULL or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap. <a href="#a31c192aa6cbffa33279f6d9f0c47c44b">More...</a><br /></td></tr>
<tr class="separator:a31c192aa6cbffa33279f6d9f0c47c44b"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<div class="textblock"><p>Description of a Allocator to be created. </p>
@ -185,6 +188,29 @@ Public Attributes</h2></td></tr>
<p>Informative callbacks for vkAllocateMemory, vkFreeMemory. </p>
<p>Optional, can be null. </p>
</div>
</div>
<a id="a31c192aa6cbffa33279f6d9f0c47c44b"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a31c192aa6cbffa33279f6d9f0c47c44b">&#9670;&nbsp;</a></span>pHeapSizeLimit</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">const VkDeviceSize* VmaAllocatorCreateInfo::pHeapSizeLimit</td>
</tr>
</table>
</div><div class="memdoc">
<p>Either NULL or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap. </p>
<p>If not NULL, it must be a pointer to an array of <code>VkPhysicalDeviceMemoryProperties::memoryHeapCount</code> elements, defining limit on maximum number of bytes that can be allocated out of particular Vulkan memory heap.</p>
<p>Any of the elements may be equal to <code>VK_WHOLE_SIZE</code>, which means no limit on that heap. This is also the default in case of <code>pHeapSizeLimit</code> = NULL.</p>
<p>If there is a limit defined for a heap:</p>
<ul>
<li>If user tries to allocate more memory from that heap using this allocator, the allocation fails with <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code>.</li>
<li>If the limit is smaller than heap size reported in <code>VkMemoryHeap::size</code>, the value of this limit will be reported instead when using <a class="el" href="group__general.html#gab88db292a17974f911182543fda52d19">vmaGetMemoryProperties()</a>. </li>
</ul>
</div>
</div>
<a id="a08230f04ae6ccf8a78150a9e829a7156"></a>
@ -216,7 +242,7 @@ Public Attributes</h2></td></tr>
</table>
</div><div class="memdoc">
<p>Size of a single memory block to allocate for resources. </p>
<p>Preferred size of a single <code>VkDeviceMemory</code> block to be allocated from large heaps. </p>
<p>Set to 0 to use default, which is currently 256 MB. </p>
</div>
@ -233,7 +259,7 @@ Public Attributes</h2></td></tr>
</table>
</div><div class="memdoc">
<p>Size of a single memory block to allocate for resources from a small heap &lt;= 512 MB. </p>
<p>Preferred size of a single <code>VkDeviceMemory</code> block to be allocated from small heaps &lt;= 512 MB. </p>
<p>Set to 0 to use default, which is currently 64 MB. </p>
</div>

File diff suppressed because one or more lines are too long

View File

@ -374,15 +374,31 @@ The library uses following algorithm for allocation, in order:
Please check "CONFIGURATION SECTION" in the code to find macros that you can define
before each `#include` of this file or change directly in this file to provide
your own implementation of basic facilities like assert, min and max functions,
your own implementation of basic facilities like assert, `min()` and `max()` functions,
mutex etc. C++ STL is used by default, but changing these allows you to get rid
of any STL usage if you want, as many game developers tend to do.
\subsection custom_memory_allocator Custom memory allocator
\subsection custom_memory_allocator Custom host memory allocator
You can use custom memory allocator by filling optional member
VmaAllocatorCreateInfo::pAllocationCallbacks. These functions will be passed to
Vulkan, as well as used by the library itself to make any CPU-side allocations.
If you use custom allocator for CPU memory rather than default operator `new`
and `delete` from C++, you can make this library using your allocator as well
by filling optional member VmaAllocatorCreateInfo::pAllocationCallbacks. These
functions will be passed to Vulkan, as well as used by the library itself to
make any CPU-side allocations.
\subsection allocation_callbacks Device memory allocation callbacks
The library makes calls to `vkAllocateMemory()` and `vkFreeMemory()` internally.
You can setup callbacks to be informed about these calls, e.g. for the purpose
of gathering some statistics. To do it, fill optional member
VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.
\subsection heap_memory_limit Device heap memory limit
If you want to test how your program behaves with limited amount of Vulkan device
memory available (without switching your graphics card to one that really has
smaller VRAM), you can use a feature of this library intended for this purpose.
To do it, fill optional member VmaAllocatorCreateInfo::pHeapSizeLimit.
\section thread_safety Thread safety
@ -458,10 +474,10 @@ typedef struct VmaAllocatorCreateInfo
/// Vulkan device.
/** It must be valid throughout whole lifetime of created allocator. */
VkDevice device;
/// Size of a single memory block to allocate for resources.
/// Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps.
/** Set to 0 to use default, which is currently 256 MB. */
VkDeviceSize preferredLargeHeapBlockSize;
/// Size of a single memory block to allocate for resources from a small heap <= 512 MB.
/// Preferred size of a single `VkDeviceMemory` block to be allocated from small heaps <= 512 MB.
/** Set to 0 to use default, which is currently 64 MB. */
VkDeviceSize preferredSmallHeapBlockSize;
/// Custom CPU memory allocation callbacks.
@ -484,6 +500,24 @@ typedef struct VmaAllocatorCreateInfo
become lost, set this value to 0.
*/
uint32_t frameInUseCount;
/** \brief Either NULL or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap.
If not NULL, it must be a pointer to an array of
`VkPhysicalDeviceMemoryProperties::memoryHeapCount` elements, defining limit on
maximum number of bytes that can be allocated out of particular Vulkan memory
heap.
Any of the elements may be equal to `VK_WHOLE_SIZE`, which means no limit on that
heap. This is also the default in case of `pHeapSizeLimit` = NULL.
If there is a limit defined for a heap:
- If user tries to allocate more memory from that heap using this allocator,
the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
- If the limit is smaller than heap size reported in `VkMemoryHeap::size`, the
value of this limit will be reported instead when using vmaGetMemoryProperties().
*/
const VkDeviceSize* pHeapSizeLimit;
} VmaAllocatorCreateInfo;
/// Creates Allocator object.
@ -3372,6 +3406,10 @@ struct VmaAllocator_T
// Non-zero when we are inside UnmapPersistentlyMappedMemory...MapPersistentlyMappedMemory.
// Counter to allow nested calls to these functions.
uint32_t m_UnmapPersistentlyMappedMemoryCounter;
// Number of bytes free out of limit, or VK_WHOLE_SIZE if not limit for that heap.
VkDeviceSize m_HeapSizeLimit[VK_MAX_MEMORY_HEAPS];
VMA_MUTEX m_HeapSizeLimitMutex;
VkPhysicalDeviceProperties m_PhysicalDeviceProperties;
VkPhysicalDeviceMemoryProperties m_MemProps;
@ -3448,6 +3486,9 @@ struct VmaAllocator_T
void CreateLostAllocation(VmaAllocation* pAllocation);
VkResult AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory);
void FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory);
private:
VkDeviceSize m_PreferredLargeHeapBlockSize;
VkDeviceSize m_PreferredSmallHeapBlockSize;
@ -4129,13 +4170,7 @@ void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator)
m_pMappedData = VMA_NULL;
}
// Callback.
if(allocator->m_DeviceMemoryCallbacks.pfnFree != VMA_NULL)
{
(*allocator->m_DeviceMemoryCallbacks.pfnFree)(allocator, m_MemoryTypeIndex, m_hMemory, m_Size);
}
vkFreeMemory(allocator->m_hDevice, m_hMemory, allocator->GetAllocationCallbacks());
allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_Size, m_hMemory);
m_hMemory = VK_NULL_HANDLE;
}
@ -5436,7 +5471,7 @@ VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIn
allocInfo.allocationSize = blockSize;
const VkDevice hDevice = m_hAllocator->m_hDevice;
VkDeviceMemory mem = VK_NULL_HANDLE;
VkResult res = vkAllocateMemory(hDevice, &allocInfo, m_hAllocator->GetAllocationCallbacks(), &mem);
VkResult res = m_hAllocator->AllocateVulkanMemory(&allocInfo, &mem);
if(res < 0)
{
return res;
@ -5453,17 +5488,11 @@ VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIn
if(res < 0)
{
VMA_DEBUG_LOG(" vkMapMemory FAILED");
vkFreeMemory(hDevice, mem, m_hAllocator->GetAllocationCallbacks());
m_hAllocator->FreeVulkanMemory(m_MemoryTypeIndex, blockSize, mem);
return res;
}
}
// Callback.
if(m_hAllocator->m_DeviceMemoryCallbacks.pfnAllocate != VMA_NULL)
{
(*m_hAllocator->m_DeviceMemoryCallbacks.pfnAllocate)(m_hAllocator, m_MemoryTypeIndex, mem, allocInfo.allocationSize);
}
// Create new Allocation for it.
VmaDeviceMemoryBlock* const pBlock = vma_new(m_hAllocator, VmaDeviceMemoryBlock)(m_hAllocator);
pBlock->Init(
@ -5978,6 +6007,11 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
memset(&m_pBlockVectors, 0, sizeof(m_pBlockVectors));
memset(&m_pOwnAllocations, 0, sizeof(m_pOwnAllocations));
for(uint32_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i)
{
m_HeapSizeLimit[i] = VK_WHOLE_SIZE;
}
if(pCreateInfo->pDeviceMemoryCallbacks != VMA_NULL)
{
m_DeviceMemoryCallbacks.pfnAllocate = pCreateInfo->pDeviceMemoryCallbacks->pfnAllocate;
@ -5992,6 +6026,22 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
m_PreferredSmallHeapBlockSize = (pCreateInfo->preferredSmallHeapBlockSize != 0) ?
pCreateInfo->preferredSmallHeapBlockSize : static_cast<VkDeviceSize>(VMA_DEFAULT_SMALL_HEAP_BLOCK_SIZE);
if(pCreateInfo->pHeapSizeLimit != VMA_NULL)
{
for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex)
{
const VkDeviceSize limit = pCreateInfo->pHeapSizeLimit[heapIndex];
if(limit != VK_WHOLE_SIZE)
{
m_HeapSizeLimit[heapIndex] = limit;
if(limit < m_MemProps.memoryHeaps[heapIndex].size)
{
m_MemProps.memoryHeaps[heapIndex].size = limit;
}
}
}
}
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
{
const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(memTypeIndex);
@ -6031,7 +6081,8 @@ VmaAllocator_T::~VmaAllocator_T()
VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex)
{
const VkDeviceSize heapSize = m_MemProps.memoryHeaps[MemoryTypeIndexToHeapIndex(memTypeIndex)].size;
const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size;
return (heapSize <= VMA_SMALL_HEAP_MAX_SIZE) ?
m_PreferredSmallHeapBlockSize : m_PreferredLargeHeapBlockSize;
}
@ -6128,7 +6179,7 @@ VkResult VmaAllocator_T::AllocateOwnMemory(
// Allocate VkDeviceMemory.
VkDeviceMemory hMemory = VK_NULL_HANDLE;
VkResult res = vkAllocateMemory(m_hDevice, &allocInfo, GetAllocationCallbacks(), &hMemory);
VkResult res = AllocateVulkanMemory(&allocInfo, &hMemory);
if(res < 0)
{
VMA_DEBUG_LOG(" vkAllocateMemory FAILED");
@ -6144,18 +6195,12 @@ VkResult VmaAllocator_T::AllocateOwnMemory(
if(res < 0)
{
VMA_DEBUG_LOG(" vkMapMemory FAILED");
vkFreeMemory(m_hDevice, hMemory, GetAllocationCallbacks());
FreeVulkanMemory(memTypeIndex, size, hMemory);
return res;
}
}
}
// Callback.
if(m_DeviceMemoryCallbacks.pfnAllocate != VMA_NULL)
{
(*m_DeviceMemoryCallbacks.pfnAllocate)(this, memTypeIndex, hMemory, size);
}
*pAllocation = vma_new(this, VmaAllocation_T)(m_CurrentFrameIndex.load());
(*pAllocation)->InitOwnAllocation(memTypeIndex, hMemory, suballocType, map, pMappedData, size, pUserData);
@ -6695,6 +6740,57 @@ void VmaAllocator_T::CreateLostAllocation(VmaAllocation* pAllocation)
(*pAllocation)->InitLost();
}
VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory)
{
const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(pAllocateInfo->memoryTypeIndex);
VkResult res;
if(m_HeapSizeLimit[heapIndex] != VK_WHOLE_SIZE)
{
VmaMutexLock lock(m_HeapSizeLimitMutex, m_UseMutex);
if(m_HeapSizeLimit[heapIndex] >= pAllocateInfo->allocationSize)
{
res = vkAllocateMemory(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory);
if(res == VK_SUCCESS)
{
m_HeapSizeLimit[heapIndex] -= pAllocateInfo->allocationSize;
}
}
else
{
res = VK_ERROR_OUT_OF_DEVICE_MEMORY;
}
}
else
{
res = vkAllocateMemory(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory);
}
if(res == VK_SUCCESS && m_DeviceMemoryCallbacks.pfnAllocate != VMA_NULL)
{
(*m_DeviceMemoryCallbacks.pfnAllocate)(this, pAllocateInfo->memoryTypeIndex, *pMemory, pAllocateInfo->allocationSize);
}
return res;
}
void VmaAllocator_T::FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory)
{
if(m_DeviceMemoryCallbacks.pfnFree != VMA_NULL)
{
(*m_DeviceMemoryCallbacks.pfnFree)(this, memoryType, hMemory, size);
}
vkFreeMemory(m_hDevice, hMemory, GetAllocationCallbacks());
const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memoryType);
if(m_HeapSizeLimit[heapIndex] != VK_WHOLE_SIZE)
{
VmaMutexLock lock(m_HeapSizeLimitMutex, m_UseMutex);
m_HeapSizeLimit[heapIndex] += size;
}
}
void VmaAllocator_T::FreeOwnMemory(VmaAllocation allocation)
{
VMA_ASSERT(allocation && allocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_OWN);
@ -6710,18 +6806,12 @@ void VmaAllocator_T::FreeOwnMemory(VmaAllocation allocation)
VkDeviceMemory hMemory = allocation->GetMemory();
// Callback.
if(m_DeviceMemoryCallbacks.pfnFree != VMA_NULL)
{
(*m_DeviceMemoryCallbacks.pfnFree)(this, memTypeIndex, hMemory, allocation->GetSize());
}
if(allocation->GetMappedData() != VMA_NULL)
{
vkUnmapMemory(m_hDevice, hMemory);
}
vkFreeMemory(m_hDevice, hMemory, GetAllocationCallbacks());
FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory);
VMA_DEBUG_LOG(" Freed OwnMemory MemoryTypeIndex=%u", memTypeIndex);
}