Add a separate pool for small allocations in Vulkan RD
This commit is contained in:
parent
648a10514b
commit
4e6c9d3ae9
|
@ -43,6 +43,8 @@
|
||||||
|
|
||||||
//#define FORCE_FULL_BARRIER
|
//#define FORCE_FULL_BARRIER
|
||||||
|
|
||||||
|
static const uint32_t SMALL_ALLOCATION_MAX_SIZE = 4096;
|
||||||
|
|
||||||
// Get the Vulkan object information and possible stage access types (bitwise OR'd with incoming values)
|
// Get the Vulkan object information and possible stage access types (bitwise OR'd with incoming values)
|
||||||
RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &r_stage_mask, VkAccessFlags &r_access_mask, uint32_t p_post_barrier) {
|
RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &r_stage_mask, VkAccessFlags &r_access_mask, uint32_t p_post_barrier) {
|
||||||
Buffer *buffer = nullptr;
|
Buffer *buffer = nullptr;
|
||||||
|
@ -1333,7 +1335,7 @@ Error RenderingDeviceVulkan::_buffer_allocate(Buffer *p_buffer, uint32_t p_size,
|
||||||
allocInfo.requiredFlags = 0;
|
allocInfo.requiredFlags = 0;
|
||||||
allocInfo.preferredFlags = 0;
|
allocInfo.preferredFlags = 0;
|
||||||
allocInfo.memoryTypeBits = 0;
|
allocInfo.memoryTypeBits = 0;
|
||||||
allocInfo.pool = nullptr;
|
allocInfo.pool = p_size <= SMALL_ALLOCATION_MAX_SIZE ? small_allocs_pool : nullptr;
|
||||||
allocInfo.pUserData = nullptr;
|
allocInfo.pUserData = nullptr;
|
||||||
|
|
||||||
VkResult err = vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &p_buffer->buffer, &p_buffer->allocation, nullptr);
|
VkResult err = vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &p_buffer->buffer, &p_buffer->allocation, nullptr);
|
||||||
|
@ -1836,13 +1838,16 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
|
||||||
|
|
||||||
//allocate memory
|
//allocate memory
|
||||||
|
|
||||||
|
uint32_t width, height;
|
||||||
|
uint32_t image_size = get_image_format_required_size(p_format.format, p_format.width, p_format.height, p_format.depth, p_format.mipmaps, &width, &height);
|
||||||
|
|
||||||
VmaAllocationCreateInfo allocInfo;
|
VmaAllocationCreateInfo allocInfo;
|
||||||
allocInfo.flags = 0;
|
allocInfo.flags = 0;
|
||||||
|
allocInfo.pool = image_size <= SMALL_ALLOCATION_MAX_SIZE ? small_allocs_pool : nullptr;
|
||||||
allocInfo.usage = p_format.usage_bits & TEXTURE_USAGE_CPU_READ_BIT ? VMA_MEMORY_USAGE_CPU_ONLY : VMA_MEMORY_USAGE_GPU_ONLY;
|
allocInfo.usage = p_format.usage_bits & TEXTURE_USAGE_CPU_READ_BIT ? VMA_MEMORY_USAGE_CPU_ONLY : VMA_MEMORY_USAGE_GPU_ONLY;
|
||||||
allocInfo.requiredFlags = 0;
|
allocInfo.requiredFlags = 0;
|
||||||
allocInfo.preferredFlags = 0;
|
allocInfo.preferredFlags = 0;
|
||||||
allocInfo.memoryTypeBits = 0;
|
allocInfo.memoryTypeBits = 0;
|
||||||
allocInfo.pool = nullptr;
|
|
||||||
allocInfo.pUserData = nullptr;
|
allocInfo.pUserData = nullptr;
|
||||||
|
|
||||||
Texture texture;
|
Texture texture;
|
||||||
|
@ -8808,6 +8813,18 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
|
||||||
vmaCreateAllocator(&allocatorInfo, &allocator);
|
vmaCreateAllocator(&allocatorInfo, &allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ //create pool for small objects
|
||||||
|
VmaPoolCreateInfo pci;
|
||||||
|
pci.flags = VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT;
|
||||||
|
pci.blockSize = 0;
|
||||||
|
pci.minBlockCount = 0;
|
||||||
|
pci.maxBlockCount = SIZE_MAX;
|
||||||
|
pci.priority = 0.5f;
|
||||||
|
pci.minAllocationAlignment = 0;
|
||||||
|
pci.pMemoryAllocateNext = nullptr;
|
||||||
|
vmaCreatePool(allocator, &pci, &small_allocs_pool);
|
||||||
|
}
|
||||||
|
|
||||||
frames = memnew_arr(Frame, frame_count);
|
frames = memnew_arr(Frame, frame_count);
|
||||||
frame = 0;
|
frame = 0;
|
||||||
//create setup and frame buffers
|
//create setup and frame buffers
|
||||||
|
@ -9276,6 +9293,7 @@ void RenderingDeviceVulkan::finalize() {
|
||||||
for (int i = 0; i < staging_buffer_blocks.size(); i++) {
|
for (int i = 0; i < staging_buffer_blocks.size(); i++) {
|
||||||
vmaDestroyBuffer(allocator, staging_buffer_blocks[i].buffer, staging_buffer_blocks[i].allocation);
|
vmaDestroyBuffer(allocator, staging_buffer_blocks[i].buffer, staging_buffer_blocks[i].allocation);
|
||||||
}
|
}
|
||||||
|
vmaDestroyPool(allocator, small_allocs_pool);
|
||||||
vmaDestroyAllocator(allocator);
|
vmaDestroyAllocator(allocator);
|
||||||
|
|
||||||
while (vertex_formats.size()) {
|
while (vertex_formats.size()) {
|
||||||
|
|
|
@ -1016,6 +1016,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||||
void _free_pending_resources(int p_frame);
|
void _free_pending_resources(int p_frame);
|
||||||
|
|
||||||
VmaAllocator allocator = nullptr;
|
VmaAllocator allocator = nullptr;
|
||||||
|
VmaPool small_allocs_pool = nullptr;
|
||||||
|
|
||||||
VulkanContext *context = nullptr;
|
VulkanContext *context = nullptr;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,567 @@
|
||||||
|
diff --git a/thirdparty/vulkan/vk_mem_alloc.h b/thirdparty/vulkan/vk_mem_alloc.h
|
||||||
|
index 74c66b9789..89e00e6326 100644
|
||||||
|
--- a/thirdparty/vulkan/vk_mem_alloc.h
|
||||||
|
+++ b/thirdparty/vulkan/vk_mem_alloc.h
|
||||||
|
@@ -1127,31 +1127,26 @@ typedef struct VmaAllocationCreateInfo
|
||||||
|
/** \brief Intended usage of memory.
|
||||||
|
|
||||||
|
You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n
|
||||||
|
- If `pool` is not null, this member is ignored.
|
||||||
|
*/
|
||||||
|
VmaMemoryUsage usage;
|
||||||
|
/** \brief Flags that must be set in a Memory Type chosen for an allocation.
|
||||||
|
|
||||||
|
- Leave 0 if you specify memory requirements in other way. \n
|
||||||
|
- If `pool` is not null, this member is ignored.*/
|
||||||
|
+ Leave 0 if you specify memory requirements in other way.*/
|
||||||
|
VkMemoryPropertyFlags requiredFlags;
|
||||||
|
/** \brief Flags that preferably should be set in a memory type chosen for an allocation.
|
||||||
|
|
||||||
|
- Set to 0 if no additional flags are preferred. \n
|
||||||
|
- If `pool` is not null, this member is ignored. */
|
||||||
|
+ Set to 0 if no additional flags are preferred.*/
|
||||||
|
VkMemoryPropertyFlags preferredFlags;
|
||||||
|
/** \brief Bitmask containing one bit set for every memory type acceptable for this allocation.
|
||||||
|
|
||||||
|
Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if
|
||||||
|
it meets other requirements specified by this structure, with no further
|
||||||
|
restrictions on memory type index. \n
|
||||||
|
- If `pool` is not null, this member is ignored.
|
||||||
|
*/
|
||||||
|
uint32_t memoryTypeBits;
|
||||||
|
/** \brief Pool that this allocation should be created in.
|
||||||
|
|
||||||
|
- Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members:
|
||||||
|
- `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored.
|
||||||
|
+ Leave `VK_NULL_HANDLE` to allocate from default pool.
|
||||||
|
*/
|
||||||
|
VmaPool VMA_NULLABLE pool;
|
||||||
|
/** \brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData().
|
||||||
|
@@ -1173,9 +1168,6 @@ typedef struct VmaAllocationCreateInfo
|
||||||
|
/// Describes parameter of created #VmaPool.
|
||||||
|
typedef struct VmaPoolCreateInfo
|
||||||
|
{
|
||||||
|
- /** \brief Vulkan memory type index to allocate this pool from.
|
||||||
|
- */
|
||||||
|
- uint32_t memoryTypeIndex;
|
||||||
|
/** \brief Use combination of #VmaPoolCreateFlagBits.
|
||||||
|
*/
|
||||||
|
VmaPoolCreateFlags flags;
|
||||||
|
@@ -10904,13 +10896,12 @@ struct VmaPool_T
|
||||||
|
friend struct VmaPoolListItemTraits;
|
||||||
|
VMA_CLASS_NO_COPY(VmaPool_T)
|
||||||
|
public:
|
||||||
|
- VmaBlockVector m_BlockVector;
|
||||||
|
- VmaDedicatedAllocationList m_DedicatedAllocations;
|
||||||
|
+ VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES];
|
||||||
|
+ VmaDedicatedAllocationList m_DedicatedAllocations[VK_MAX_MEMORY_TYPES];
|
||||||
|
|
||||||
|
VmaPool_T(
|
||||||
|
VmaAllocator hAllocator,
|
||||||
|
- const VmaPoolCreateInfo& createInfo,
|
||||||
|
- VkDeviceSize preferredBlockSize);
|
||||||
|
+ const VmaPoolCreateInfo& createInfo);
|
||||||
|
~VmaPool_T();
|
||||||
|
|
||||||
|
uint32_t GetId() const { return m_Id; }
|
||||||
|
@@ -10924,6 +10915,7 @@ public:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
+ const VmaAllocator m_hAllocator;
|
||||||
|
uint32_t m_Id;
|
||||||
|
char* m_Name;
|
||||||
|
VmaPool_T* m_PrevPool = VMA_NULL;
|
||||||
|
@@ -11405,8 +11397,10 @@ private:
|
||||||
|
|
||||||
|
void ValidateVulkanFunctions();
|
||||||
|
|
||||||
|
+public: // I'm sorry
|
||||||
|
VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex);
|
||||||
|
|
||||||
|
+private:
|
||||||
|
VkResult AllocateMemoryOfType(
|
||||||
|
VmaPool pool,
|
||||||
|
VkDeviceSize size,
|
||||||
|
@@ -14176,30 +14170,36 @@ void VmaDefragmentationContext_T::AddPools(uint32_t poolCount, const VmaPool* pP
|
||||||
|
{
|
||||||
|
VmaPool pool = pPools[poolIndex];
|
||||||
|
VMA_ASSERT(pool);
|
||||||
|
- // Pools with algorithm other than default are not defragmented.
|
||||||
|
- if (pool->m_BlockVector.GetAlgorithm() == 0)
|
||||||
|
+ for(uint32_t memTypeIndex = 0; memTypeIndex < m_hAllocator->GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
{
|
||||||
|
- VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;
|
||||||
|
-
|
||||||
|
- for (size_t i = m_CustomPoolContexts.size(); i--; )
|
||||||
|
+ if(pool->m_pBlockVectors[memTypeIndex])
|
||||||
|
{
|
||||||
|
- if (m_CustomPoolContexts[i]->GetCustomPool() == pool)
|
||||||
|
+ // Pools with algorithm other than default are not defragmented.
|
||||||
|
+ if (pool->m_pBlockVectors[memTypeIndex]->GetAlgorithm() == 0)
|
||||||
|
{
|
||||||
|
- pBlockVectorDefragCtx = m_CustomPoolContexts[i];
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;
|
||||||
|
|
||||||
|
- if (!pBlockVectorDefragCtx)
|
||||||
|
- {
|
||||||
|
- pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
|
||||||
|
- m_hAllocator,
|
||||||
|
- pool,
|
||||||
|
- &pool->m_BlockVector);
|
||||||
|
- m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
|
||||||
|
- }
|
||||||
|
+ for (size_t i = m_CustomPoolContexts.size(); i--; )
|
||||||
|
+ {
|
||||||
|
+ if (m_CustomPoolContexts[i]->GetCustomPool() == pool)
|
||||||
|
+ {
|
||||||
|
+ pBlockVectorDefragCtx = m_CustomPoolContexts[i];
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!pBlockVectorDefragCtx)
|
||||||
|
+ {
|
||||||
|
+ pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
|
||||||
|
+ m_hAllocator,
|
||||||
|
+ pool,
|
||||||
|
+ pool->m_pBlockVectors[memTypeIndex]);
|
||||||
|
+ m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- pBlockVectorDefragCtx->AddAll();
|
||||||
|
+ pBlockVectorDefragCtx->AddAll();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -14214,6 +14214,7 @@ void VmaDefragmentationContext_T::AddAllocations(
|
||||||
|
{
|
||||||
|
const VmaAllocation hAlloc = pAllocations[allocIndex];
|
||||||
|
VMA_ASSERT(hAlloc);
|
||||||
|
+ const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex();
|
||||||
|
// DedicatedAlloc cannot be defragmented.
|
||||||
|
if (hAlloc->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK)
|
||||||
|
{
|
||||||
|
@@ -14224,7 +14225,7 @@ void VmaDefragmentationContext_T::AddAllocations(
|
||||||
|
if (hAllocPool != VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
// Pools with algorithm other than default are not defragmented.
|
||||||
|
- if (hAllocPool->m_BlockVector.GetAlgorithm() == 0)
|
||||||
|
+ if (hAllocPool->m_pBlockVectors[memTypeIndex]->GetAlgorithm() == 0)
|
||||||
|
{
|
||||||
|
for (size_t i = m_CustomPoolContexts.size(); i--; )
|
||||||
|
{
|
||||||
|
@@ -14239,7 +14240,7 @@ void VmaDefragmentationContext_T::AddAllocations(
|
||||||
|
pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
|
||||||
|
m_hAllocator,
|
||||||
|
hAllocPool,
|
||||||
|
- &hAllocPool->m_BlockVector);
|
||||||
|
+ hAllocPool->m_pBlockVectors[memTypeIndex]);
|
||||||
|
m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -14247,7 +14248,6 @@ void VmaDefragmentationContext_T::AddAllocations(
|
||||||
|
// This allocation belongs to default pool.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
- const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex();
|
||||||
|
pBlockVectorDefragCtx = m_DefaultPoolContexts[memTypeIndex];
|
||||||
|
if (!pBlockVectorDefragCtx)
|
||||||
|
{
|
||||||
|
@@ -14481,41 +14481,61 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd()
|
||||||
|
#ifndef _VMA_POOL_T_FUNCTIONS
|
||||||
|
VmaPool_T::VmaPool_T(
|
||||||
|
VmaAllocator hAllocator,
|
||||||
|
- const VmaPoolCreateInfo& createInfo,
|
||||||
|
- VkDeviceSize preferredBlockSize)
|
||||||
|
- : m_BlockVector(
|
||||||
|
- hAllocator,
|
||||||
|
- this, // hParentPool
|
||||||
|
- createInfo.memoryTypeIndex,
|
||||||
|
- createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize,
|
||||||
|
- createInfo.minBlockCount,
|
||||||
|
- createInfo.maxBlockCount,
|
||||||
|
- (createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(),
|
||||||
|
- createInfo.blockSize != 0, // explicitBlockSize
|
||||||
|
- createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm
|
||||||
|
- createInfo.priority,
|
||||||
|
- VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(createInfo.memoryTypeIndex), createInfo.minAllocationAlignment),
|
||||||
|
- createInfo.pMemoryAllocateNext),
|
||||||
|
+ const VmaPoolCreateInfo& createInfo) :
|
||||||
|
+ m_hAllocator(hAllocator),
|
||||||
|
+ m_pBlockVectors{},
|
||||||
|
m_Id(0),
|
||||||
|
- m_Name(VMA_NULL) {}
|
||||||
|
+ m_Name(VMA_NULL)
|
||||||
|
+{
|
||||||
|
+ for(uint32_t memTypeIndex = 0; memTypeIndex < hAllocator->GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
+ {
|
||||||
|
+ // Create only supported types
|
||||||
|
+ if((hAllocator->GetGlobalMemoryTypeBits() & (1u << memTypeIndex)) != 0)
|
||||||
|
+ {
|
||||||
|
+ m_pBlockVectors[memTypeIndex] = vma_new(hAllocator, VmaBlockVector)(
|
||||||
|
+ hAllocator,
|
||||||
|
+ this, // hParentPool
|
||||||
|
+ memTypeIndex,
|
||||||
|
+ createInfo.blockSize != 0 ? createInfo.blockSize : hAllocator->CalcPreferredBlockSize(memTypeIndex),
|
||||||
|
+ createInfo.minBlockCount,
|
||||||
|
+ createInfo.maxBlockCount,
|
||||||
|
+ (createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(),
|
||||||
|
+ false, // explicitBlockSize
|
||||||
|
+ createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm
|
||||||
|
+ createInfo.priority,
|
||||||
|
+ VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(memTypeIndex), createInfo.minAllocationAlignment),
|
||||||
|
+ createInfo.pMemoryAllocateNext);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
|
||||||
|
VmaPool_T::~VmaPool_T()
|
||||||
|
{
|
||||||
|
VMA_ASSERT(m_PrevPool == VMA_NULL && m_NextPool == VMA_NULL);
|
||||||
|
+ for(uint32_t memTypeIndex = 0; memTypeIndex < m_hAllocator->GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
+ {
|
||||||
|
+ vma_delete(m_hAllocator, m_pBlockVectors[memTypeIndex]);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void VmaPool_T::SetName(const char* pName)
|
||||||
|
{
|
||||||
|
- const VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()->GetAllocationCallbacks();
|
||||||
|
- VmaFreeString(allocs, m_Name);
|
||||||
|
-
|
||||||
|
- if (pName != VMA_NULL)
|
||||||
|
- {
|
||||||
|
- m_Name = VmaCreateStringCopy(allocs, pName);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
+ for(uint32_t memTypeIndex = 0; memTypeIndex < m_hAllocator->GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
{
|
||||||
|
- m_Name = VMA_NULL;
|
||||||
|
+ if(m_pBlockVectors[memTypeIndex])
|
||||||
|
+ {
|
||||||
|
+ const VkAllocationCallbacks* allocs = m_pBlockVectors[memTypeIndex]->GetAllocator()->GetAllocationCallbacks();
|
||||||
|
+ VmaFreeString(allocs, m_Name);
|
||||||
|
+
|
||||||
|
+ if (pName != VMA_NULL)
|
||||||
|
+ {
|
||||||
|
+ m_Name = VmaCreateStringCopy(allocs, pName);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ m_Name = VMA_NULL;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // _VMA_POOL_T_FUNCTIONS
|
||||||
|
@@ -15377,15 +15397,22 @@ VkResult VmaAllocator_T::CalcAllocationParams(
|
||||||
|
inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if(inoutCreateInfo.pool != VK_NULL_HANDLE)
|
||||||
|
+ if(inoutCreateInfo.pool != VK_NULL_HANDLE && (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0)
|
||||||
|
{
|
||||||
|
- if(inoutCreateInfo.pool->m_BlockVector.HasExplicitBlockSize() &&
|
||||||
|
- (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0)
|
||||||
|
+ // Assuming here every block has the same block size and priority.
|
||||||
|
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
{
|
||||||
|
- VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations.");
|
||||||
|
- return VK_ERROR_FEATURE_NOT_PRESENT;
|
||||||
|
+ if(inoutCreateInfo.pool->m_pBlockVectors[memTypeIndex])
|
||||||
|
+ {
|
||||||
|
+ if(inoutCreateInfo.pool->m_pBlockVectors[memTypeIndex]->HasExplicitBlockSize())
|
||||||
|
+ {
|
||||||
|
+ VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations.");
|
||||||
|
+ return VK_ERROR_FEATURE_NOT_PRESENT;
|
||||||
|
+ }
|
||||||
|
+ inoutCreateInfo.priority = inoutCreateInfo.pool->m_pBlockVectors[memTypeIndex]->GetPriority();
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
- inoutCreateInfo.priority = inoutCreateInfo.pool->m_BlockVector.GetPriority();
|
||||||
|
}
|
||||||
|
|
||||||
|
if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 &&
|
||||||
|
@@ -15429,67 +15456,46 @@ VkResult VmaAllocator_T::AllocateMemory(
|
||||||
|
if(res != VK_SUCCESS)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
- if(createInfoFinal.pool != VK_NULL_HANDLE)
|
||||||
|
+ // Bit mask of memory Vulkan types acceptable for this allocation.
|
||||||
|
+ uint32_t memoryTypeBits = vkMemReq.memoryTypeBits;
|
||||||
|
+ uint32_t memTypeIndex = UINT32_MAX;
|
||||||
|
+ res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex);
|
||||||
|
+ // Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT.
|
||||||
|
+ if(res != VK_SUCCESS)
|
||||||
|
+ return res;
|
||||||
|
+ do
|
||||||
|
{
|
||||||
|
- VmaBlockVector& blockVector = createInfoFinal.pool->m_BlockVector;
|
||||||
|
- return AllocateMemoryOfType(
|
||||||
|
+ VmaBlockVector* blockVector = createInfoFinal.pool == VK_NULL_HANDLE ? m_pBlockVectors[memTypeIndex] : createInfoFinal.pool->m_pBlockVectors[memTypeIndex];
|
||||||
|
+ VMA_ASSERT(blockVector && "Trying to use unsupported memory type!");
|
||||||
|
+ VmaDedicatedAllocationList& dedicatedAllocations = createInfoFinal.pool == VK_NULL_HANDLE ? m_DedicatedAllocations[memTypeIndex] : createInfoFinal.pool->m_DedicatedAllocations[memTypeIndex];
|
||||||
|
+ res = AllocateMemoryOfType(
|
||||||
|
createInfoFinal.pool,
|
||||||
|
vkMemReq.size,
|
||||||
|
vkMemReq.alignment,
|
||||||
|
- prefersDedicatedAllocation,
|
||||||
|
+ requiresDedicatedAllocation || prefersDedicatedAllocation,
|
||||||
|
dedicatedBuffer,
|
||||||
|
dedicatedBufferUsage,
|
||||||
|
dedicatedImage,
|
||||||
|
createInfoFinal,
|
||||||
|
- blockVector.GetMemoryTypeIndex(),
|
||||||
|
+ memTypeIndex,
|
||||||
|
suballocType,
|
||||||
|
- createInfoFinal.pool->m_DedicatedAllocations,
|
||||||
|
- blockVector,
|
||||||
|
+ dedicatedAllocations,
|
||||||
|
+ *blockVector,
|
||||||
|
allocationCount,
|
||||||
|
pAllocations);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- // Bit mask of memory Vulkan types acceptable for this allocation.
|
||||||
|
- uint32_t memoryTypeBits = vkMemReq.memoryTypeBits;
|
||||||
|
- uint32_t memTypeIndex = UINT32_MAX;
|
||||||
|
- res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex);
|
||||||
|
- // Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT.
|
||||||
|
- if(res != VK_SUCCESS)
|
||||||
|
- return res;
|
||||||
|
- do
|
||||||
|
- {
|
||||||
|
- VmaBlockVector* blockVector = m_pBlockVectors[memTypeIndex];
|
||||||
|
- VMA_ASSERT(blockVector && "Trying to use unsupported memory type!");
|
||||||
|
- res = AllocateMemoryOfType(
|
||||||
|
- VK_NULL_HANDLE,
|
||||||
|
- vkMemReq.size,
|
||||||
|
- vkMemReq.alignment,
|
||||||
|
- requiresDedicatedAllocation || prefersDedicatedAllocation,
|
||||||
|
- dedicatedBuffer,
|
||||||
|
- dedicatedBufferUsage,
|
||||||
|
- dedicatedImage,
|
||||||
|
- createInfoFinal,
|
||||||
|
- memTypeIndex,
|
||||||
|
- suballocType,
|
||||||
|
- m_DedicatedAllocations[memTypeIndex],
|
||||||
|
- *blockVector,
|
||||||
|
- allocationCount,
|
||||||
|
- pAllocations);
|
||||||
|
- // Allocation succeeded
|
||||||
|
- if(res == VK_SUCCESS)
|
||||||
|
- return VK_SUCCESS;
|
||||||
|
+ // Allocation succeeded
|
||||||
|
+ if(res == VK_SUCCESS)
|
||||||
|
+ return VK_SUCCESS;
|
||||||
|
|
||||||
|
- // Remove old memTypeIndex from list of possibilities.
|
||||||
|
- memoryTypeBits &= ~(1u << memTypeIndex);
|
||||||
|
- // Find alternative memTypeIndex.
|
||||||
|
- res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex);
|
||||||
|
- } while(res == VK_SUCCESS);
|
||||||
|
+ // Remove old memTypeIndex from list of possibilities.
|
||||||
|
+ memoryTypeBits &= ~(1u << memTypeIndex);
|
||||||
|
+ // Find alternative memTypeIndex.
|
||||||
|
+ res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex);
|
||||||
|
+ } while(res == VK_SUCCESS);
|
||||||
|
|
||||||
|
- // No other matching memory type index could be found.
|
||||||
|
- // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once.
|
||||||
|
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
||||||
|
- }
|
||||||
|
+ // No other matching memory type index could be found.
|
||||||
|
+ // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once.
|
||||||
|
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VmaAllocator_T::FreeMemory(
|
||||||
|
@@ -15515,16 +15521,16 @@ void VmaAllocator_T::FreeMemory(
|
||||||
|
{
|
||||||
|
VmaBlockVector* pBlockVector = VMA_NULL;
|
||||||
|
VmaPool hPool = allocation->GetParentPool();
|
||||||
|
+ const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
|
||||||
|
if(hPool != VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
- pBlockVector = &hPool->m_BlockVector;
|
||||||
|
+ pBlockVector = hPool->m_pBlockVectors[memTypeIndex];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
- const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
|
||||||
|
pBlockVector = m_pBlockVectors[memTypeIndex];
|
||||||
|
- VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!");
|
||||||
|
}
|
||||||
|
+ VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!");
|
||||||
|
pBlockVector->Free(allocation);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
@@ -15564,11 +15570,17 @@ void VmaAllocator_T::CalculateStats(VmaStats* pStats)
|
||||||
|
VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
|
||||||
|
for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool))
|
||||||
|
{
|
||||||
|
- VmaBlockVector& blockVector = pool->m_BlockVector;
|
||||||
|
- blockVector.AddStats(pStats);
|
||||||
|
- const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex();
|
||||||
|
- const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
|
||||||
|
- pool->m_DedicatedAllocations.AddStats(pStats, memTypeIndex, memHeapIndex);
|
||||||
|
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
+ {
|
||||||
|
+ if (pool->m_pBlockVectors[memTypeIndex])
|
||||||
|
+ {
|
||||||
|
+ VmaBlockVector& blockVector = *pool->m_pBlockVectors[memTypeIndex];
|
||||||
|
+ blockVector.AddStats(pStats);
|
||||||
|
+ const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex();
|
||||||
|
+ const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
|
||||||
|
+ pool->m_DedicatedAllocations[memTypeIndex].AddStats(pStats, memTypeIndex, memHeapIndex);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -15720,27 +15732,26 @@ VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPoo
|
||||||
|
{
|
||||||
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
- // Memory type index out of range or forbidden.
|
||||||
|
- if(pCreateInfo->memoryTypeIndex >= GetMemoryTypeCount() ||
|
||||||
|
- ((1u << pCreateInfo->memoryTypeIndex) & m_GlobalMemoryTypeBits) == 0)
|
||||||
|
- {
|
||||||
|
- return VK_ERROR_FEATURE_NOT_PRESENT;
|
||||||
|
- }
|
||||||
|
if(newCreateInfo.minAllocationAlignment > 0)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(VmaIsPow2(newCreateInfo.minAllocationAlignment));
|
||||||
|
}
|
||||||
|
|
||||||
|
- const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(newCreateInfo.memoryTypeIndex);
|
||||||
|
-
|
||||||
|
- *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo, preferredBlockSize);
|
||||||
|
+ *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo);
|
||||||
|
|
||||||
|
- VkResult res = (*pPool)->m_BlockVector.CreateMinBlocks();
|
||||||
|
- if(res != VK_SUCCESS)
|
||||||
|
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
{
|
||||||
|
- vma_delete(this, *pPool);
|
||||||
|
- *pPool = VMA_NULL;
|
||||||
|
- return res;
|
||||||
|
+ // Create only supported types
|
||||||
|
+ if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0)
|
||||||
|
+ {
|
||||||
|
+ VkResult res = (*pPool)->m_pBlockVectors[memTypeIndex]->CreateMinBlocks();
|
||||||
|
+ if(res != VK_SUCCESS)
|
||||||
|
+ {
|
||||||
|
+ vma_delete(this, *pPool);
|
||||||
|
+ *pPool = VMA_NULL;
|
||||||
|
+ return res;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to m_Pools.
|
||||||
|
@@ -15772,8 +15783,14 @@ void VmaAllocator_T::GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats)
|
||||||
|
pPoolStats->unusedRangeCount = 0;
|
||||||
|
pPoolStats->blockCount = 0;
|
||||||
|
|
||||||
|
- pool->m_BlockVector.AddPoolStats(pPoolStats);
|
||||||
|
- pool->m_DedicatedAllocations.AddPoolStats(pPoolStats);
|
||||||
|
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
+ {
|
||||||
|
+ if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0)
|
||||||
|
+ {
|
||||||
|
+ pool->m_pBlockVectors[memTypeIndex]->AddPoolStats(pPoolStats);
|
||||||
|
+ pool->m_DedicatedAllocations[memTypeIndex].AddPoolStats(pPoolStats);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex)
|
||||||
|
@@ -15790,7 +15807,13 @@ void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex)
|
||||||
|
|
||||||
|
VkResult VmaAllocator_T::CheckPoolCorruption(VmaPool hPool)
|
||||||
|
{
|
||||||
|
- return hPool->m_BlockVector.CheckCorruption();
|
||||||
|
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
+ {
|
||||||
|
+ if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0)
|
||||||
|
+ {
|
||||||
|
+ return hPool->m_pBlockVectors[memTypeIndex]->CheckCorruption();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits)
|
||||||
|
@@ -15822,18 +15845,21 @@ VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits)
|
||||||
|
VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
|
||||||
|
for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool))
|
||||||
|
{
|
||||||
|
- if(((1u << pool->m_BlockVector.GetMemoryTypeIndex()) & memoryTypeBits) != 0)
|
||||||
|
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
{
|
||||||
|
- VkResult localRes = pool->m_BlockVector.CheckCorruption();
|
||||||
|
- switch(localRes)
|
||||||
|
+ if(pool->m_pBlockVectors[memTypeIndex] && ((1u << memTypeIndex) & memoryTypeBits) != 0)
|
||||||
|
{
|
||||||
|
- case VK_ERROR_FEATURE_NOT_PRESENT:
|
||||||
|
- break;
|
||||||
|
- case VK_SUCCESS:
|
||||||
|
- finalRes = VK_SUCCESS;
|
||||||
|
- break;
|
||||||
|
- default:
|
||||||
|
- return localRes;
|
||||||
|
+ VkResult localRes = pool->m_pBlockVectors[memTypeIndex]->CheckCorruption();
|
||||||
|
+ switch(localRes)
|
||||||
|
+ {
|
||||||
|
+ case VK_ERROR_FEATURE_NOT_PRESENT:
|
||||||
|
+ break;
|
||||||
|
+ case VK_SUCCESS:
|
||||||
|
+ finalRes = VK_SUCCESS;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return localRes;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -16155,7 +16181,7 @@ void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Custom pool
|
||||||
|
- parentPool->m_DedicatedAllocations.Unregister(allocation);
|
||||||
|
+ parentPool->m_DedicatedAllocations[memTypeIndex].Unregister(allocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDeviceMemory hMemory = allocation->GetMemory();
|
||||||
|
@@ -16430,12 +16456,18 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
|
||||||
|
json.EndString();
|
||||||
|
|
||||||
|
json.BeginObject();
|
||||||
|
- pool->m_BlockVector.PrintDetailedMap(json);
|
||||||
|
-
|
||||||
|
- if (!pool->m_DedicatedAllocations.IsEmpty())
|
||||||
|
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
{
|
||||||
|
- json.WriteString("DedicatedAllocations");
|
||||||
|
- pool->m_DedicatedAllocations.BuildStatsString(json);
|
||||||
|
+ if (pool->m_pBlockVectors[memTypeIndex])
|
||||||
|
+ {
|
||||||
|
+ pool->m_pBlockVectors[memTypeIndex]->PrintDetailedMap(json);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!pool->m_DedicatedAllocations[memTypeIndex].IsEmpty())
|
||||||
|
+ {
|
||||||
|
+ json.WriteString("DedicatedAllocations");
|
||||||
|
+ pool->m_DedicatedAllocations->BuildStatsString(json);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
json.EndObject();
|
||||||
|
}
|
|
@ -1127,31 +1127,26 @@ typedef struct VmaAllocationCreateInfo
|
||||||
/** \brief Intended usage of memory.
|
/** \brief Intended usage of memory.
|
||||||
|
|
||||||
You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n
|
You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n
|
||||||
If `pool` is not null, this member is ignored.
|
|
||||||
*/
|
*/
|
||||||
VmaMemoryUsage usage;
|
VmaMemoryUsage usage;
|
||||||
/** \brief Flags that must be set in a Memory Type chosen for an allocation.
|
/** \brief Flags that must be set in a Memory Type chosen for an allocation.
|
||||||
|
|
||||||
Leave 0 if you specify memory requirements in other way. \n
|
Leave 0 if you specify memory requirements in other way.*/
|
||||||
If `pool` is not null, this member is ignored.*/
|
|
||||||
VkMemoryPropertyFlags requiredFlags;
|
VkMemoryPropertyFlags requiredFlags;
|
||||||
/** \brief Flags that preferably should be set in a memory type chosen for an allocation.
|
/** \brief Flags that preferably should be set in a memory type chosen for an allocation.
|
||||||
|
|
||||||
Set to 0 if no additional flags are preferred. \n
|
Set to 0 if no additional flags are preferred.*/
|
||||||
If `pool` is not null, this member is ignored. */
|
|
||||||
VkMemoryPropertyFlags preferredFlags;
|
VkMemoryPropertyFlags preferredFlags;
|
||||||
/** \brief Bitmask containing one bit set for every memory type acceptable for this allocation.
|
/** \brief Bitmask containing one bit set for every memory type acceptable for this allocation.
|
||||||
|
|
||||||
Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if
|
Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if
|
||||||
it meets other requirements specified by this structure, with no further
|
it meets other requirements specified by this structure, with no further
|
||||||
restrictions on memory type index. \n
|
restrictions on memory type index. \n
|
||||||
If `pool` is not null, this member is ignored.
|
|
||||||
*/
|
*/
|
||||||
uint32_t memoryTypeBits;
|
uint32_t memoryTypeBits;
|
||||||
/** \brief Pool that this allocation should be created in.
|
/** \brief Pool that this allocation should be created in.
|
||||||
|
|
||||||
Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members:
|
Leave `VK_NULL_HANDLE` to allocate from default pool.
|
||||||
`usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored.
|
|
||||||
*/
|
*/
|
||||||
VmaPool VMA_NULLABLE pool;
|
VmaPool VMA_NULLABLE pool;
|
||||||
/** \brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData().
|
/** \brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData().
|
||||||
|
@ -1173,9 +1168,6 @@ typedef struct VmaAllocationCreateInfo
|
||||||
/// Describes parameter of created #VmaPool.
|
/// Describes parameter of created #VmaPool.
|
||||||
typedef struct VmaPoolCreateInfo
|
typedef struct VmaPoolCreateInfo
|
||||||
{
|
{
|
||||||
/** \brief Vulkan memory type index to allocate this pool from.
|
|
||||||
*/
|
|
||||||
uint32_t memoryTypeIndex;
|
|
||||||
/** \brief Use combination of #VmaPoolCreateFlagBits.
|
/** \brief Use combination of #VmaPoolCreateFlagBits.
|
||||||
*/
|
*/
|
||||||
VmaPoolCreateFlags flags;
|
VmaPoolCreateFlags flags;
|
||||||
|
@ -10904,13 +10896,12 @@ struct VmaPool_T
|
||||||
friend struct VmaPoolListItemTraits;
|
friend struct VmaPoolListItemTraits;
|
||||||
VMA_CLASS_NO_COPY(VmaPool_T)
|
VMA_CLASS_NO_COPY(VmaPool_T)
|
||||||
public:
|
public:
|
||||||
VmaBlockVector m_BlockVector;
|
VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES];
|
||||||
VmaDedicatedAllocationList m_DedicatedAllocations;
|
VmaDedicatedAllocationList m_DedicatedAllocations[VK_MAX_MEMORY_TYPES];
|
||||||
|
|
||||||
VmaPool_T(
|
VmaPool_T(
|
||||||
VmaAllocator hAllocator,
|
VmaAllocator hAllocator,
|
||||||
const VmaPoolCreateInfo& createInfo,
|
const VmaPoolCreateInfo& createInfo);
|
||||||
VkDeviceSize preferredBlockSize);
|
|
||||||
~VmaPool_T();
|
~VmaPool_T();
|
||||||
|
|
||||||
uint32_t GetId() const { return m_Id; }
|
uint32_t GetId() const { return m_Id; }
|
||||||
|
@ -10924,6 +10915,7 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const VmaAllocator m_hAllocator;
|
||||||
uint32_t m_Id;
|
uint32_t m_Id;
|
||||||
char* m_Name;
|
char* m_Name;
|
||||||
VmaPool_T* m_PrevPool = VMA_NULL;
|
VmaPool_T* m_PrevPool = VMA_NULL;
|
||||||
|
@ -11405,8 +11397,10 @@ private:
|
||||||
|
|
||||||
void ValidateVulkanFunctions();
|
void ValidateVulkanFunctions();
|
||||||
|
|
||||||
|
public: // I'm sorry
|
||||||
VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex);
|
VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex);
|
||||||
|
|
||||||
|
private:
|
||||||
VkResult AllocateMemoryOfType(
|
VkResult AllocateMemoryOfType(
|
||||||
VmaPool pool,
|
VmaPool pool,
|
||||||
VkDeviceSize size,
|
VkDeviceSize size,
|
||||||
|
@ -14176,30 +14170,36 @@ void VmaDefragmentationContext_T::AddPools(uint32_t poolCount, const VmaPool* pP
|
||||||
{
|
{
|
||||||
VmaPool pool = pPools[poolIndex];
|
VmaPool pool = pPools[poolIndex];
|
||||||
VMA_ASSERT(pool);
|
VMA_ASSERT(pool);
|
||||||
// Pools with algorithm other than default are not defragmented.
|
for(uint32_t memTypeIndex = 0; memTypeIndex < m_hAllocator->GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
if (pool->m_BlockVector.GetAlgorithm() == 0)
|
|
||||||
{
|
{
|
||||||
VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;
|
if(pool->m_pBlockVectors[memTypeIndex])
|
||||||
|
|
||||||
for (size_t i = m_CustomPoolContexts.size(); i--; )
|
|
||||||
{
|
{
|
||||||
if (m_CustomPoolContexts[i]->GetCustomPool() == pool)
|
// Pools with algorithm other than default are not defragmented.
|
||||||
|
if (pool->m_pBlockVectors[memTypeIndex]->GetAlgorithm() == 0)
|
||||||
{
|
{
|
||||||
pBlockVectorDefragCtx = m_CustomPoolContexts[i];
|
VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;
|
||||||
break;
|
|
||||||
|
for (size_t i = m_CustomPoolContexts.size(); i--; )
|
||||||
|
{
|
||||||
|
if (m_CustomPoolContexts[i]->GetCustomPool() == pool)
|
||||||
|
{
|
||||||
|
pBlockVectorDefragCtx = m_CustomPoolContexts[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pBlockVectorDefragCtx)
|
||||||
|
{
|
||||||
|
pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
|
||||||
|
m_hAllocator,
|
||||||
|
pool,
|
||||||
|
pool->m_pBlockVectors[memTypeIndex]);
|
||||||
|
m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
pBlockVectorDefragCtx->AddAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pBlockVectorDefragCtx)
|
|
||||||
{
|
|
||||||
pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
|
|
||||||
m_hAllocator,
|
|
||||||
pool,
|
|
||||||
&pool->m_BlockVector);
|
|
||||||
m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
pBlockVectorDefragCtx->AddAll();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14214,6 +14214,7 @@ void VmaDefragmentationContext_T::AddAllocations(
|
||||||
{
|
{
|
||||||
const VmaAllocation hAlloc = pAllocations[allocIndex];
|
const VmaAllocation hAlloc = pAllocations[allocIndex];
|
||||||
VMA_ASSERT(hAlloc);
|
VMA_ASSERT(hAlloc);
|
||||||
|
const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex();
|
||||||
// DedicatedAlloc cannot be defragmented.
|
// DedicatedAlloc cannot be defragmented.
|
||||||
if (hAlloc->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK)
|
if (hAlloc->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK)
|
||||||
{
|
{
|
||||||
|
@ -14224,7 +14225,7 @@ void VmaDefragmentationContext_T::AddAllocations(
|
||||||
if (hAllocPool != VK_NULL_HANDLE)
|
if (hAllocPool != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
// Pools with algorithm other than default are not defragmented.
|
// Pools with algorithm other than default are not defragmented.
|
||||||
if (hAllocPool->m_BlockVector.GetAlgorithm() == 0)
|
if (hAllocPool->m_pBlockVectors[memTypeIndex]->GetAlgorithm() == 0)
|
||||||
{
|
{
|
||||||
for (size_t i = m_CustomPoolContexts.size(); i--; )
|
for (size_t i = m_CustomPoolContexts.size(); i--; )
|
||||||
{
|
{
|
||||||
|
@ -14239,7 +14240,7 @@ void VmaDefragmentationContext_T::AddAllocations(
|
||||||
pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
|
pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
|
||||||
m_hAllocator,
|
m_hAllocator,
|
||||||
hAllocPool,
|
hAllocPool,
|
||||||
&hAllocPool->m_BlockVector);
|
hAllocPool->m_pBlockVectors[memTypeIndex]);
|
||||||
m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
|
m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14247,7 +14248,6 @@ void VmaDefragmentationContext_T::AddAllocations(
|
||||||
// This allocation belongs to default pool.
|
// This allocation belongs to default pool.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex();
|
|
||||||
pBlockVectorDefragCtx = m_DefaultPoolContexts[memTypeIndex];
|
pBlockVectorDefragCtx = m_DefaultPoolContexts[memTypeIndex];
|
||||||
if (!pBlockVectorDefragCtx)
|
if (!pBlockVectorDefragCtx)
|
||||||
{
|
{
|
||||||
|
@ -14481,41 +14481,61 @@ VkResult VmaDefragmentationContext_T::DefragmentPassEnd()
|
||||||
#ifndef _VMA_POOL_T_FUNCTIONS
|
#ifndef _VMA_POOL_T_FUNCTIONS
|
||||||
VmaPool_T::VmaPool_T(
|
VmaPool_T::VmaPool_T(
|
||||||
VmaAllocator hAllocator,
|
VmaAllocator hAllocator,
|
||||||
const VmaPoolCreateInfo& createInfo,
|
const VmaPoolCreateInfo& createInfo) :
|
||||||
VkDeviceSize preferredBlockSize)
|
m_hAllocator(hAllocator),
|
||||||
: m_BlockVector(
|
m_pBlockVectors{},
|
||||||
hAllocator,
|
|
||||||
this, // hParentPool
|
|
||||||
createInfo.memoryTypeIndex,
|
|
||||||
createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize,
|
|
||||||
createInfo.minBlockCount,
|
|
||||||
createInfo.maxBlockCount,
|
|
||||||
(createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(),
|
|
||||||
createInfo.blockSize != 0, // explicitBlockSize
|
|
||||||
createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm
|
|
||||||
createInfo.priority,
|
|
||||||
VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(createInfo.memoryTypeIndex), createInfo.minAllocationAlignment),
|
|
||||||
createInfo.pMemoryAllocateNext),
|
|
||||||
m_Id(0),
|
m_Id(0),
|
||||||
m_Name(VMA_NULL) {}
|
m_Name(VMA_NULL)
|
||||||
|
{
|
||||||
|
for(uint32_t memTypeIndex = 0; memTypeIndex < hAllocator->GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
{
|
||||||
|
// Create only supported types
|
||||||
|
if((hAllocator->GetGlobalMemoryTypeBits() & (1u << memTypeIndex)) != 0)
|
||||||
|
{
|
||||||
|
m_pBlockVectors[memTypeIndex] = vma_new(hAllocator, VmaBlockVector)(
|
||||||
|
hAllocator,
|
||||||
|
this, // hParentPool
|
||||||
|
memTypeIndex,
|
||||||
|
createInfo.blockSize != 0 ? createInfo.blockSize : hAllocator->CalcPreferredBlockSize(memTypeIndex),
|
||||||
|
createInfo.minBlockCount,
|
||||||
|
createInfo.maxBlockCount,
|
||||||
|
(createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(),
|
||||||
|
false, // explicitBlockSize
|
||||||
|
createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm
|
||||||
|
createInfo.priority,
|
||||||
|
VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(memTypeIndex), createInfo.minAllocationAlignment),
|
||||||
|
createInfo.pMemoryAllocateNext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VmaPool_T::~VmaPool_T()
|
VmaPool_T::~VmaPool_T()
|
||||||
{
|
{
|
||||||
VMA_ASSERT(m_PrevPool == VMA_NULL && m_NextPool == VMA_NULL);
|
VMA_ASSERT(m_PrevPool == VMA_NULL && m_NextPool == VMA_NULL);
|
||||||
|
for(uint32_t memTypeIndex = 0; memTypeIndex < m_hAllocator->GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
{
|
||||||
|
vma_delete(m_hAllocator, m_pBlockVectors[memTypeIndex]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VmaPool_T::SetName(const char* pName)
|
void VmaPool_T::SetName(const char* pName)
|
||||||
{
|
{
|
||||||
const VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()->GetAllocationCallbacks();
|
for(uint32_t memTypeIndex = 0; memTypeIndex < m_hAllocator->GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
VmaFreeString(allocs, m_Name);
|
{
|
||||||
|
if(m_pBlockVectors[memTypeIndex])
|
||||||
|
{
|
||||||
|
const VkAllocationCallbacks* allocs = m_pBlockVectors[memTypeIndex]->GetAllocator()->GetAllocationCallbacks();
|
||||||
|
VmaFreeString(allocs, m_Name);
|
||||||
|
|
||||||
if (pName != VMA_NULL)
|
if (pName != VMA_NULL)
|
||||||
{
|
{
|
||||||
m_Name = VmaCreateStringCopy(allocs, pName);
|
m_Name = VmaCreateStringCopy(allocs, pName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_Name = VMA_NULL;
|
m_Name = VMA_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // _VMA_POOL_T_FUNCTIONS
|
#endif // _VMA_POOL_T_FUNCTIONS
|
||||||
|
@ -15377,15 +15397,22 @@ VkResult VmaAllocator_T::CalcAllocationParams(
|
||||||
inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
|
inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(inoutCreateInfo.pool != VK_NULL_HANDLE)
|
if(inoutCreateInfo.pool != VK_NULL_HANDLE && (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0)
|
||||||
{
|
{
|
||||||
if(inoutCreateInfo.pool->m_BlockVector.HasExplicitBlockSize() &&
|
// Assuming here every block has the same block size and priority.
|
||||||
(inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0)
|
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
{
|
{
|
||||||
VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations.");
|
if(inoutCreateInfo.pool->m_pBlockVectors[memTypeIndex])
|
||||||
return VK_ERROR_FEATURE_NOT_PRESENT;
|
{
|
||||||
|
if(inoutCreateInfo.pool->m_pBlockVectors[memTypeIndex]->HasExplicitBlockSize())
|
||||||
|
{
|
||||||
|
VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations.");
|
||||||
|
return VK_ERROR_FEATURE_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
inoutCreateInfo.priority = inoutCreateInfo.pool->m_pBlockVectors[memTypeIndex]->GetPriority();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
inoutCreateInfo.priority = inoutCreateInfo.pool->m_BlockVector.GetPriority();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 &&
|
if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 &&
|
||||||
|
@ -15429,67 +15456,46 @@ VkResult VmaAllocator_T::AllocateMemory(
|
||||||
if(res != VK_SUCCESS)
|
if(res != VK_SUCCESS)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
if(createInfoFinal.pool != VK_NULL_HANDLE)
|
// Bit mask of memory Vulkan types acceptable for this allocation.
|
||||||
|
uint32_t memoryTypeBits = vkMemReq.memoryTypeBits;
|
||||||
|
uint32_t memTypeIndex = UINT32_MAX;
|
||||||
|
res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex);
|
||||||
|
// Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT.
|
||||||
|
if(res != VK_SUCCESS)
|
||||||
|
return res;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
VmaBlockVector& blockVector = createInfoFinal.pool->m_BlockVector;
|
VmaBlockVector* blockVector = createInfoFinal.pool == VK_NULL_HANDLE ? m_pBlockVectors[memTypeIndex] : createInfoFinal.pool->m_pBlockVectors[memTypeIndex];
|
||||||
return AllocateMemoryOfType(
|
VMA_ASSERT(blockVector && "Trying to use unsupported memory type!");
|
||||||
|
VmaDedicatedAllocationList& dedicatedAllocations = createInfoFinal.pool == VK_NULL_HANDLE ? m_DedicatedAllocations[memTypeIndex] : createInfoFinal.pool->m_DedicatedAllocations[memTypeIndex];
|
||||||
|
res = AllocateMemoryOfType(
|
||||||
createInfoFinal.pool,
|
createInfoFinal.pool,
|
||||||
vkMemReq.size,
|
vkMemReq.size,
|
||||||
vkMemReq.alignment,
|
vkMemReq.alignment,
|
||||||
prefersDedicatedAllocation,
|
requiresDedicatedAllocation || prefersDedicatedAllocation,
|
||||||
dedicatedBuffer,
|
dedicatedBuffer,
|
||||||
dedicatedBufferUsage,
|
dedicatedBufferUsage,
|
||||||
dedicatedImage,
|
dedicatedImage,
|
||||||
createInfoFinal,
|
createInfoFinal,
|
||||||
blockVector.GetMemoryTypeIndex(),
|
memTypeIndex,
|
||||||
suballocType,
|
suballocType,
|
||||||
createInfoFinal.pool->m_DedicatedAllocations,
|
dedicatedAllocations,
|
||||||
blockVector,
|
*blockVector,
|
||||||
allocationCount,
|
allocationCount,
|
||||||
pAllocations);
|
pAllocations);
|
||||||
}
|
// Allocation succeeded
|
||||||
else
|
if(res == VK_SUCCESS)
|
||||||
{
|
return VK_SUCCESS;
|
||||||
// Bit mask of memory Vulkan types acceptable for this allocation.
|
|
||||||
uint32_t memoryTypeBits = vkMemReq.memoryTypeBits;
|
// Remove old memTypeIndex from list of possibilities.
|
||||||
uint32_t memTypeIndex = UINT32_MAX;
|
memoryTypeBits &= ~(1u << memTypeIndex);
|
||||||
|
// Find alternative memTypeIndex.
|
||||||
res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex);
|
res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex);
|
||||||
// Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT.
|
} while(res == VK_SUCCESS);
|
||||||
if(res != VK_SUCCESS)
|
|
||||||
return res;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
VmaBlockVector* blockVector = m_pBlockVectors[memTypeIndex];
|
|
||||||
VMA_ASSERT(blockVector && "Trying to use unsupported memory type!");
|
|
||||||
res = AllocateMemoryOfType(
|
|
||||||
VK_NULL_HANDLE,
|
|
||||||
vkMemReq.size,
|
|
||||||
vkMemReq.alignment,
|
|
||||||
requiresDedicatedAllocation || prefersDedicatedAllocation,
|
|
||||||
dedicatedBuffer,
|
|
||||||
dedicatedBufferUsage,
|
|
||||||
dedicatedImage,
|
|
||||||
createInfoFinal,
|
|
||||||
memTypeIndex,
|
|
||||||
suballocType,
|
|
||||||
m_DedicatedAllocations[memTypeIndex],
|
|
||||||
*blockVector,
|
|
||||||
allocationCount,
|
|
||||||
pAllocations);
|
|
||||||
// Allocation succeeded
|
|
||||||
if(res == VK_SUCCESS)
|
|
||||||
return VK_SUCCESS;
|
|
||||||
|
|
||||||
// Remove old memTypeIndex from list of possibilities.
|
// No other matching memory type index could be found.
|
||||||
memoryTypeBits &= ~(1u << memTypeIndex);
|
// Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once.
|
||||||
// Find alternative memTypeIndex.
|
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
||||||
res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfoFinal, &memTypeIndex);
|
|
||||||
} while(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
// No other matching memory type index could be found.
|
|
||||||
// Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once.
|
|
||||||
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VmaAllocator_T::FreeMemory(
|
void VmaAllocator_T::FreeMemory(
|
||||||
|
@ -15515,16 +15521,16 @@ void VmaAllocator_T::FreeMemory(
|
||||||
{
|
{
|
||||||
VmaBlockVector* pBlockVector = VMA_NULL;
|
VmaBlockVector* pBlockVector = VMA_NULL;
|
||||||
VmaPool hPool = allocation->GetParentPool();
|
VmaPool hPool = allocation->GetParentPool();
|
||||||
|
const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
|
||||||
if(hPool != VK_NULL_HANDLE)
|
if(hPool != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
pBlockVector = &hPool->m_BlockVector;
|
pBlockVector = hPool->m_pBlockVectors[memTypeIndex];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
|
|
||||||
pBlockVector = m_pBlockVectors[memTypeIndex];
|
pBlockVector = m_pBlockVectors[memTypeIndex];
|
||||||
VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!");
|
|
||||||
}
|
}
|
||||||
|
VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!");
|
||||||
pBlockVector->Free(allocation);
|
pBlockVector->Free(allocation);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -15564,11 +15570,17 @@ void VmaAllocator_T::CalculateStats(VmaStats* pStats)
|
||||||
VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
|
VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
|
||||||
for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool))
|
for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool))
|
||||||
{
|
{
|
||||||
VmaBlockVector& blockVector = pool->m_BlockVector;
|
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
blockVector.AddStats(pStats);
|
{
|
||||||
const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex();
|
if (pool->m_pBlockVectors[memTypeIndex])
|
||||||
const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
|
{
|
||||||
pool->m_DedicatedAllocations.AddStats(pStats, memTypeIndex, memHeapIndex);
|
VmaBlockVector& blockVector = *pool->m_pBlockVectors[memTypeIndex];
|
||||||
|
blockVector.AddStats(pStats);
|
||||||
|
const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex();
|
||||||
|
const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
|
||||||
|
pool->m_DedicatedAllocations[memTypeIndex].AddStats(pStats, memTypeIndex, memHeapIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15720,27 +15732,26 @@ VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPoo
|
||||||
{
|
{
|
||||||
return VK_ERROR_INITIALIZATION_FAILED;
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
}
|
}
|
||||||
// Memory type index out of range or forbidden.
|
|
||||||
if(pCreateInfo->memoryTypeIndex >= GetMemoryTypeCount() ||
|
|
||||||
((1u << pCreateInfo->memoryTypeIndex) & m_GlobalMemoryTypeBits) == 0)
|
|
||||||
{
|
|
||||||
return VK_ERROR_FEATURE_NOT_PRESENT;
|
|
||||||
}
|
|
||||||
if(newCreateInfo.minAllocationAlignment > 0)
|
if(newCreateInfo.minAllocationAlignment > 0)
|
||||||
{
|
{
|
||||||
VMA_ASSERT(VmaIsPow2(newCreateInfo.minAllocationAlignment));
|
VMA_ASSERT(VmaIsPow2(newCreateInfo.minAllocationAlignment));
|
||||||
}
|
}
|
||||||
|
|
||||||
const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(newCreateInfo.memoryTypeIndex);
|
*pPool = vma_new(this, VmaPool_T)(this, newCreateInfo);
|
||||||
|
|
||||||
*pPool = vma_new(this, VmaPool_T)(this, newCreateInfo, preferredBlockSize);
|
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
|
||||||
VkResult res = (*pPool)->m_BlockVector.CreateMinBlocks();
|
|
||||||
if(res != VK_SUCCESS)
|
|
||||||
{
|
{
|
||||||
vma_delete(this, *pPool);
|
// Create only supported types
|
||||||
*pPool = VMA_NULL;
|
if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0)
|
||||||
return res;
|
{
|
||||||
|
VkResult res = (*pPool)->m_pBlockVectors[memTypeIndex]->CreateMinBlocks();
|
||||||
|
if(res != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
vma_delete(this, *pPool);
|
||||||
|
*pPool = VMA_NULL;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to m_Pools.
|
// Add to m_Pools.
|
||||||
|
@ -15772,8 +15783,14 @@ void VmaAllocator_T::GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats)
|
||||||
pPoolStats->unusedRangeCount = 0;
|
pPoolStats->unusedRangeCount = 0;
|
||||||
pPoolStats->blockCount = 0;
|
pPoolStats->blockCount = 0;
|
||||||
|
|
||||||
pool->m_BlockVector.AddPoolStats(pPoolStats);
|
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
pool->m_DedicatedAllocations.AddPoolStats(pPoolStats);
|
{
|
||||||
|
if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0)
|
||||||
|
{
|
||||||
|
pool->m_pBlockVectors[memTypeIndex]->AddPoolStats(pPoolStats);
|
||||||
|
pool->m_DedicatedAllocations[memTypeIndex].AddPoolStats(pPoolStats);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex)
|
void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex)
|
||||||
|
@ -15790,7 +15807,13 @@ void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex)
|
||||||
|
|
||||||
VkResult VmaAllocator_T::CheckPoolCorruption(VmaPool hPool)
|
VkResult VmaAllocator_T::CheckPoolCorruption(VmaPool hPool)
|
||||||
{
|
{
|
||||||
return hPool->m_BlockVector.CheckCorruption();
|
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
{
|
||||||
|
if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0)
|
||||||
|
{
|
||||||
|
return hPool->m_pBlockVectors[memTypeIndex]->CheckCorruption();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits)
|
VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits)
|
||||||
|
@ -15822,18 +15845,21 @@ VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits)
|
||||||
VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
|
VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
|
||||||
for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool))
|
for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool))
|
||||||
{
|
{
|
||||||
if(((1u << pool->m_BlockVector.GetMemoryTypeIndex()) & memoryTypeBits) != 0)
|
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
{
|
{
|
||||||
VkResult localRes = pool->m_BlockVector.CheckCorruption();
|
if(pool->m_pBlockVectors[memTypeIndex] && ((1u << memTypeIndex) & memoryTypeBits) != 0)
|
||||||
switch(localRes)
|
|
||||||
{
|
{
|
||||||
case VK_ERROR_FEATURE_NOT_PRESENT:
|
VkResult localRes = pool->m_pBlockVectors[memTypeIndex]->CheckCorruption();
|
||||||
break;
|
switch(localRes)
|
||||||
case VK_SUCCESS:
|
{
|
||||||
finalRes = VK_SUCCESS;
|
case VK_ERROR_FEATURE_NOT_PRESENT:
|
||||||
break;
|
break;
|
||||||
default:
|
case VK_SUCCESS:
|
||||||
return localRes;
|
finalRes = VK_SUCCESS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return localRes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16155,7 +16181,7 @@ void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Custom pool
|
// Custom pool
|
||||||
parentPool->m_DedicatedAllocations.Unregister(allocation);
|
parentPool->m_DedicatedAllocations[memTypeIndex].Unregister(allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDeviceMemory hMemory = allocation->GetMemory();
|
VkDeviceMemory hMemory = allocation->GetMemory();
|
||||||
|
@ -16430,12 +16456,18 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
|
||||||
json.EndString();
|
json.EndString();
|
||||||
|
|
||||||
json.BeginObject();
|
json.BeginObject();
|
||||||
pool->m_BlockVector.PrintDetailedMap(json);
|
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
|
||||||
|
|
||||||
if (!pool->m_DedicatedAllocations.IsEmpty())
|
|
||||||
{
|
{
|
||||||
json.WriteString("DedicatedAllocations");
|
if (pool->m_pBlockVectors[memTypeIndex])
|
||||||
pool->m_DedicatedAllocations.BuildStatsString(json);
|
{
|
||||||
|
pool->m_pBlockVectors[memTypeIndex]->PrintDetailedMap(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool->m_DedicatedAllocations[memTypeIndex].IsEmpty())
|
||||||
|
{
|
||||||
|
json.WriteString("DedicatedAllocations");
|
||||||
|
pool->m_DedicatedAllocations->BuildStatsString(json);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
json.EndObject();
|
json.EndObject();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue