Improved support for non-coherent memory. Added functions: vmaFlushAllocation, vmaInvalidateAllocation. nonCoherentAtomSize is respected automatically. Issue #27 Thanks @egdaniel !

Also added VmaVulkanFunctions::vkFlushMappedMemoryRanges, vkInvalidateMappedMemoryRanges. Fixed bug with uninitialized VmaPool_T::m_Id.
This commit is contained in:
Adam Sawicki 2018-06-08 17:11:12 +02:00
parent 5aa99be043
commit 776ae0d5f8
15 changed files with 521 additions and 171 deletions

View File

@ -41,6 +41,7 @@ Additional features:
- Configuration: Fill optional members of CreateInfo structure to provide custom CPU memory allocator, pointers to Vulkan functions 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 memory mapping, reference-counted internally. Support for persistently mapped memory: Just allocate with appropriate flag and you get access to mapped pointer.
- Support for non-coherent memory. Functions that flush/invalidate memory. nonCoherentAtomSize is respected automatically.
- Custom memory pools: Create a pool with desired parameters (e.g. fixed or limited maximum size) and allocate memory out of it.
- Support for VK_KHR_dedicated_allocation extension: Just enable it and it will be used automatically by the library.
- Defragmentation: Call one function and let the library move data around to free some memory blocks and make your allocations better compacted.

View File

