mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
synced 2024-12-24 17:51:04 +00:00
Improved logic of vmaFindMemoryTypeIndex for some cases, especially integrated GPUs.
This commit is contained in:
parent
9bb910e63c
commit
5391e6c7fa
@ -87,7 +87,7 @@ Cache control</h1>
|
||||
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>
|
||||
<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 <a class="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>
|
||||
<div class="fragment"><div class="line">VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div><div class="line">bufCreateInfo.size = <span class="keyword">sizeof</span>(ConstantBuffer);</div><div class="line">bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;</div><div class="line"></div><div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div><div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>;</div><div class="line"></div><div class="line">VkBuffer buf;</div><div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc;</div><div class="line"><a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div><div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);</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>, &memFlags);</div><div class="line"><span class="keywordflow">if</span>((memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)</div><div class="line">{</div><div class="line"> <span class="comment">// Allocation ended up in mappable memory. You can map it and access it directly.</span></div><div class="line"> <span class="keywordtype">void</span>* mappedData;</div><div class="line"> <a class="code" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vmaMapMemory</a>(allocator, alloc, &mappedData);</div><div class="line"> memcpy(mappedData, &constantBufferData, <span class="keyword">sizeof</span>(constantBufferData));</div><div class="line"> <a class="code" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vmaUnmapMemory</a>(allocator, alloc);</div><div class="line">}</div><div class="line"><span class="keywordflow">else</span></div><div class="line">{</div><div class="line"> <span class="comment">// Allocation ended up in non-mappable memory.</span></div><div class="line"> <span class="comment">// You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.</span></div><div class="line">}</div></div><!-- fragment --><p>You can even use <a class="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 <a class="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>
|
||||
<div class="fragment"><div class="line">VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div><div class="line">bufCreateInfo.size = <span class="keyword">sizeof</span>(ConstantBuffer);</div><div class="line">bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;</div><div class="line"></div><div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div><div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>;</div><div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a> = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;</div><div class="line"></div><div class="line">VkBuffer buf;</div><div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc;</div><div class="line"><a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div><div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);</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>, &memFlags);</div><div class="line"><span class="keywordflow">if</span>((memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)</div><div class="line">{</div><div class="line"> <span class="comment">// Allocation ended up in mappable memory. You can map it and access it directly.</span></div><div class="line"> <span class="keywordtype">void</span>* mappedData;</div><div class="line"> <a class="code" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vmaMapMemory</a>(allocator, alloc, &mappedData);</div><div class="line"> memcpy(mappedData, &constantBufferData, <span class="keyword">sizeof</span>(constantBufferData));</div><div class="line"> <a class="code" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vmaUnmapMemory</a>(allocator, alloc);</div><div class="line">}</div><div class="line"><span class="keywordflow">else</span></div><div class="line">{</div><div class="line"> <span class="comment">// Allocation ended up in non-mappable memory.</span></div><div class="line"> <span class="comment">// You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.</span></div><div class="line">}</div></div><!-- fragment --><p>You can even use <a class="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 <a class="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>
|
||||
<div class="fragment"><div class="line">VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div><div class="line">bufCreateInfo.size = <span class="keyword">sizeof</span>(ConstantBuffer);</div><div class="line">bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;</div><div class="line"></div><div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div><div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>;</div><div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> = <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>;</div><div class="line"></div><div class="line">VkBuffer buf;</div><div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc;</div><div class="line"><a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div><div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);</div><div class="line"></div><div class="line"><span class="keywordflow">if</span>(allocInfo.<a class="code" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">pUserData</a> != <span class="keyword">nullptr</span>)</div><div class="line">{</div><div class="line"> <span class="comment">// Allocation ended up in mappable memory.</span></div><div class="line"> <span class="comment">// It's persistently mapped. You can access it directly.</span></div><div class="line"> memcpy(allocInfo.<a class="code" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a>, &constantBufferData, <span class="keyword">sizeof</span>(constantBufferData));</div><div class="line">}</div><div class="line"><span class="keywordflow">else</span></div><div class="line">{</div><div class="line"> <span class="comment">// Allocation ended up in non-mappable memory.</span></div><div class="line"> <span class="comment">// You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.</span></div><div class="line">}</div></div><!-- fragment --> </div></div><!-- contents -->
|
||||
<!-- start footer part -->
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
|
File diff suppressed because one or more lines are too long
@ -411,6 +411,7 @@ bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANS
|
||||
|
||||
VmaAllocationCreateInfo allocCreateInfo = {};
|
||||
allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||
allocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||
|
||||
VkBuffer buf;
|
||||
VmaAllocation alloc;
|
||||
@ -4444,6 +4445,11 @@ struct VmaAllocator_T
|
||||
return m_MemProps.memoryTypes[memTypeIndex].heapIndex;
|
||||
}
|
||||
|
||||
bool IsIntegratedGpu() const
|
||||
{
|
||||
return m_PhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
|
||||
}
|
||||
|
||||
void GetBufferMemoryRequirements(
|
||||
VkBuffer hBuffer,
|
||||
VkMemoryRequirements& memReq,
|
||||
@ -8815,20 +8821,32 @@ VkResult vmaFindMemoryTypeIndex(
|
||||
uint32_t requiredFlags = pAllocationCreateInfo->requiredFlags;
|
||||
uint32_t preferredFlags = pAllocationCreateInfo->preferredFlags;
|
||||
|
||||
const bool mapped = (pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0;
|
||||
if(mapped)
|
||||
{
|
||||
preferredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||
}
|
||||
|
||||
// Convert usage to requiredFlags and preferredFlags.
|
||||
switch(pAllocationCreateInfo->usage)
|
||||
{
|
||||
case VMA_MEMORY_USAGE_UNKNOWN:
|
||||
break;
|
||||
case VMA_MEMORY_USAGE_GPU_ONLY:
|
||||
preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
if(!allocator->IsIntegratedGpu() || (preferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
|
||||
{
|
||||
preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
}
|
||||
break;
|
||||
case VMA_MEMORY_USAGE_CPU_ONLY:
|
||||
requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
||||
break;
|
||||
case VMA_MEMORY_USAGE_CPU_TO_GPU:
|
||||
requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||
preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
if(!allocator->IsIntegratedGpu() || (preferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
|
||||
{
|
||||
preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
}
|
||||
break;
|
||||
case VMA_MEMORY_USAGE_GPU_TO_CPU:
|
||||
requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||
|
Loading…
Reference in New Issue
Block a user