mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
synced 2024-11-26 08:34:34 +00:00
Added support for VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT without HOST_VISIBLE. Improved empty block heuristics.
This commit is contained in:
parent
951f66a841
commit
1bb85fa719
@ -203,7 +203,8 @@ Functions</h2></td></tr>
|
|||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td class="fieldname"><a id="ggad9889c10c798b040d59c92f257cae597ae443691ef3d077c0dc3de5576ac4c312"></a>VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT </td><td class="fielddoc"><p>Set this flag to use a memory that will be persistently mapped and retrieve pointer to it. </p>
|
<tr><td class="fieldname"><a id="ggad9889c10c798b040d59c92f257cae597ae443691ef3d077c0dc3de5576ac4c312"></a>VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT </td><td class="fielddoc"><p>Set this flag to use a memory that will be persistently mapped and retrieve pointer to it. </p>
|
||||||
<p>Pointer to mapped memory will be returned through <a class="el" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2" title="Pointer to the beginning of this allocation as mapped data. Null if this alloaction is not persistent...">VmaAllocationInfo::pMappedData</a>. You cannot map the memory on your own as multiple mappings of a single <code>VkDeviceMemory</code> are illegal.</p>
|
<p>Pointer to mapped memory will be returned through <a class="el" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2" title="Pointer to the beginning of this allocation as mapped data. Null if this alloaction is not persistent...">VmaAllocationInfo::pMappedData</a>. You cannot map the memory on your own as multiple mappings of a single <code>VkDeviceMemory</code> are illegal.</p>
|
||||||
<p>If <a class="el" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150" title="Pool that this allocation should be created in. ">VmaAllocationCreateInfo::pool</a> is not null, usage of this flag must match usage of flag <code>VMA_POOL_CREATE_PERSISTENT_MAP_BIT</code> used during pool creation. </p>
|
<p>If <a class="el" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150" title="Pool that this allocation should be created in. ">VmaAllocationCreateInfo::pool</a> is not null, usage of this flag must match usage of flag <code>VMA_POOL_CREATE_PERSISTENT_MAP_BIT</code> used during pool creation.</p>
|
||||||
|
<p>Is it valid to use this flag for allocation made from memory type that is not <code>HOST_VISIBLE</code>. This flag is then ignored and memory is not mapped. This is useful if you need an allocation that is efficient to use on GPU (<code>DEVICE_LOCAL</code>) and still want to map it directly if possible on platforms that support it (e.g. Intel GPU). </p>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td class="fieldname"><a id="ggad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2"></a>VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT </td><td class="fielddoc"><p>Allocation created with this flag can become lost as a result of another allocation with <code>VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</code> flag, so you must check it before use.</p>
|
<tr><td class="fieldname"><a id="ggad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2"></a>VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT </td><td class="fielddoc"><p>Allocation created with this flag can become lost as a result of another allocation with <code>VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</code> flag, so you must check it before use.</p>
|
||||||
<p>To check if allocation is not lost, call <a class="el" href="group__layer2.html#ga86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation. ">vmaGetAllocationInfo()</a> and check if <a class="el" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67" title="Handle to Vulkan memory object. ">VmaAllocationInfo::deviceMemory</a> is not <code>VK_NULL_HANDLE</code>.</p>
|
<p>To check if allocation is not lost, call <a class="el" href="group__layer2.html#ga86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation. ">vmaGetAllocationInfo()</a> and check if <a class="el" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67" title="Handle to Vulkan memory object. ">VmaAllocationInfo::deviceMemory</a> is not <code>VK_NULL_HANDLE</code>.</p>
|
||||||
|
File diff suppressed because one or more lines are too long
@ -685,6 +685,12 @@ typedef enum VmaAllocationCreateFlagBits {
|
|||||||
|
|
||||||
If VmaAllocationCreateInfo::pool is not null, usage of this flag must match
|
If VmaAllocationCreateInfo::pool is not null, usage of this flag must match
|
||||||
usage of flag `VMA_POOL_CREATE_PERSISTENT_MAP_BIT` used during pool creation.
|
usage of flag `VMA_POOL_CREATE_PERSISTENT_MAP_BIT` used during pool creation.
|
||||||
|
|
||||||
|
Is it valid to use this flag for allocation made from memory type that is not
|
||||||
|
`HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is
|
||||||
|
useful if you need an allocation that is efficient to use on GPU
|
||||||
|
(`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that
|
||||||
|
support it (e.g. Intel GPU).
|
||||||
*/
|
*/
|
||||||
VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT = 0x00000004,
|
VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT = 0x00000004,
|
||||||
/** Allocation created with this flag can become lost as a result of another
|
/** Allocation created with this flag can become lost as a result of another
|
||||||
@ -5315,8 +5321,8 @@ VkResult VmaBlockVector::Allocate(
|
|||||||
VmaAllocation* pAllocation)
|
VmaAllocation* pAllocation)
|
||||||
{
|
{
|
||||||
// Validate flags.
|
// Validate flags.
|
||||||
if(((createInfo.flags & VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT) != 0) !=
|
if(createInfo.pool != VK_NULL_HANDLE &&
|
||||||
(m_BlockVectorType == VMA_BLOCK_VECTOR_TYPE_MAPPED))
|
((createInfo.flags & VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT) != 0) != (m_BlockVectorType == VMA_BLOCK_VECTOR_TYPE_MAPPED))
|
||||||
{
|
{
|
||||||
VMA_ASSERT(0 && "Usage of VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT must match VMA_POOL_CREATE_PERSISTENT_MAP_BIT.");
|
VMA_ASSERT(0 && "Usage of VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT must match VMA_POOL_CREATE_PERSISTENT_MAP_BIT.");
|
||||||
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
||||||
@ -5548,7 +5554,19 @@ void VmaBlockVector::Free(
|
|||||||
m_HasEmptyBlock = true;
|
m_HasEmptyBlock = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Must be called after srcBlockIndex is used, because later it may become invalid!
|
// pBlock didn't become empty, but we have another empty block - find and free that one.
|
||||||
|
// (This is optional, heuristics.)
|
||||||
|
else if(m_HasEmptyBlock)
|
||||||
|
{
|
||||||
|
VmaDeviceMemoryBlock* pLastBlock = m_Blocks.back();
|
||||||
|
if(pLastBlock->m_Metadata.IsEmpty() && m_Blocks.size() > m_MinBlockCount)
|
||||||
|
{
|
||||||
|
pBlockToDelete = pLastBlock;
|
||||||
|
m_Blocks.pop_back();
|
||||||
|
m_HasEmptyBlock = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IncrementallySortBlocks();
|
IncrementallySortBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6313,17 +6331,31 @@ VkResult VmaAllocator_T::AllocateMemoryOfType(
|
|||||||
VmaBlockVector* const blockVector = m_pBlockVectors[memTypeIndex][blockVectorType];
|
VmaBlockVector* const blockVector = m_pBlockVectors[memTypeIndex][blockVectorType];
|
||||||
VMA_ASSERT(blockVector);
|
VMA_ASSERT(blockVector);
|
||||||
|
|
||||||
const VkDeviceSize preferredBlockSize = blockVector->GetPreferredBlockSize();
|
VmaAllocationCreateInfo finalCreateInfo = createInfo;
|
||||||
// Heuristics: Allocate own memory if requested size if greater than half of preferred block size.
|
|
||||||
const bool ownMemory =
|
|
||||||
(createInfo.flags & VMA_ALLOCATION_CREATE_OWN_MEMORY_BIT) != 0 ||
|
|
||||||
VMA_DEBUG_ALWAYS_OWN_MEMORY ||
|
|
||||||
((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 &&
|
|
||||||
vkMemReq.size > preferredBlockSize / 2);
|
|
||||||
|
|
||||||
if(ownMemory)
|
if(VMA_DEBUG_ALWAYS_OWN_MEMORY)
|
||||||
{
|
{
|
||||||
if((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
|
finalCreateInfo.flags |= VMA_ALLOCATION_CREATE_OWN_MEMORY_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Heuristics: Allocate own memory if requested size if greater than half of preferred block size.
|
||||||
|
const VkDeviceSize preferredBlockSize = blockVector->GetPreferredBlockSize();
|
||||||
|
if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 &&
|
||||||
|
vkMemReq.size > preferredBlockSize / 2)
|
||||||
|
{
|
||||||
|
finalCreateInfo.flags |= VMA_ALLOCATION_CREATE_OWN_MEMORY_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If memory type is not HOST_VISIBLE, disable PERSISTENT_MAP.
|
||||||
|
if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT) != 0 &&
|
||||||
|
(m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
|
||||||
|
{
|
||||||
|
finalCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_OWN_MEMORY_BIT) != 0)
|
||||||
|
{
|
||||||
|
if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
|
||||||
{
|
{
|
||||||
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
||||||
}
|
}
|
||||||
@ -6333,8 +6365,8 @@ VkResult VmaAllocator_T::AllocateMemoryOfType(
|
|||||||
vkMemReq.size,
|
vkMemReq.size,
|
||||||
suballocType,
|
suballocType,
|
||||||
memTypeIndex,
|
memTypeIndex,
|
||||||
(createInfo.flags & VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT) != 0,
|
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT) != 0,
|
||||||
createInfo.pUserData,
|
finalCreateInfo.pUserData,
|
||||||
pAllocation);
|
pAllocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6344,7 +6376,7 @@ VkResult VmaAllocator_T::AllocateMemoryOfType(
|
|||||||
VK_NULL_HANDLE, // hCurrentPool
|
VK_NULL_HANDLE, // hCurrentPool
|
||||||
m_CurrentFrameIndex.load(),
|
m_CurrentFrameIndex.load(),
|
||||||
vkMemReq,
|
vkMemReq,
|
||||||
createInfo,
|
finalCreateInfo,
|
||||||
suballocType,
|
suballocType,
|
||||||
pAllocation);
|
pAllocation);
|
||||||
if(res == VK_SUCCESS)
|
if(res == VK_SUCCESS)
|
||||||
@ -6353,12 +6385,18 @@ VkResult VmaAllocator_T::AllocateMemoryOfType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 5. Try own memory.
|
// 5. Try own memory.
|
||||||
|
if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
|
||||||
|
{
|
||||||
|
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
res = AllocateOwnMemory(
|
res = AllocateOwnMemory(
|
||||||
vkMemReq.size,
|
vkMemReq.size,
|
||||||
suballocType,
|
suballocType,
|
||||||
memTypeIndex,
|
memTypeIndex,
|
||||||
(createInfo.flags & VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT) != 0,
|
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT) != 0,
|
||||||
createInfo.pUserData,
|
finalCreateInfo.pUserData,
|
||||||
pAllocation);
|
pAllocation);
|
||||||
if(res == VK_SUCCESS)
|
if(res == VK_SUCCESS)
|
||||||
{
|
{
|
||||||
@ -6373,6 +6411,7 @@ VkResult VmaAllocator_T::AllocateMemoryOfType(
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult VmaAllocator_T::AllocateOwnMemory(
|
VkResult VmaAllocator_T::AllocateOwnMemory(
|
||||||
@ -7394,11 +7433,6 @@ VkResult vmaFindMemoryTypeIndex(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT) != 0)
|
|
||||||
{
|
|
||||||
requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pMemoryTypeIndex = UINT32_MAX;
|
*pMemoryTypeIndex = UINT32_MAX;
|
||||||
uint32_t minCost = UINT32_MAX;
|
uint32_t minCost = UINT32_MAX;
|
||||||
for(uint32_t memTypeIndex = 0, memTypeBit = 1;
|
for(uint32_t memTypeIndex = 0, memTypeBit = 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user