@ -273,6 +273,9 @@ $(function() {
<li>vkDestroyImage
: <a class="el" href="struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa">VmaVulkanFunctions</a>
</li>
<li>vkFlushMappedMemoryRanges
: <a class="el" href="struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9">VmaVulkanFunctions</a>
</li>
<li>vkFreeMemory
: <a class="el" href="struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4">VmaVulkanFunctions</a>
</li>
@ -288,6 +291,9 @@ $(function() {
<li>vkGetPhysicalDeviceProperties
: <a class="el" href="struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96">VmaVulkanFunctions</a>
</li>
<li>vkInvalidateMappedMemoryRanges
: <a class="el" href="struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1">VmaVulkanFunctions</a>
</li>
<li>vkMapMemory
: <a class="el" href="struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49">VmaVulkanFunctions</a>
</li>

View File

@ -273,6 +273,9 @@ $(function() {
<li>vkDestroyImage
: <a class="el" href="struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa">VmaVulkanFunctions</a>
</li>
<li>vkFlushMappedMemoryRanges
: <a class="el" href="struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9">VmaVulkanFunctions</a>
</li>
<li>vkFreeMemory
: <a class="el" href="struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4">VmaVulkanFunctions</a>
</li>
@ -288,6 +291,9 @@ $(function() {
<li>vkGetPhysicalDeviceProperties
: <a class="el" href="struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96">VmaVulkanFunctions</a>
</li>
<li>vkInvalidateMappedMemoryRanges
: <a class="el" href="struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1">VmaVulkanFunctions</a>
</li>
<li>vkMapMemory
: <a class="el" href="struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49">VmaVulkanFunctions</a>
</li>

View File

@ -221,6 +221,9 @@ $(function() {
<li>vmaFindMemoryTypeIndexForImageInfo()
: <a class="el" href="vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472">vk_mem_alloc.h</a>
</li>
<li>vmaFlushAllocation()
: <a class="el" href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de">vk_mem_alloc.h</a>
</li>
<li>vmaFreeMemory()
: <a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568">vk_mem_alloc.h</a>
</li>
@ -242,6 +245,9 @@ $(function() {
<li>vmaGetPoolStats()
: <a class="el" href="vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153">vk_mem_alloc.h</a>
</li>
<li>vmaInvalidateAllocation()
: <a class="el" href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006">vk_mem_alloc.h</a>
</li>
<li>vmaMakePoolAllocationsLost()
: <a class="el" href="vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024">vk_mem_alloc.h</a>
</li>

View File

@ -121,6 +121,9 @@ $(function() {
<li>vmaFindMemoryTypeIndexForImageInfo()
: <a class="el" href="vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472">vk_mem_alloc.h</a>
</li>
<li>vmaFlushAllocation()
: <a class="el" href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de">vk_mem_alloc.h</a>
</li>
<li>vmaFreeMemory()
: <a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568">vk_mem_alloc.h</a>
</li>
@ -142,6 +145,9 @@ $(function() {
<li>vmaGetPoolStats()
: <a class="el" href="vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153">vk_mem_alloc.h</a>
</li>
<li>vmaInvalidateAllocation()
: <a class="el" href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006">vk_mem_alloc.h</a>
</li>
<li>vmaMakePoolAllocationsLost()
: <a class="el" href="vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024">vk_mem_alloc.h</a>
</li>

View File

@ -62,7 +62,7 @@ $(function() {
<div class="title">Vulkan Memory Allocator </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><b>Version 2.0.0</b> (2018-03-19)</p>
<div class="textblock"><p><b>Version 2.1.0-alpha.1</b> (2018-06-04)</p>
<p>Copyright (c) 2017-2018 Advanced Micro Devices, Inc. All rights reserved. <br />
License: MIT</p>
<p>Documentation of all members: <a class="el" href="vk__mem__alloc_8h.html">vk_mem_alloc.h</a></p>

View File

@ -80,9 +80,10 @@ Persistently mapped memory</h1>
</ul>
<h1><a class="anchor" id="memory_mapping_cache_control"></a>
Cache control</h1>
<p>Memory in Vulkan doesn't need to be unmapped before using it on GPU, but unless a memory types has <code>VK_MEMORY_PROPERTY_HOST_COHERENT_BIT</code> flag set, you need to manually invalidate cache before reading of mapped pointer using function <code>vkvkInvalidateMappedMemoryRanges()</code> and flush cache after writing to mapped pointer using function <code>vkFlushMappedMemoryRanges()</code>. Example:</p>
<div class="fragment"><div class="line">memcpy(allocInfo.<a class="code" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a>, &amp;constantBufferData, <span class="keyword">sizeof</span>(constantBufferData));</div><div class="line"></div><div class="line">VkMemoryPropertyFlags memFlags;</div><div class="line"><a class="code" href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca">vmaGetMemoryTypeProperties</a>(allocator, allocInfo.<a class="code" href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">memoryType</a>, &amp;memFlags);</div><div class="line"><span class="keywordflow">if</span>((memFlags &amp; VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)</div><div class="line">{</div><div class="line"> VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };</div><div class="line"> memRange.memory = allocInfo.<a class="code" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67">deviceMemory</a>;</div><div class="line"> memRange.offset = allocInfo.<a class="code" href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268">offset</a>;</div><div class="line"> memRange.size = allocInfo.<a class="code" href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f">size</a>;</div><div class="line"> vkFlushMappedMemoryRanges(device, 1, &amp;memRange);</div><div class="line">}</div></div><!-- fragment --><p>Please note that memory allocated with <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a> is guaranteed to be host coherent.</p>
<p>Also, Windows drivers from all 3 PC GPU vendors (AMD, Intel, NVIDIA) currently provide <code>VK_MEMORY_PROPERTY_HOST_COHERENT_BIT</code> flag on all memory types that are <code>VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT</code>, so on this platform you may not need to bother.</p>
<p>Memory in Vulkan doesn't need to be unmapped before using it on GPU, but unless a memory types has <code>VK_MEMORY_PROPERTY_HOST_COHERENT_BIT</code> flag set, you need to manually invalidate cache before reading of mapped pointer and flush cache after writing to mapped pointer. Vulkan provides following functions for this purpose <code>vkFlushMappedMemoryRanges()</code>, <code>vkInvalidateMappedMemoryRanges()</code>, but this library provides more convenient functions that refer to given allocation object: <a class="el" href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de" title="Flushes memory of given allocation. ">vmaFlushAllocation()</a>, <a class="el" href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006" title="Invalidates memory of given allocation. ">vmaInvalidateAllocation()</a>.</p>
<p>Regions of memory specified for flush/invalidate must be aligned to <code>VkPhysicalDeviceLimits::nonCoherentAtomSize</code>. This is automatically ensured by the library. In any memory type that is <code>HOST_VISIBLE</code> but not <code>HOST_COHERENT</code>, all allocations within blocks are aligned to this value, so their offsets are always multiply of <code>nonCoherentAtomSize</code> and two different allocations never share same "line" of this size.</p>
<p>Please note that memory allocated with <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a> is guaranteed to be <code>HOST_COHERENT</code>.</p>
<p>Also, Windows drivers from all 3 PC GPU vendors (AMD, Intel, NVIDIA) currently provide <code>HOST_COHERENT</code> flag on all memory types that are <code>HOST_VISIBLE</code>, so on this platform you may not need to bother.</p>
<h1><a class="anchor" id="memory_mapping_finding_if_memory_mappable"></a>
Finding out if memory is mappable</h1>
<p>It may happen that your allocation ends up in memory that is <code>HOST_VISIBLE</code> (available for mapping) despite it wasn't explicitly requested. For example, application may work on integrated graphics with unified memory (like Intel) or allocation from video memory might have failed, so the library chose system memory as fallback.</p>

View File

@ -10,11 +10,13 @@ var searchData=
['vkcreateimage',['vkCreateImage',['../struct_vma_vulkan_functions.html#a23ebe70be515b9b5010a1d691200e325',1,'VmaVulkanFunctions']]],
['vkdestroybuffer',['vkDestroyBuffer',['../struct_vma_vulkan_functions.html#a7e054606faddb07f0e8556f3ed317d45',1,'VmaVulkanFunctions']]],
['vkdestroyimage',['vkDestroyImage',['../struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa',1,'VmaVulkanFunctions']]],
['vkflushmappedmemoryranges',['vkFlushMappedMemoryRanges',['../struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9',1,'VmaVulkanFunctions']]],
['vkfreememory',['vkFreeMemory',['../struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4',1,'VmaVulkanFunctions']]],
['vkgetbuffermemoryrequirements',['vkGetBufferMemoryRequirements',['../struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143',1,'VmaVulkanFunctions']]],
['vkgetimagememoryrequirements',['vkGetImageMemoryRequirements',['../struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4',1,'VmaVulkanFunctions']]],
['vkgetphysicaldevicememoryproperties',['vkGetPhysicalDeviceMemoryProperties',['../struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830',1,'VmaVulkanFunctions']]],
['vkgetphysicaldeviceproperties',['vkGetPhysicalDeviceProperties',['../struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96',1,'VmaVulkanFunctions']]],
['vkinvalidatemappedmemoryranges',['vkInvalidateMappedMemoryRanges',['../struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1',1,'VmaVulkanFunctions']]],
['vkmapmemory',['vkMapMemory',['../struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49',1,'VmaVulkanFunctions']]],
['vkunmapmemory',['vkUnmapMemory',['../struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9',1,'VmaVulkanFunctions']]],
['vma_5fallocation_5fcreate_5fcan_5fbecome_5flost_5fbit',['VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2',1,'vk_mem_alloc.h']]],
@ -69,6 +71,7 @@ var searchData=
['vmafindmemorytypeindex',['vmaFindMemoryTypeIndex',['../vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a',1,'vk_mem_alloc.h']]],
['vmafindmemorytypeindexforbufferinfo',['vmaFindMemoryTypeIndexForBufferInfo',['../vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888',1,'vk_mem_alloc.h']]],
['vmafindmemorytypeindexforimageinfo',['vmaFindMemoryTypeIndexForImageInfo',['../vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472',1,'vk_mem_alloc.h']]],
['vmaflushallocation',['vmaFlushAllocation',['../vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de',1,'vk_mem_alloc.h']]],
['vmafreememory',['vmaFreeMemory',['../vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568',1,'vk_mem_alloc.h']]],
['vmafreestatsstring',['vmaFreeStatsString',['../vk__mem__alloc_8h.html#a3104eb30d8122c84dd8541063f145288',1,'vk_mem_alloc.h']]],
['vmagetallocationinfo',['vmaGetAllocationInfo',['../vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b',1,'vk_mem_alloc.h']]],
@ -76,6 +79,7 @@ var searchData=
['vmagetmemorytypeproperties',['vmaGetMemoryTypeProperties',['../vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca',1,'vk_mem_alloc.h']]],
['vmagetphysicaldeviceproperties',['vmaGetPhysicalDeviceProperties',['../vk__mem__alloc_8h.html#aecabf7b6e91ea87d0316fa0a9e014fe0',1,'vk_mem_alloc.h']]],
['vmagetpoolstats',['vmaGetPoolStats',['../vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153',1,'vk_mem_alloc.h']]],
['vmainvalidateallocation',['vmaInvalidateAllocation',['../vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006',1,'vk_mem_alloc.h']]],
['vmamakepoolallocationslost',['vmaMakePoolAllocationsLost',['../vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024',1,'vk_mem_alloc.h']]],
['vmamapmemory',['vmaMapMemory',['../vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069',1,'vk_mem_alloc.h']]],
['vmamemoryusage',['VmaMemoryUsage',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc',1,'VmaMemoryUsage():&#160;vk_mem_alloc.h'],['../vk__mem__alloc_8h.html#ad63b2113c0bfdbeade1cb498f5a8580d',1,'VmaMemoryUsage():&#160;vk_mem_alloc.h']]],

View File

@ -20,6 +20,7 @@ var searchData=
['vmafindmemorytypeindex',['vmaFindMemoryTypeIndex',['../vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a',1,'vk_mem_alloc.h']]],
['vmafindmemorytypeindexforbufferinfo',['vmaFindMemoryTypeIndexForBufferInfo',['../vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888',1,'vk_mem_alloc.h']]],
['vmafindmemorytypeindexforimageinfo',['vmaFindMemoryTypeIndexForImageInfo',['../vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472',1,'vk_mem_alloc.h']]],
['vmaflushallocation',['vmaFlushAllocation',['../vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de',1,'vk_mem_alloc.h']]],
['vmafreememory',['vmaFreeMemory',['../vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568',1,'vk_mem_alloc.h']]],
['vmafreestatsstring',['vmaFreeStatsString',['../vk__mem__alloc_8h.html#a3104eb30d8122c84dd8541063f145288',1,'vk_mem_alloc.h']]],
['vmagetallocationinfo',['vmaGetAllocationInfo',['../vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b',1,'vk_mem_alloc.h']]],
@ -27,6 +28,7 @@ var searchData=
['vmagetmemorytypeproperties',['vmaGetMemoryTypeProperties',['../vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca',1,'vk_mem_alloc.h']]],
['vmagetphysicaldeviceproperties',['vmaGetPhysicalDeviceProperties',['../vk__mem__alloc_8h.html#aecabf7b6e91ea87d0316fa0a9e014fe0',1,'vk_mem_alloc.h']]],
['vmagetpoolstats',['vmaGetPoolStats',['../vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153',1,'vk_mem_alloc.h']]],
['vmainvalidateallocation',['vmaInvalidateAllocation',['../vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006',1,'vk_mem_alloc.h']]],
['vmamakepoolallocationslost',['vmaMakePoolAllocationsLost',['../vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024',1,'vk_mem_alloc.h']]],
['vmamapmemory',['vmaMapMemory',['../vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069',1,'vk_mem_alloc.h']]],
['vmasetallocationuserdata',['vmaSetAllocationUserData',['../vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f',1,'vk_mem_alloc.h']]],

View File

@ -7,11 +7,13 @@ var searchData=
['vkcreateimage',['vkCreateImage',['../struct_vma_vulkan_functions.html#a23ebe70be515b9b5010a1d691200e325',1,'VmaVulkanFunctions']]],
['vkdestroybuffer',['vkDestroyBuffer',['../struct_vma_vulkan_functions.html#a7e054606faddb07f0e8556f3ed317d45',1,'VmaVulkanFunctions']]],
['vkdestroyimage',['vkDestroyImage',['../struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa',1,'VmaVulkanFunctions']]],
['vkflushmappedmemoryranges',['vkFlushMappedMemoryRanges',['../struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9',1,'VmaVulkanFunctions']]],
['vkfreememory',['vkFreeMemory',['../struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4',1,'VmaVulkanFunctions']]],
['vkgetbuffermemoryrequirements',['vkGetBufferMemoryRequirements',['../struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143',1,'VmaVulkanFunctions']]],
['vkgetimagememoryrequirements',['vkGetImageMemoryRequirements',['../struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4',1,'VmaVulkanFunctions']]],
['vkgetphysicaldevicememoryproperties',['vkGetPhysicalDeviceMemoryProperties',['../struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830',1,'VmaVulkanFunctions']]],
['vkgetphysicaldeviceproperties',['vkGetPhysicalDeviceProperties',['../struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96',1,'VmaVulkanFunctions']]],
['vkinvalidatemappedmemoryranges',['vkInvalidateMappedMemoryRanges',['../struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1',1,'VmaVulkanFunctions']]],
['vkmapmemory',['vkMapMemory',['../struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49',1,'VmaVulkanFunctions']]],
['vkunmapmemory',['vkUnmapMemory',['../struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9',1,'VmaVulkanFunctions']]]
];

View File

@ -72,11 +72,13 @@ $(function() {
<tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a23ebe70be515b9b5010a1d691200e325">vkCreateImage</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a7e054606faddb07f0e8556f3ed317d45">vkDestroyBuffer</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa">vkDestroyImage</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4">vkFreeMemory</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143">vkGetBufferMemoryRequirements</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4">vkGetImageMemoryRequirements</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830">vkGetPhysicalDeviceMemoryProperties</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96">vkGetPhysicalDeviceProperties</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9">vkFlushMappedMemoryRanges</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4">vkFreeMemory</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143">vkGetBufferMemoryRequirements</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4">vkGetImageMemoryRequirements</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830">vkGetPhysicalDeviceMemoryProperties</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96">vkGetPhysicalDeviceProperties</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1">vkInvalidateMappedMemoryRanges</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49">vkMapMemory</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
<tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9">vkUnmapMemory</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
</table></div><!-- contents -->

View File

@ -85,6 +85,10 @@ Public Attributes</h2></td></tr>
<tr class="separator:ab5c1f38dea3a2cf00dc9eb4f57218c49"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:acc798589736f0becb317fc2196c1d8b9"><td class="memItemLeft" align="right" valign="top">PFN_vkUnmapMemory&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9">vkUnmapMemory</a></td></tr>
<tr class="separator:acc798589736f0becb317fc2196c1d8b9"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a33c322f4c4ad2810f8a9c97a277572f9"><td class="memItemLeft" align="right" valign="top">PFN_vkFlushMappedMemoryRanges&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9">vkFlushMappedMemoryRanges</a></td></tr>
<tr class="separator:a33c322f4c4ad2810f8a9c97a277572f9"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a5c1093bc32386a8060c37c9f282078a1"><td class="memItemLeft" align="right" valign="top">PFN_vkInvalidateMappedMemoryRanges&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1">vkInvalidateMappedMemoryRanges</a></td></tr>
<tr class="separator:a5c1093bc32386a8060c37c9f282078a1"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a94fc4f3a605d9880bb3c0ba2c2fc80b2"><td class="memItemLeft" align="right" valign="top">PFN_vkBindBufferMemory&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a94fc4f3a605d9880bb3c0ba2c2fc80b2">vkBindBufferMemory</a></td></tr>
<tr class="separator:a94fc4f3a605d9880bb3c0ba2c2fc80b2"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a1338d96a128a5ade648b8d934907c637"><td class="memItemLeft" align="right" valign="top">PFN_vkBindImageMemory&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a1338d96a128a5ade648b8d934907c637">vkBindImageMemory</a></td></tr>
@ -202,6 +206,20 @@ Public Attributes</h2></td></tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="a33c322f4c4ad2810f8a9c97a277572f9"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a33c322f4c4ad2810f8a9c97a277572f9">&#9670;&nbsp;</a></span>vkFlushMappedMemoryRanges</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">PFN_vkFlushMappedMemoryRanges VmaVulkanFunctions::vkFlushMappedMemoryRanges</td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="a4c658701778564d62034255b5dda91b4"></a>
@ -272,6 +290,20 @@ Public Attributes</h2></td></tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="a5c1093bc32386a8060c37c9f282078a1"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a5c1093bc32386a8060c37c9f282078a1">&#9670;&nbsp;</a></span>vkInvalidateMappedMemoryRanges</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">PFN_vkInvalidateMappedMemoryRanges VmaVulkanFunctions::vkInvalidateMappedMemoryRanges</td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="ab5c1f38dea3a2cf00dc9eb4f57218c49"></a>

View File

@ -286,6 +286,12 @@ Functions</h2></td></tr>
<tr class="memitem:a9bc268595cb33f6ec4d519cfce81ff45"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vmaUnmapMemory</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</td></tr>
<tr class="memdesc:a9bc268595cb33f6ec4d519cfce81ff45"><td class="mdescLeft">&#160;</td><td class="mdescRight">Unmaps memory represented by given allocation, mapped previously using <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 href="#a9bc268595cb33f6ec4d519cfce81ff45">More...</a><br /></td></tr>
<tr class="separator:a9bc268595cb33f6ec4d519cfce81ff45"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:abc34ee6f021f459aff885f3758c435de"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de">vmaFlushAllocation</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize offset, VkDeviceSize size)</td></tr>
<tr class="memdesc:abc34ee6f021f459aff885f3758c435de"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flushes memory of given allocation. <a href="#abc34ee6f021f459aff885f3758c435de">More...</a><br /></td></tr>
<tr class="separator:abc34ee6f021f459aff885f3758c435de"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a0d0eb0c1102268fa9a476d12ecbe4006"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006">vmaInvalidateAllocation</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize offset, VkDeviceSize size)</td></tr>
<tr class="memdesc:a0d0eb0c1102268fa9a476d12ecbe4006"><td class="mdescLeft">&#160;</td><td class="mdescRight">Invalidates memory of given allocation. <a href="#a0d0eb0c1102268fa9a476d12ecbe4006">More...</a><br /></td></tr>
<tr class="separator:a0d0eb0c1102268fa9a476d12ecbe4006"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a6aced90fcc7b39882b6654a740a0b9bb"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb">vmaDefragment</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *pAllocations, size_t allocationCount, VkBool32 *pAllocationsChanged, const <a class="el" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a> *pDefragmentationInfo, <a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a> *pDefragmentationStats)</td></tr>
<tr class="memdesc:a6aced90fcc7b39882b6654a740a0b9bb"><td class="mdescLeft">&#160;</td><td class="mdescRight">Compacts memory by moving allocations. <a href="#a6aced90fcc7b39882b6654a740a0b9bb">More...</a><br /></td></tr>
<tr class="separator:a6aced90fcc7b39882b6654a740a0b9bb"><td class="memSeparator" colspan="2">&#160;</td></tr>
@ -1681,6 +1687,56 @@ Functions</h2></td></tr>
<li><code>vkDestroyImage</code> </li>
</ul>
</div>
</div>
<a id="abc34ee6f021f459aff885f3758c435de"></a>
<h2 class="memtitle"><span class="permalink"><a href="#abc34ee6f021f459aff885f3758c435de">&#9670;&nbsp;</a></span>vmaFlushAllocation()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void vmaFlushAllocation </td>
<td>(</td>
<td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
<td class="paramname"><em>allocator</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
<td class="paramname"><em>allocation</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">VkDeviceSize&#160;</td>
<td class="paramname"><em>offset</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">VkDeviceSize&#160;</td>
<td class="paramname"><em>size</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Flushes memory of given allocation. </p>
<p>Calls <code>vkFlushMappedMemoryRanges()</code> for memory associated with given range of given allocation.</p>
<ul>
<li><code>offset</code> must be relative to the beginning of allocation.</li>
<li><code>size</code> can be <code>VK_WHOLE_SIZE</code>. It means all memory from <code>offset</code> the the end of given allocation.</li>
<li><code>offset</code> and <code>size</code> don't have to be aligned. They are internally rounded down/up to multiply of <code>nonCoherentAtomSize</code>.</li>
<li>If <code>size</code> is 0, this call is ignored.</li>
<li>If memory type that the <code>allocation</code> belongs to is not <code>HOST_VISIBLE</code> or it is <code>HOST_COHERENT</code>, this call is ignored. </li>
</ul>
</div>
</div>
<a id="a11f0fbc034fa81a4efedd73d61ce7568"></a>
@ -1921,6 +1977,56 @@ Functions</h2></td></tr>
</dd>
</dl>
</div>
</div>
<a id="a0d0eb0c1102268fa9a476d12ecbe4006"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a0d0eb0c1102268fa9a476d12ecbe4006">&#9670;&nbsp;</a></span>vmaInvalidateAllocation()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void vmaInvalidateAllocation </td>
<td>(</td>
<td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
<td class="paramname"><em>allocator</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
<td class="paramname"><em>allocation</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">VkDeviceSize&#160;</td>
<td class="paramname"><em>offset</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">VkDeviceSize&#160;</td>
<td class="paramname"><em>size</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Invalidates memory of given allocation. </p>
<p>Calls <code>vkInvalidateMappedMemoryRanges()</code> for memory associated with given range of given allocation.</p>
<ul>
<li><code>offset</code> must be relative to the beginning of allocation.</li>
<li><code>size</code> can be <code>VK_WHOLE_SIZE</code>. It means all memory from <code>offset</code> the the end of given allocation.</li>
<li><code>offset</code> and <code>size</code> don't have to be aligned. They are internally rounded down/up to multiply of <code>nonCoherentAtomSize</code>.</li>
<li>If <code>size</code> is 0, this call is ignored.</li>
<li>If memory type that the <code>allocation</code> belongs to is not <code>HOST_VISIBLE</code> or it is <code>HOST_COHERENT</code>, this call is ignored. </li>
</ul>
</div>
</div>
<a id="a736bd6cbda886f36c891727e73bd4024"></a>

File diff suppressed because one or more lines are too long

View File

@ -366,31 +366,23 @@ There are some exceptions though, when you should consider mapping memory only f
Memory in Vulkan doesn't need to be unmapped before using it on GPU,
but unless a memory types has `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` flag set,
you need to manually invalidate cache before reading of mapped pointer
using function `vkvkInvalidateMappedMemoryRanges()`
and flush cache after writing to mapped pointer
using function `vkFlushMappedMemoryRanges()`.
Example:
and flush cache after writing to mapped pointer.
Vulkan provides following functions for this purpose `vkFlushMappedMemoryRanges()`,
`vkInvalidateMappedMemoryRanges()`, but this library provides more convenient
functions that refer to given allocation object: vmaFlushAllocation(),
vmaInvalidateAllocation().
\code
memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData));
Regions of memory specified for flush/invalidate must be aligned to
`VkPhysicalDeviceLimits::nonCoherentAtomSize`. This is automatically ensured by the library.
In any memory type that is `HOST_VISIBLE` but not `HOST_COHERENT`, all allocations
within blocks are aligned to this value, so their offsets are always multiply of
`nonCoherentAtomSize` and two different allocations never share same "line" of this size.
VkMemoryPropertyFlags memFlags;
vmaGetMemoryTypeProperties(allocator, allocInfo.memoryType, &memFlags);
if((memFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
{
VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
memRange.memory = allocInfo.deviceMemory;
memRange.offset = allocInfo.offset;
memRange.size = allocInfo.size;
vkFlushMappedMemoryRanges(device, 1, &memRange);
}
\endcode
Please note that memory allocated with #VMA_MEMORY_USAGE_CPU_ONLY is guaranteed to be host coherent.
Please note that memory allocated with #VMA_MEMORY_USAGE_CPU_ONLY is guaranteed to be `HOST_COHERENT`.
Also, Windows drivers from all 3 PC GPU vendors (AMD, Intel, NVIDIA)
currently provide `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` flag on all memory types that are
`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, so on this platform you may not need to bother.
currently provide `HOST_COHERENT` flag on all memory types that are
`HOST_VISIBLE`, so on this platform you may not need to bother.
\section memory_mapping_finding_if_memory_mappable Finding out if memory is mappable
@ -1182,6 +1174,8 @@ typedef struct VmaVulkanFunctions {
PFN_vkFreeMemory vkFreeMemory;
PFN_vkMapMemory vkMapMemory;
PFN_vkUnmapMemory vkUnmapMemory;
PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges;
PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges;
PFN_vkBindBufferMemory vkBindBufferMemory;
PFN_vkBindImageMemory vkBindImageMemory;
PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
@ -1958,6 +1952,34 @@ void vmaUnmapMemory(
VmaAllocator allocator,
VmaAllocation allocation);
/** \brief Flushes memory of given allocation.
Calls `vkFlushMappedMemoryRanges()` for memory associated with given range of given allocation.
- `offset` must be relative to the beginning of allocation.
- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation.
- `offset` and `size` don't have to be aligned.
They are internally rounded down/up to multiply of `nonCoherentAtomSize`.
- If `size` is 0, this call is ignored.
- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,
this call is ignored.
*/
void vmaFlushAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
/** \brief Invalidates memory of given allocation.
Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given range of given allocation.
- `offset` must be relative to the beginning of allocation.
- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation.
- `offset` and `size` don't have to be aligned.
They are internally rounded down/up to multiply of `nonCoherentAtomSize`.
- If `size` is 0, this call is ignored.
- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,
this call is ignored.
*/
void vmaInvalidateAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
/** \brief Optional configuration parameters to be passed to function vmaDefragment(). */
typedef struct VmaDefragmentationInfo {
/** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places.
@ -2417,7 +2439,7 @@ If providing your own implementation, you need to implement a subset of std::ato
#ifndef VMA_DEBUG_ALIGNMENT
/**
Minimum alignment of all suballocations, in bytes.
Minimum alignment of all allocations, in bytes.
Set to more than 1 for debugging purposes only. Must be power of two.
*/
#define VMA_DEBUG_ALIGNMENT (1)
@ -2491,6 +2513,13 @@ static inline T VmaAlignUp(T val, T align)
{
return (val + align - 1) / align * align;
}
// Aligns given value down to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 8.
// Use types like uint32_t, uint64_t as T.
template <typename T>
static inline T VmaAlignDown(T val, T align)
{
return val / align * align;
}
// Division with mathematical rounding to nearest number.
template <typename T>
@ -3761,6 +3790,8 @@ void VmaMap<KeyT, ValueT>::erase(iterator it)
class VmaDeviceMemoryBlock;
enum VMA_CACHE_OPERATION { VMA_CACHE_FLUSH, VMA_CACHE_INVALIDATE };
struct VmaAllocation_T
{
VMA_CLASS_NO_COPY(VmaAllocation_T)
@ -4231,7 +4262,8 @@ public:
VkResult Allocate(
VmaPool hCurrentPool,
uint32_t currentFrameIndex,
const VkMemoryRequirements& vkMemReq,
VkDeviceSize size,
VkDeviceSize alignment,
const VmaAllocationCreateInfo& createInfo,
VmaSuballocationType suballocType,
VmaAllocation* pAllocation);
@ -4501,6 +4533,19 @@ public:
VMA_ASSERT(memTypeIndex < m_MemProps.memoryTypeCount);
return m_MemProps.memoryTypes[memTypeIndex].heapIndex;
}
// True when specific memory type is HOST_VISIBLE but not HOST_COHERENT.
bool IsMemoryTypeNonCoherent(uint32_t memTypeIndex) const
{
return (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ==
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
}
// Minimum alignment for all allocations in specific memory type.
VkDeviceSize GetMemoryTypeMinAlignment(uint32_t memTypeIndex) const
{
return IsMemoryTypeNonCoherent(memTypeIndex) ?
VMA_MAX((VkDeviceSize)VMA_DEBUG_ALIGNMENT, m_PhysicalDeviceProperties.limits.nonCoherentAtomSize) :
(VkDeviceSize)VMA_DEBUG_ALIGNMENT;
}
bool IsIntegratedGpu() const
{
@ -4569,6 +4614,11 @@ public:
VkResult BindBufferMemory(VmaAllocation hAllocation, VkBuffer hBuffer);
VkResult BindImageMemory(VmaAllocation hAllocation, VkImage hImage);
void FlushOrInvalidateAllocation(
VmaAllocation hAllocation,
VkDeviceSize offset, VkDeviceSize size,
VMA_CACHE_OPERATION op);
private:
VkDeviceSize m_PreferredLargeHeapBlockSize;
@ -4587,7 +4637,8 @@ private:
VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex);
VkResult AllocateMemoryOfType(
const VkMemoryRequirements& vkMemReq,
VkDeviceSize size,
VkDeviceSize alignment,
bool dedicatedAllocation,
VkBuffer dedicatedBuffer,
VkImage dedicatedImage,
@ -6022,8 +6073,7 @@ bool VmaBlockMetadata::CheckAllocation(
}
// Apply alignment.
const VkDeviceSize alignment = VMA_MAX(allocAlignment, static_cast<VkDeviceSize>(VMA_DEBUG_ALIGNMENT));
*pOffset = VmaAlignUp(*pOffset, alignment);
*pOffset = VmaAlignUp(*pOffset, allocAlignment);
// Check previous suballocations for BufferImageGranularity conflicts.
// Make bigger alignment if necessary.
@ -6169,8 +6219,7 @@ bool VmaBlockMetadata::CheckAllocation(
}
// Apply alignment.
const VkDeviceSize alignment = VMA_MAX(allocAlignment, static_cast<VkDeviceSize>(VMA_DEBUG_ALIGNMENT));
*pOffset = VmaAlignUp(*pOffset, alignment);
*pOffset = VmaAlignUp(*pOffset, allocAlignment);
// Check previous suballocations for BufferImageGranularity conflicts.
// Make bigger alignment if necessary.
@ -6554,7 +6603,8 @@ VmaPool_T::VmaPool_T(
createInfo.maxBlockCount,
(createInfo.flags & VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(),
createInfo.frameInUseCount,
true) // isCustomPool
true), // isCustomPool
m_Id(0)
{
}
@ -6638,7 +6688,8 @@ static const uint32_t VMA_ALLOCATION_TRY_COUNT = 32;
VkResult VmaBlockVector::Allocate(
VmaPool hCurrentPool,
uint32_t currentFrameIndex,
const VkMemoryRequirements& vkMemReq,
VkDeviceSize size,
VkDeviceSize alignment,
const VmaAllocationCreateInfo& createInfo,
VmaSuballocationType suballocType,
VmaAllocation* pAllocation)
@ -6659,8 +6710,8 @@ VkResult VmaBlockVector::Allocate(
currentFrameIndex,
m_FrameInUseCount,
m_BufferImageGranularity,
vkMemReq.size,
vkMemReq.alignment,
size,
alignment,
suballocType,
false, // canMakeOtherLost
&currRequest))
@ -6684,13 +6735,13 @@ VkResult VmaBlockVector::Allocate(
}
*pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString);
pCurrBlock->m_Metadata.Alloc(currRequest, suballocType, vkMemReq.size, *pAllocation);
pCurrBlock->m_Metadata.Alloc(currRequest, suballocType, size, *pAllocation);
(*pAllocation)->InitBlockAllocation(
hCurrentPool,
pCurrBlock,
currRequest.offset,
vkMemReq.alignment,
vkMemReq.size,
alignment,
size,
suballocType,
mapped,
(createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0);
@ -6722,7 +6773,7 @@ VkResult VmaBlockVector::Allocate(
for(uint32_t i = 0; i < NEW_BLOCK_SIZE_SHIFT_MAX; ++i)
{
const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
if(smallerNewBlockSize > maxExistingBlockSize && smallerNewBlockSize >= vkMemReq.size * 2)
if(smallerNewBlockSize > maxExistingBlockSize && smallerNewBlockSize >= size * 2)
{
newBlockSize = smallerNewBlockSize;
++newBlockSizeShift;
@ -6742,7 +6793,7 @@ VkResult VmaBlockVector::Allocate(
while(res < 0 && newBlockSizeShift < NEW_BLOCK_SIZE_SHIFT_MAX)
{
const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
if(smallerNewBlockSize >= vkMemReq.size)
if(smallerNewBlockSize >= size)
{
newBlockSize = smallerNewBlockSize;
++newBlockSizeShift;
@ -6758,7 +6809,7 @@ VkResult VmaBlockVector::Allocate(
if(res == VK_SUCCESS)
{
VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex];
VMA_ASSERT(pBlock->m_Metadata.GetSize() >= vkMemReq.size);
VMA_ASSERT(pBlock->m_Metadata.GetSize() >= size);
if(mapped)
{
@ -6773,13 +6824,13 @@ VkResult VmaBlockVector::Allocate(
VmaAllocationRequest allocRequest;
pBlock->m_Metadata.CreateFirstAllocationRequest(&allocRequest);
*pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString);
pBlock->m_Metadata.Alloc(allocRequest, suballocType, vkMemReq.size, *pAllocation);
pBlock->m_Metadata.Alloc(allocRequest, suballocType, size, *pAllocation);
(*pAllocation)->InitBlockAllocation(
hCurrentPool,
pBlock,
allocRequest.offset,
vkMemReq.alignment,
vkMemReq.size,
alignment,
size,
suballocType,
mapped,
(createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0);
@ -6813,8 +6864,8 @@ VkResult VmaBlockVector::Allocate(
currentFrameIndex,
m_FrameInUseCount,
m_BufferImageGranularity,
vkMemReq.size,
vkMemReq.alignment,
size,
alignment,
suballocType,
canMakeOtherLost,
&currRequest))
@ -6858,13 +6909,13 @@ VkResult VmaBlockVector::Allocate(
}
// Allocate from this pBlock.
*pAllocation = vma_new(m_hAllocator, VmaAllocation_T)(currentFrameIndex, isUserDataString);
pBestRequestBlock->m_Metadata.Alloc(bestRequest, suballocType, vkMemReq.size, *pAllocation);
pBestRequestBlock->m_Metadata.Alloc(bestRequest, suballocType, size, *pAllocation);
(*pAllocation)->InitBlockAllocation(
hCurrentPool,
pBestRequestBlock,
bestRequest.offset,
vkMemReq.alignment,
vkMemReq.size,
alignment,
size,
suballocType,
mapped,
(createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0);
@ -7513,8 +7564,8 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
#endif
memset(&m_DeviceMemoryCallbacks, 0 ,sizeof(m_DeviceMemoryCallbacks));
memset(&m_MemProps, 0, sizeof(m_MemProps));
memset(&m_PhysicalDeviceProperties, 0, sizeof(m_PhysicalDeviceProperties));
memset(&m_MemProps, 0, sizeof(m_MemProps));
memset(&m_pBlockVectors, 0, sizeof(m_pBlockVectors));
memset(&m_pDedicatedAllocations, 0, sizeof(m_pDedicatedAllocations));
@ -7570,6 +7621,7 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
// No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here,
// becase minBlockCount is 0.
m_pDedicatedAllocations[memTypeIndex] = vma_new(this, AllocationVectorType)(VmaStlAllocator<VmaAllocation>(GetAllocationCallbacks()));
}
}
@ -7593,6 +7645,8 @@ void VmaAllocator_T::ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunc
m_VulkanFunctions.vkFreeMemory = &vkFreeMemory;
m_VulkanFunctions.vkMapMemory = &vkMapMemory;
m_VulkanFunctions.vkUnmapMemory = &vkUnmapMemory;
m_VulkanFunctions.vkFlushMappedMemoryRanges = &vkFlushMappedMemoryRanges;
m_VulkanFunctions.vkInvalidateMappedMemoryRanges = &vkInvalidateMappedMemoryRanges;
m_VulkanFunctions.vkBindBufferMemory = &vkBindBufferMemory;
m_VulkanFunctions.vkBindImageMemory = &vkBindImageMemory;
m_VulkanFunctions.vkGetBufferMemoryRequirements = &vkGetBufferMemoryRequirements;
@ -7623,6 +7677,8 @@ void VmaAllocator_T::ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunc
VMA_COPY_IF_NOT_NULL(vkFreeMemory);
VMA_COPY_IF_NOT_NULL(vkMapMemory);
VMA_COPY_IF_NOT_NULL(vkUnmapMemory);
VMA_COPY_IF_NOT_NULL(vkFlushMappedMemoryRanges);
VMA_COPY_IF_NOT_NULL(vkInvalidateMappedMemoryRanges);
VMA_COPY_IF_NOT_NULL(vkBindBufferMemory);
VMA_COPY_IF_NOT_NULL(vkBindImageMemory);
VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements);
@ -7647,6 +7703,8 @@ void VmaAllocator_T::ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunc
VMA_ASSERT(m_VulkanFunctions.vkFreeMemory != VMA_NULL);
VMA_ASSERT(m_VulkanFunctions.vkMapMemory != VMA_NULL);
VMA_ASSERT(m_VulkanFunctions.vkUnmapMemory != VMA_NULL);
VMA_ASSERT(m_VulkanFunctions.vkFlushMappedMemoryRanges != VMA_NULL);
VMA_ASSERT(m_VulkanFunctions.vkInvalidateMappedMemoryRanges != VMA_NULL);
VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory != VMA_NULL);
VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory != VMA_NULL);
VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements != VMA_NULL);
@ -7673,7 +7731,8 @@ VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex)
}
VkResult VmaAllocator_T::AllocateMemoryOfType(
const VkMemoryRequirements& vkMemReq,
VkDeviceSize size,
VkDeviceSize alignment,
bool dedicatedAllocation,
VkBuffer dedicatedBuffer,
VkImage dedicatedImage,
@ -7702,7 +7761,7 @@ VkResult VmaAllocator_T::AllocateMemoryOfType(
VMA_DEBUG_ALWAYS_DEDICATED_MEMORY ||
dedicatedAllocation ||
// Heuristics: Allocate dedicated memory if requested size if greater than half of preferred block size.
vkMemReq.size > preferredBlockSize / 2;
size > preferredBlockSize / 2;
if(preferDedicatedMemory &&
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 &&
@ -7720,7 +7779,7 @@ VkResult VmaAllocator_T::AllocateMemoryOfType(
else
{
return AllocateDedicatedMemory(
vkMemReq.size,
size,
suballocType,
memTypeIndex,
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
@ -7736,7 +7795,8 @@ VkResult VmaAllocator_T::AllocateMemoryOfType(
VkResult res = blockVector->Allocate(
VK_NULL_HANDLE, // hCurrentPool
m_CurrentFrameIndex.load(),
vkMemReq,
size,
alignment,
finalCreateInfo,
suballocType,
pAllocation);
@ -7753,7 +7813,7 @@ VkResult VmaAllocator_T::AllocateMemoryOfType(
else
{
res = AllocateDedicatedMemory(
vkMemReq.size,
size,
suballocType,
memTypeIndex,
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
@ -7965,10 +8025,14 @@ VkResult VmaAllocator_T::AllocateMemory(
if(createInfo.pool != VK_NULL_HANDLE)
{
const VkDeviceSize alignmentForPool = VMA_MAX(
vkMemReq.alignment,
GetMemoryTypeMinAlignment(createInfo.pool->m_BlockVector.GetMemoryTypeIndex()));
return createInfo.pool->m_BlockVector.Allocate(
createInfo.pool,
m_CurrentFrameIndex.load(),
vkMemReq,
vkMemReq.size,
alignmentForPool,
createInfo,
suballocType,
pAllocation);
@ -7981,8 +8045,13 @@ VkResult VmaAllocator_T::AllocateMemory(
VkResult res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfo, &memTypeIndex);
if(res == VK_SUCCESS)
{
VkDeviceSize alignmentForMemType = VMA_MAX(
vkMemReq.alignment,
GetMemoryTypeMinAlignment(memTypeIndex));
res = AllocateMemoryOfType(
vkMemReq,
vkMemReq.size,
alignmentForMemType,
requiresDedicatedAllocation || prefersDedicatedAllocation,
dedicatedBuffer,
dedicatedImage,
@ -8006,8 +8075,13 @@ VkResult VmaAllocator_T::AllocateMemory(
res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfo, &memTypeIndex);
if(res == VK_SUCCESS)
{
alignmentForMemType = VMA_MAX(
vkMemReq.alignment,
GetMemoryTypeMinAlignment(memTypeIndex));
res = AllocateMemoryOfType(
vkMemReq,
vkMemReq.size,
alignmentForMemType,
requiresDedicatedAllocation || prefersDedicatedAllocation,
dedicatedBuffer,
dedicatedImage,
@ -8585,6 +8659,82 @@ VkResult VmaAllocator_T::BindImageMemory(VmaAllocation hAllocation, VkImage hIma
return res;
}
void VmaAllocator_T::FlushOrInvalidateAllocation(
VmaAllocation hAllocation,
VkDeviceSize offset, VkDeviceSize size,
VMA_CACHE_OPERATION op)
{
const uint32_t memTypeIndex = hAllocation->GetMemoryTypeIndex();
if(size > 0 && IsMemoryTypeNonCoherent(memTypeIndex))
{
const VkDeviceSize allocationSize = hAllocation->GetSize();
VMA_ASSERT(offset <= allocationSize);
const VkDeviceSize nonCoherentAtomSize = m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
memRange.memory = hAllocation->GetMemory();
switch(hAllocation->GetType())
{
case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
memRange.offset = VmaAlignDown(offset, nonCoherentAtomSize);
if(size == VK_WHOLE_SIZE)
{
memRange.size = allocationSize - memRange.offset;
}
else
{
VMA_ASSERT(offset + size <= allocationSize);
memRange.size = VMA_MIN(
VmaAlignUp(size + (offset - memRange.offset), nonCoherentAtomSize),
allocationSize - memRange.offset);
}
break;
case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
{
// 1. Still within this allocation.
memRange.offset = VmaAlignDown(offset, nonCoherentAtomSize);
if(size == VK_WHOLE_SIZE)
{
size = allocationSize - offset;
}
else
{
VMA_ASSERT(offset + size <= allocationSize);
}
memRange.size = VmaAlignUp(size + (offset - memRange.offset), nonCoherentAtomSize);
// 2. Adjust to whole block.
const VkDeviceSize allocationOffset = hAllocation->GetOffset();
VMA_ASSERT(allocationOffset % nonCoherentAtomSize == 0);
const VkDeviceSize blockSize = hAllocation->GetBlock()->m_Metadata.GetSize();
memRange.offset += allocationOffset;
memRange.size = VMA_MIN(memRange.size, blockSize - memRange.offset);
break;
}
default:
VMA_ASSERT(0);
}
switch(op)
{
case VMA_CACHE_FLUSH:
(*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, 1, &memRange);
break;
case VMA_CACHE_INVALIDATE:
(*GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hDevice, 1, &memRange);
break;
default:
VMA_ASSERT(0);
}
}
// else: Just ignore this call.
}
void VmaAllocator_T::FreeDedicatedMemory(VmaAllocation allocation)
{
VMA_ASSERT(allocation && allocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
@ -9309,6 +9459,28 @@ void vmaUnmapMemory(
allocator->Unmap(allocation);
}
void vmaFlushAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
{
VMA_ASSERT(allocator && allocation);
VMA_DEBUG_LOG("vmaFlushAllocation");
VMA_DEBUG_GLOBAL_MUTEX_LOCK
allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_FLUSH);
}
void vmaInvalidateAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
{
VMA_ASSERT(allocator && allocation);
VMA_DEBUG_LOG("vmaInvalidateAllocation");
VMA_DEBUG_GLOBAL_MUTEX_LOCK
allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_INVALIDATE);
}
VkResult vmaDefragment(
VmaAllocator allocator,
VmaAllocation* pAllocations,