<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>
<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>
<p>You can even use <code>VMA_ALLOCATION_CREATE_MAPPED_BIT</code> flag while creating allocations that are not necessarily <code>HOST_VISIBLE</code> (e.g. using <code>VMA_MEMORY_USAGE_GPU_ONLY</code>). 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="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_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_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#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_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="keywordflow">if</span>(allocInfo.<aclass="code"href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">pUserData</a> != <spanclass="keyword">nullptr</span>)</div><divclass="line">{</div><divclass="line"><spanclass="comment">// Allocation ended up in mappable memory.</span></div><divclass="line"><spanclass="comment">// It's persistently mapped. You can access it directly.</span></div><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"><spanclass="keywordflow">else</span></div><divclass="line">{</div><divclass="line"><spanclass="comment">// Allocation ended up in non-mappable memory.</span></div><divclass="line"><spanclass="comment">// You need to create CPU-side copy in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.</span></div><divclass="line">}</div></div><!-- fragment --></div></div><!-- contents -->