<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 <code>VmaAllocation</code>: <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. They 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>
<divclass="fragment"><divclass="line"><spanclass="comment">// Having these objects initialized:</span></div><divclass="line"></div><divclass="line"><spanclass="keyword">struct </span>ConstantBuffer</div><divclass="line">{</div><divclass="line"> ...</div><divclass="line">};</div><divclass="line">ConstantBuffer constantBufferData;</div><divclass="line"></div><divclass="line">VmaAllocator allocator;</div><divclass="line">VmaBuffer constantBuffer;</div><divclass="line">VmaAllocation constantBufferAllocation;</div><divclass="line"></div><divclass="line"><spanclass="comment">// You can map and fill your buffer using following code:</span></div><divclass="line"></div><divclass="line"><spanclass="keywordtype">void</span>* mappedData;</div><divclass="line"><aclass="code"href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vmaMapMemory</a>(allocator, constantBufferAllocation, &mappedData);</div><divclass="line">memcpy(mappedData, &constantBufferData, <spanclass="keyword">sizeof</span>(constantBufferData));</div><divclass="line"><aclass="code"href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vmaUnmapMemory</a>(allocator, constantBufferAllocation);</div></div><!-- fragment --><h1><aclass="anchor"id="memory_mapping_persistently_mapped_memory"></a>
<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 <code>VMA_ALLOCATION_CREATE_MAPPED_BIT</code> 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>
<divclass="fragment"><divclass="line">VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div><divclass="line">bufCreateInfo.size = <spanclass="keyword">sizeof</span>(ConstantBuffer);</div><divclass="line">bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;</div><divclass="line"></div><divclass="line"><aclass="code"href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div><divclass="line">allocCreateInfo.<aclass="code"href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <aclass="code"href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a>;</div><divclass="line">allocCreateInfo.<aclass="code"href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> = <aclass="code"href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>;</div><divclass="line"></div><divclass="line">VkBuffer buf;</div><divclass="line">VmaAllocation alloc;</div><divclass="line"><aclass="code"href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div><divclass="line"><aclass="code"href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);</div><divclass="line"></div><divclass="line"><spanclass="comment">// Buffer is already mapped. You can access its memory.</span></div><divclass="line">memcpy(allocInfo.<aclass="code"href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a>, &constantBufferData, <spanclass="keyword">sizeof</span>(constantBufferData));</div></div><!-- fragment --><p>There are some exceptions though, when you should consider mapping memory only for a short period of time:</p>
<ul>
<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 <code>VMA_MEMORY_USAGE_CPU_TO_GPU</code>), 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>Keeping many large memory blocks mapped may impact performance or stability of some debugging tools.</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 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>
<divclass="fragment"><divclass="line">memcpy(allocInfo.<aclass="code"href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a>, &constantBufferData, <spanclass="keyword">sizeof</span>(constantBufferData));</div><divclass="line"></div><divclass="line">VkMemoryPropertyFlags memFlags;</div><divclass="line"><aclass="code"href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca">vmaGetMemoryTypeProperties</a>(allocator, allocInfo.<aclass="code"href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">memoryType</a>, &memFlags);</div><divclass="line"><spanclass="keywordflow">if</span>((memFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)</div><divclass="line">{</div><divclass="line"> VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };</div><divclass="line"> memRange.memory = allocInfo.<aclass="code"href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67">deviceMemory</a>;</div><divclass="line"> memRange.offset = allocInfo.<aclass="code"href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268">offset</a>;</div><divclass="line"> memRange.size = allocInfo.<aclass="code"href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f">size</a>;</div><divclass="line"> vkFlushMappedMemoryRanges(device, 1, &memRange);</div><divclass="line">}</div></div><!-- fragment --><p>Please note that memory allocated with <code>VMA_MEMORY_USAGE_CPU_ONLY</code> 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>