<divclass="textblock"><p>To "map memory" in Vulkan means to obtain a CPU pointer to <code>VkDeviceMemory</code>, to be able to read from it or write to it in CPU code. Mapping is possible only of memory allocated from a memory type that has <code>VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT</code> flag. Functions <code>vkMapMemory()</code>, <code>vkUnmapMemory()</code> are designed for this purpose. You can use them directly with memory allocated by this library, but it is not recommended because of following issue: Mapping the same <code>VkDeviceMemory</code> block multiple times is illegal - only one mapping at a time is allowed. This includes mapping disjoint regions. Mapping is not reference-counted internally by Vulkan. Because of this, Vulkan Memory Allocator provides following facilities:</p>
<p>The library provides following functions for mapping of a specific <aclass="el"href="struct_vma_allocation.html"title="Represents single memory allocation.">VmaAllocation</a>: <aclass="el"href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069"title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a>, <aclass="el"href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45"title="Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().">vmaUnmapMemory()</a>. They are safer and more convenient to use than standard Vulkan functions. You can map an allocation multiple times simultaneously - mapping is reference-counted internally. You can also map different allocations simultaneously regardless of whether they use the same <code>VkDeviceMemory</code> block. The way it's implemented is that the library always maps entire memory block, not just region of the allocation. For further details, see description of <aclass="el"href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069"title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a> function. Example:</p>
<p><em>Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.</em></p>
<p>It happens because the library maps entire <code>VkDeviceMemory</code> block, where different types of images and buffers may end up together, especially on GPUs with unified memory like Intel. You can safely ignore it if you are sure you access only memory of the intended object that you wanted to map.</p>
<p>Kepping your memory persistently mapped is generally OK in Vulkan. You don't need to unmap it before using its data on the GPU. The library provides a special feature designed for that: Allocations made with <aclass="el"href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f"title="Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.">VMA_ALLOCATION_CREATE_MAPPED_BIT</a> flag set in <aclass="el"href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b"title="Use VmaAllocationCreateFlagBits enum.">VmaAllocationCreateInfo::flags</a> stay mapped all the time, so you can just access CPU pointer to it any time without a need to call any "map" or "unmap" function. Example:</p>
<li>When operating system is Windows 7 or 8.x (Windows 10 is not affected because it uses WDDM2), device is discrete AMD GPU, and memory type is the special 256 MiB pool of <code>DEVICE_LOCAL + HOST_VISIBLE</code> memory (selected when you use <aclass="el"href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67">VMA_MEMORY_USAGE_CPU_TO_GPU</a>), then whenever a memory block allocated from this memory type stays mapped for the time of any call to <code>vkQueueSubmit()</code> or <code>vkQueuePresentKHR()</code>, this block is migrated by WDDM to system RAM, which degrades performance. It doesn't matter if that particular memory block is actually used by the command buffer being submitted.</li>
<li>On Mac/MoltenVK there is a known bug - <ahref="https://github.com/KhronosGroup/MoltenVK/issues/175">Issue #175</a> which requires unmapping before GPU can see updated texture.</li>
<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 <b>invalidate</b> cache before reading of mapped pointer and <b>flush</b> cache after writing to mapped pointer. Map/unmap operations don't do that automatically. 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: <aclass="el"href="vk__mem__alloc_8h.html#a30c37c1eec6025f397be41644f48490f"title="Flushes memory of given allocation.">vmaFlushAllocation()</a>, <aclass="el"href="vk__mem__alloc_8h.html#aaa8412919139ef413a4215ac6a290fae"title="Invalidates memory of given allocation.">vmaInvalidateAllocation()</a>, or multiple objects at once: <aclass="el"href="vk__mem__alloc_8h.html#ac3dd00da721875ed99fa8a881922bdfc"title="Flushes memory of given set of allocations.">vmaFlushAllocations()</a>, <aclass="el"href="vk__mem__alloc_8h.html#ab25b558d75f7378ec944a1522fdcc3c5"title="Invalidates memory of given set of allocations.">vmaInvalidateAllocations()</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 <aclass="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 <b>PC</b> 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>
<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>
<p>You can detect this case and map such allocation to access its memory on CPU directly, instead of launching a transfer operation. In order to do that: inspect <code>allocInfo.memoryType</code>, call <aclass="el"href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca"title="Given Memory Type Index, returns Property Flags of this memory type.">vmaGetMemoryTypeProperties()</a>, and look for <code>VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT</code> flag in properties of that memory type.</p>
<divclass="line"><spanclass="comment">// Allocation ended up in non-mappable memory.</span></div>
<divclass="line"><spanclass="comment">// You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.</span></div>
<divclass="line">}</div>
</div><!-- fragment --><p>You can even use <aclass="el"href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f"title="Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.">VMA_ALLOCATION_CREATE_MAPPED_BIT</a> flag while creating allocations that are not necessarily <code>HOST_VISIBLE</code> (e.g. using <aclass="el"href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>). If the allocation ends up in memory type that is <code>HOST_VISIBLE</code>, it will be persistently mapped and you can use it directly. If not, the flag is just ignored. Example:</p>
<divclass="ttc"id="avk__mem__alloc_8h_html_a9bc268595cb33f6ec4d519cfce81ff45"><divclass="ttname"><ahref="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vmaUnmapMemory</a></div><divclass="ttdeci">void vmaUnmapMemory(VmaAllocator allocator, VmaAllocation allocation)</div><divclass="ttdoc">Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().</div></div>
<divclass="ttc"id="astruct_vma_allocator_html"><divclass="ttname"><ahref="struct_vma_allocator.html">VmaAllocator</a></div><divclass="ttdoc">Represents main object of this library initialized.</div></div>
<divclass="ttc"id="astruct_vma_allocation_html"><divclass="ttname"><ahref="struct_vma_allocation.html">VmaAllocation</a></div><divclass="ttdoc">Represents single memory allocation.</div></div>
<divclass="ttc"id="avk__mem__alloc_8h_html_ad5bd1243512d099706de88168992f069"><divclass="ttname"><ahref="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vmaMapMemory</a></div><divclass="ttdeci">VkResult vmaMapMemory(VmaAllocator allocator, VmaAllocation allocation, void **ppData)</div><divclass="ttdoc">Maps memory represented by given allocation and returns pointer to it.</div></div>
<divclass="ttc"id="astruct_vma_allocation_info_html_a5eeffbe2d2f30f53370ff14aefbadbe2"><divclass="ttname"><ahref="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">VmaAllocationInfo::pMappedData</a></div><divclass="ttdeci">void * pMappedData</div><divclass="ttdoc">Pointer to the beginning of this allocation as mapped data.</div><divclass="ttdef"><b>Definition:</b> vk_mem_alloc.h:3236</div></div>
<divclass="ttc"id="astruct_vma_allocation_create_info_html_accb8b06b1f677d858cb9af20705fa910"><divclass="ttname"><ahref="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">VmaAllocationCreateInfo::usage</a></div><divclass="ttdeci">VmaMemoryUsage usage</div><divclass="ttdoc">Intended usage of memory.</div><divclass="ttdef"><b>Definition:</b> vk_mem_alloc.h:2863</div></div>
<divclass="ttc"id="astruct_vma_allocation_info_html_a7f6b0aa58c135e488e6b40a388dad9d5"><divclass="ttname"><ahref="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">VmaAllocationInfo::memoryType</a></div><divclass="ttdeci">uint32_t memoryType</div><divclass="ttdoc">Memory type index that this allocation was allocated from.</div><divclass="ttdef"><b>Definition:</b> vk_mem_alloc.h:3197</div></div>
<divclass="ttc"id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f"><divclass="ttname"><ahref="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a></div><divclass="ttdeci">@ VMA_ALLOCATION_CREATE_MAPPED_BIT</div><divclass="ttdoc">Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.</div><divclass="ttdef"><b>Definition:</b> vk_mem_alloc.h:2774</div></div>
<divclass="ttc"id="astruct_vma_allocation_create_info_html_a7fe8d81a1ad10b2a2faacacee5b15d6d"><divclass="ttname"><ahref="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">VmaAllocationCreateInfo::preferredFlags</a></div><divclass="ttdeci">VkMemoryPropertyFlags preferredFlags</div><divclass="ttdoc">Flags that preferably should be set in a memory type chosen for an allocation.</div><divclass="ttdef"><b>Definition:</b> vk_mem_alloc.h:2873</div></div>
<divclass="ttc"id="astruct_vma_allocation_info_html"><divclass="ttname"><ahref="struct_vma_allocation_info.html">VmaAllocationInfo</a></div><divclass="ttdoc">Parameters of VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().</div><divclass="ttdef"><b>Definition:</b> vk_mem_alloc.h:3192</div></div>