mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
synced 2024-11-05 12:20:07 +00:00
Added initial implementation and a test
Every suballocation has a separate buffer for now, but otherwise entire API is implemented, except not all creation structure parameters and flags are respected yet.
This commit is contained in:
parent
8113ea104f
commit
441b6f41f6
@ -2781,15 +2781,16 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushBufferSuballocations(
|
|||||||
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
||||||
uint32_t bufferSuballocationCount,
|
uint32_t bufferSuballocationCount,
|
||||||
const VmaBufferSuballocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pBufferSuballocations,
|
const VmaBufferSuballocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pBufferSuballocations,
|
||||||
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pOffset,
|
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pOffsets,
|
||||||
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pSizes);
|
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pSizes);
|
||||||
/** \brief TODO implement! TODO document!
|
/** \brief TODO implement! TODO document!
|
||||||
*/
|
*/
|
||||||
VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateBufferSuballocations(
|
VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateBufferSuballocations(
|
||||||
VmaAllocator VMA_NOT_NULL allocator,
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
||||||
|
uint32_t bufferSuballocationCount,
|
||||||
const VmaBufferSuballocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pBufferSuballocations,
|
const VmaBufferSuballocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pBufferSuballocations,
|
||||||
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pOffset,
|
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pOffsets,
|
||||||
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pSizes);
|
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pSizes);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
@ -11591,6 +11592,98 @@ void VmaVirtualBlock_T::BuildStatsString(bool detailedMap, VmaStringBuilder& sb)
|
|||||||
#endif // _VMA_VIRTUAL_BLOCK_T_FUNCTIONS
|
#endif // _VMA_VIRTUAL_BLOCK_T_FUNCTIONS
|
||||||
#endif // _VMA_VIRTUAL_BLOCK_T
|
#endif // _VMA_VIRTUAL_BLOCK_T
|
||||||
|
|
||||||
|
#ifndef _VMA_BUFFER_ALLOCATOR_T
|
||||||
|
|
||||||
|
struct VmaBufferAllocation_T;
|
||||||
|
|
||||||
|
struct VmaBufferSuballocation_T
|
||||||
|
{
|
||||||
|
VmaBufferAllocation_T* m_BufferAllocation = nullptr;
|
||||||
|
VmaVirtualAllocation m_VirtualAllocation = VK_NULL_HANDLE;
|
||||||
|
VkDeviceSize m_BufferLocalOffset = 0; // Cached for optimization.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Represents a single buffer managed by VmaBufferAllocator:
|
||||||
|
// VmaAllocation + VkBuffer + VmaVirtualBlock.
|
||||||
|
struct VmaBufferAllocation_T
|
||||||
|
{
|
||||||
|
VMA_CLASS_NO_COPY(VmaBufferAllocation_T);
|
||||||
|
public:
|
||||||
|
VmaBufferAllocation_T(VmaBufferAllocator parentBufferAllocator);
|
||||||
|
VkResult Init(
|
||||||
|
const VkBufferCreateInfo& bufferCreateInfo,
|
||||||
|
const VmaAllocationCreateInfo& allocationCreateInfo,
|
||||||
|
bool linearAlgorithm);
|
||||||
|
~VmaBufferAllocation_T();
|
||||||
|
|
||||||
|
VkResult Allocate(
|
||||||
|
const VmaBufferSuballocationCreateInfo& createInfo,
|
||||||
|
VmaBufferSuballocation_T*& outBufferSuballocation,
|
||||||
|
VmaBufferSuballocationInfo* outBufferSuballocationInfo);
|
||||||
|
void Free(VmaBufferSuballocation_T* bufferSuballocation);
|
||||||
|
|
||||||
|
void GetSuballocationInfo(
|
||||||
|
const VmaBufferSuballocation_T& bufferSuballocation,
|
||||||
|
VmaBufferSuballocationInfo& outBufferSuballocationInfo) const;
|
||||||
|
void SetSuballocationUserData(
|
||||||
|
const VmaBufferSuballocation_T& bufferSuballocation, void* pUserData);
|
||||||
|
VkResult MapSuballocation(
|
||||||
|
const VmaBufferSuballocation_T& bufferSuballocation,
|
||||||
|
void*& outData);
|
||||||
|
void UnmapSuballocation(const VmaBufferSuballocation_T& bufferSuballocation);
|
||||||
|
VkResult FlushOrInvalidateSuballocation(
|
||||||
|
const VmaBufferSuballocation_T& bufferSuballocation,
|
||||||
|
VkDeviceSize suballocLocalOffset, VkDeviceSize size, VMA_CACHE_OPERATION op) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VmaBufferAllocator const m_ParentBufferAllocator;
|
||||||
|
VmaAllocation m_Allocation = VK_NULL_HANDLE;
|
||||||
|
VkBuffer m_Buffer = VK_NULL_HANDLE;
|
||||||
|
VmaVirtualBlock m_VirtualBlock = VK_NULL_HANDLE;
|
||||||
|
// We want to cache mapping of individual suballocations so we don't overflow
|
||||||
|
// the 8-bit VmaAllocation_T::m_MapCount when having many small buffers.
|
||||||
|
uint32_t m_MapCounter = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VmaBufferAllocator_T
|
||||||
|
{
|
||||||
|
VMA_CLASS_NO_COPY(VmaBufferAllocator_T);
|
||||||
|
public:
|
||||||
|
VmaBufferAllocator_T(VmaAllocator allocator, const VmaBufferAllocatorCreateInfo& createInfo);
|
||||||
|
VkResult Init();
|
||||||
|
~VmaBufferAllocator_T();
|
||||||
|
|
||||||
|
VmaAllocator GetAllocator() const { return m_Allocator; }
|
||||||
|
|
||||||
|
VkResult Allocate(
|
||||||
|
const VmaBufferSuballocationCreateInfo& createInfo,
|
||||||
|
VmaBufferSuballocation& outBufferSuballocation,
|
||||||
|
VmaBufferSuballocationInfo* outBufferSuballocationInfo);
|
||||||
|
void Free(VmaBufferSuballocation bufferSuballocation);
|
||||||
|
|
||||||
|
void GetSuballocationInfo(
|
||||||
|
const VmaBufferSuballocation bufferSuballocation,
|
||||||
|
VmaBufferSuballocationInfo& outBufferSuballocationInfo) const;
|
||||||
|
void SetSuballocationUserData(
|
||||||
|
const VmaBufferSuballocation bufferSuballocation, void* pUserData);
|
||||||
|
VkResult MapSuballocation(
|
||||||
|
const VmaBufferSuballocation bufferSuballocation,
|
||||||
|
void*& outData);
|
||||||
|
void UnmapSuballocation(const VmaBufferSuballocation bufferSuballocation);
|
||||||
|
VkResult FlushOrInvalidateSuballocations(
|
||||||
|
uint32_t count, const VmaBufferSuballocation* bufferSuballocations,
|
||||||
|
const VkDeviceSize* offsets, const VkDeviceSize* sizes, VMA_CACHE_OPERATION op) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VmaAllocator m_Allocator = VK_NULL_HANDLE;
|
||||||
|
VmaBufferAllocatorCreateInfo m_CreateInfo = {};
|
||||||
|
typedef VmaVector<VmaBufferAllocation_T*, VmaStlAllocator<VmaBufferAllocation_T*>> BufferAllocationVectorType;
|
||||||
|
BufferAllocationVectorType m_BufferAllocations;
|
||||||
|
|
||||||
|
VkResult CreateBufferAllocation(VkDeviceSize size);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _VMA_BUFFER_ALLOCATOR_T
|
||||||
|
|
||||||
// Main allocator object.
|
// Main allocator object.
|
||||||
struct VmaAllocator_T
|
struct VmaAllocator_T
|
||||||
@ -16247,6 +16340,327 @@ void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
|
|||||||
#endif // VMA_STATS_STRING_ENABLED
|
#endif // VMA_STATS_STRING_ENABLED
|
||||||
#endif // _VMA_ALLOCATOR_T_FUNCTIONS
|
#endif // _VMA_ALLOCATOR_T_FUNCTIONS
|
||||||
|
|
||||||
|
#ifndef _VMA_BUFFER_ALLOCATOR_T_FUNCTIONS
|
||||||
|
|
||||||
|
VmaBufferAllocation_T::VmaBufferAllocation_T(VmaBufferAllocator parentBufferAllocator) :
|
||||||
|
m_ParentBufferAllocator(parentBufferAllocator)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult VmaBufferAllocation_T::Init(
|
||||||
|
const VkBufferCreateInfo& bufferCreateInfo,
|
||||||
|
const VmaAllocationCreateInfo& allocationCreateInfo,
|
||||||
|
bool linearAlgorithm)
|
||||||
|
{
|
||||||
|
VmaAllocator const allocator = m_ParentBufferAllocator->GetAllocator();
|
||||||
|
|
||||||
|
// Create VkBuffer and VmaAllocation.
|
||||||
|
VmaAllocationInfo allocInfo = {};
|
||||||
|
VkResult res = vmaCreateBuffer(allocator, &bufferCreateInfo, &allocationCreateInfo,
|
||||||
|
&m_Buffer, &m_Allocation, &allocInfo);
|
||||||
|
if(res == VK_SUCCESS)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(m_Buffer != VK_NULL_HANDLE && m_Allocation != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
// Create VmaVirtualBlock.
|
||||||
|
VmaVirtualBlockCreateInfo virtualBlockCreateInfo = {};
|
||||||
|
virtualBlockCreateInfo.size = bufferCreateInfo.size;
|
||||||
|
virtualBlockCreateInfo.flags = linearAlgorithm ? VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT : 0;
|
||||||
|
virtualBlockCreateInfo.pAllocationCallbacks = allocator->GetAllocationCallbacks();
|
||||||
|
res = vmaCreateVirtualBlock(&virtualBlockCreateInfo, &m_VirtualBlock);
|
||||||
|
if(res == VK_SUCCESS)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(m_VirtualBlock != VK_NULL_HANDLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
VmaBufferAllocation_T::~VmaBufferAllocation_T()
|
||||||
|
{
|
||||||
|
vmaDestroyVirtualBlock(m_VirtualBlock);
|
||||||
|
vmaDestroyBuffer(m_ParentBufferAllocator->GetAllocator(), m_Buffer, m_Allocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult VmaBufferAllocation_T::Allocate(
|
||||||
|
const VmaBufferSuballocationCreateInfo& createInfo,
|
||||||
|
VmaBufferSuballocation_T*& outBufferSuballocation,
|
||||||
|
VmaBufferSuballocationInfo* outBufferSuballocationInfo)
|
||||||
|
{
|
||||||
|
VmaVirtualAllocationCreateInfo virtualAllocCreateInfo = {};
|
||||||
|
virtualAllocCreateInfo.size = createInfo.size; // TODO check size if it fits, early return if not.
|
||||||
|
virtualAllocCreateInfo.alignment = createInfo.alignment;
|
||||||
|
virtualAllocCreateInfo.pUserData = createInfo.pUserData;
|
||||||
|
if(createInfo.flags & VMA_BUFFER_SUBALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT)
|
||||||
|
virtualAllocCreateInfo.flags |= VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT;
|
||||||
|
if(createInfo.flags & VMA_BUFFER_SUBALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT)
|
||||||
|
virtualAllocCreateInfo.flags |= VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT;
|
||||||
|
if(createInfo.flags & VMA_BUFFER_SUBALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT)
|
||||||
|
virtualAllocCreateInfo.flags |= VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT;
|
||||||
|
|
||||||
|
VmaAllocationInfo allocInfo = {};
|
||||||
|
vmaGetAllocationInfo(m_ParentBufferAllocator->GetAllocator(), m_Allocation, &allocInfo);
|
||||||
|
|
||||||
|
// Create VmaVirtualAllocation.
|
||||||
|
VmaVirtualAllocation virtualAlloc = VK_NULL_HANDLE;
|
||||||
|
VkDeviceSize bufferLocalOffset = 0;
|
||||||
|
VkResult res = vmaVirtualAllocate(m_VirtualBlock, &virtualAllocCreateInfo,
|
||||||
|
&virtualAlloc, &bufferLocalOffset);
|
||||||
|
if(res == VK_SUCCESS)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(virtualAlloc != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
// Create VmaBufferSuballocation structure.
|
||||||
|
outBufferSuballocation = vma_new(
|
||||||
|
m_ParentBufferAllocator->GetAllocator()->GetAllocationCallbacks(), VmaBufferSuballocation_T);
|
||||||
|
outBufferSuballocation->m_BufferAllocation = this;
|
||||||
|
outBufferSuballocation->m_VirtualAllocation = virtualAlloc;
|
||||||
|
outBufferSuballocation->m_BufferLocalOffset = bufferLocalOffset;
|
||||||
|
|
||||||
|
// Fetch VmaBufferSuballocationInfo.
|
||||||
|
if(outBufferSuballocationInfo)
|
||||||
|
{
|
||||||
|
outBufferSuballocationInfo->allocation = m_Allocation;
|
||||||
|
outBufferSuballocationInfo->buffer = m_Buffer;
|
||||||
|
outBufferSuballocationInfo->bufferLocalOffset = bufferLocalOffset;
|
||||||
|
outBufferSuballocationInfo->size = createInfo.size;
|
||||||
|
outBufferSuballocationInfo->pMappedData = allocInfo.pMappedData ?
|
||||||
|
(void*)((char*)allocInfo.pMappedData + bufferLocalOffset) : nullptr;
|
||||||
|
outBufferSuballocationInfo->pUserData = createInfo.pUserData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VmaBufferAllocation_T::Free(VmaBufferSuballocation_T* bufferSuballocation)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(bufferSuballocation->m_BufferAllocation == this);
|
||||||
|
|
||||||
|
vmaVirtualFree(m_VirtualBlock, bufferSuballocation->m_VirtualAllocation);
|
||||||
|
vma_delete(m_ParentBufferAllocator->GetAllocator()->GetAllocationCallbacks(), bufferSuballocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VmaBufferAllocation_T::GetSuballocationInfo(
|
||||||
|
const VmaBufferSuballocation_T& bufferSuballocation,
|
||||||
|
VmaBufferSuballocationInfo& outBufferSuballocationInfo) const
|
||||||
|
{
|
||||||
|
VMA_ASSERT(bufferSuballocation.m_BufferAllocation == this);
|
||||||
|
|
||||||
|
VmaAllocationInfo allocInfo = {};
|
||||||
|
vmaGetAllocationInfo(m_ParentBufferAllocator->GetAllocator(), m_Allocation, &allocInfo);
|
||||||
|
|
||||||
|
VmaVirtualAllocationInfo virtualAllocInfo = {};
|
||||||
|
vmaGetVirtualAllocationInfo(m_VirtualBlock, bufferSuballocation.m_VirtualAllocation, &virtualAllocInfo);
|
||||||
|
|
||||||
|
outBufferSuballocationInfo.allocation = m_Allocation;
|
||||||
|
outBufferSuballocationInfo.buffer = m_Buffer;
|
||||||
|
outBufferSuballocationInfo.bufferLocalOffset = virtualAllocInfo.offset;
|
||||||
|
outBufferSuballocationInfo.size = virtualAllocInfo.size;
|
||||||
|
outBufferSuballocationInfo.pMappedData = allocInfo.pMappedData ?
|
||||||
|
(void*)((char*)allocInfo.pMappedData + virtualAllocInfo.offset) : nullptr;
|
||||||
|
outBufferSuballocationInfo.pUserData = virtualAllocInfo.pUserData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VmaBufferAllocation_T::SetSuballocationUserData(
|
||||||
|
const VmaBufferSuballocation_T& bufferSuballocation, void* pUserData)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(bufferSuballocation.m_BufferAllocation == this);
|
||||||
|
|
||||||
|
vmaSetVirtualAllocationUserData(m_VirtualBlock, bufferSuballocation.m_VirtualAllocation,
|
||||||
|
pUserData);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult VmaBufferAllocation_T::MapSuballocation(
|
||||||
|
const VmaBufferSuballocation_T& bufferSuballocation,
|
||||||
|
void*& outData)
|
||||||
|
{
|
||||||
|
void* allocMappedPtr = nullptr;
|
||||||
|
if(m_MapCounter == 0)
|
||||||
|
{
|
||||||
|
VkResult res = vmaMapMemory(m_ParentBufferAllocator->GetAllocator(), m_Allocation, &allocMappedPtr);
|
||||||
|
if(res == VK_SUCCESS)
|
||||||
|
{
|
||||||
|
outData = (void*)((char*)allocMappedPtr + bufferSuballocation.m_BufferLocalOffset);
|
||||||
|
m_MapCounter = 1;
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VmaAllocationInfo allocInfo = {};
|
||||||
|
vmaGetAllocationInfo(m_ParentBufferAllocator->GetAllocator(), m_Allocation, &allocInfo);
|
||||||
|
VMA_ASSERT(allocInfo.pMappedData);
|
||||||
|
outData = (void*)((char*)allocInfo.pMappedData + bufferSuballocation.m_BufferLocalOffset);
|
||||||
|
++m_MapCounter;
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VmaBufferAllocation_T::UnmapSuballocation(const VmaBufferSuballocation_T& bufferSuballocation)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(m_MapCounter > 0);
|
||||||
|
if(m_MapCounter == 1)
|
||||||
|
{
|
||||||
|
vmaUnmapMemory(m_ParentBufferAllocator->GetAllocator(), m_Allocation);
|
||||||
|
m_MapCounter = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
--m_MapCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult VmaBufferAllocation_T::FlushOrInvalidateSuballocation(
|
||||||
|
const VmaBufferSuballocation_T& bufferSuballocation,
|
||||||
|
VkDeviceSize suballocLocalOffset, VkDeviceSize size, VMA_CACHE_OPERATION op) const
|
||||||
|
{
|
||||||
|
VMA_ASSERT(bufferSuballocation.m_BufferAllocation == this);
|
||||||
|
|
||||||
|
// VkBuffer-local offset is the same thing as VmaAllocation-local offset.
|
||||||
|
const VkDeviceSize allocOffset = bufferSuballocation.m_BufferLocalOffset + suballocLocalOffset;
|
||||||
|
|
||||||
|
if(op == VMA_CACHE_FLUSH)
|
||||||
|
return vmaFlushAllocation(m_ParentBufferAllocator->GetAllocator(), m_Allocation, allocOffset, size);
|
||||||
|
else
|
||||||
|
return vmaInvalidateAllocation(m_ParentBufferAllocator->GetAllocator(), m_Allocation, allocOffset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
VmaBufferAllocator_T::VmaBufferAllocator_T(VmaAllocator allocator, const VmaBufferAllocatorCreateInfo& createInfo) :
|
||||||
|
m_Allocator(allocator),
|
||||||
|
m_CreateInfo(createInfo),
|
||||||
|
m_BufferAllocations(VmaStlAllocator<VmaBufferAllocation_T*>(allocator->GetAllocationCallbacks()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult VmaBufferAllocator_T::Init()
|
||||||
|
{
|
||||||
|
// TODO create minBufferCount
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VmaBufferAllocator_T::~VmaBufferAllocator_T()
|
||||||
|
{
|
||||||
|
const VkAllocationCallbacks* const allocationCallbacks = m_Allocator->GetAllocationCallbacks();
|
||||||
|
|
||||||
|
for(size_t i = m_BufferAllocations.size(); i--; )
|
||||||
|
vma_delete(allocationCallbacks, m_BufferAllocations[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult VmaBufferAllocator_T::Allocate(
|
||||||
|
const VmaBufferSuballocationCreateInfo& createInfo,
|
||||||
|
VmaBufferSuballocation& outBufferSuballocation,
|
||||||
|
VmaBufferSuballocationInfo* outBufferSuballocationInfo)
|
||||||
|
{
|
||||||
|
// TODO find existing BufferAllocation to allocate if possible.
|
||||||
|
// TODO respect VMA_BUFFER_SUBALLOCATION_CREATE_DEDICATED_BUFFER_BIT
|
||||||
|
// TODO respect VMA_BUFFER_SUBALLOCATION_CREATE_NEVER_CREATE_BUFFER_BIT and VMA_BUFFER_SUBALLOCATION_CREATE_NEVER_ALLOCATE_BIT.
|
||||||
|
// TODO respect VMA_BUFFER_SUBALLOCATION_CREATE_WITHIN_BUDGET_BIT.
|
||||||
|
// TODO manage BufferAllocation sizes
|
||||||
|
|
||||||
|
VkResult res = CreateBufferAllocation(createInfo.size);
|
||||||
|
if(res == VK_SUCCESS)
|
||||||
|
{
|
||||||
|
VmaBufferSuballocation_T* suballocStruct = nullptr;
|
||||||
|
res = m_BufferAllocations.back()->Allocate(createInfo, suballocStruct, outBufferSuballocationInfo);
|
||||||
|
outBufferSuballocation = (VmaBufferSuballocation)suballocStruct;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VmaBufferAllocator_T::Free(VmaBufferSuballocation bufferSuballocation)
|
||||||
|
{
|
||||||
|
VmaBufferSuballocation_T* const suballocStruct = (VmaBufferSuballocation_T*)bufferSuballocation;
|
||||||
|
|
||||||
|
// Find BufferAllocation. TODO any faster than linear search to use?
|
||||||
|
for(size_t i = 0, count = m_BufferAllocations.size(); i < count; ++i)
|
||||||
|
{
|
||||||
|
VmaBufferAllocation_T* bufferAllocation = m_BufferAllocations[i];
|
||||||
|
if(suballocStruct->m_BufferAllocation == bufferAllocation)
|
||||||
|
{
|
||||||
|
bufferAllocation->Free(suballocStruct);
|
||||||
|
vma_delete(m_Allocator->GetAllocationCallbacks(), bufferAllocation);
|
||||||
|
m_BufferAllocations.remove(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VMA_ASSERT(0 && "BufferSuballocation doesn't belong to this BufferAllocator!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void VmaBufferAllocator_T::GetSuballocationInfo(
|
||||||
|
const VmaBufferSuballocation bufferSuballocation,
|
||||||
|
VmaBufferSuballocationInfo& outBufferSuballocationInfo) const
|
||||||
|
{
|
||||||
|
VmaBufferSuballocation_T* const suballocStruct = (VmaBufferSuballocation_T*)bufferSuballocation;
|
||||||
|
VMA_ASSERT(suballocStruct->m_BufferAllocation);
|
||||||
|
suballocStruct->m_BufferAllocation->GetSuballocationInfo(
|
||||||
|
*suballocStruct, outBufferSuballocationInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VmaBufferAllocator_T::SetSuballocationUserData(
|
||||||
|
const VmaBufferSuballocation bufferSuballocation, void* pUserData)
|
||||||
|
{
|
||||||
|
VmaBufferSuballocation_T* const suballocStruct = (VmaBufferSuballocation_T*)bufferSuballocation;
|
||||||
|
VMA_ASSERT(suballocStruct->m_BufferAllocation);
|
||||||
|
suballocStruct->m_BufferAllocation->SetSuballocationUserData(
|
||||||
|
*suballocStruct, pUserData);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult VmaBufferAllocator_T::MapSuballocation(
|
||||||
|
const VmaBufferSuballocation bufferSuballocation,
|
||||||
|
void*& outData)
|
||||||
|
{
|
||||||
|
VmaBufferSuballocation_T* const suballocStruct = (VmaBufferSuballocation_T*)bufferSuballocation;
|
||||||
|
VMA_ASSERT(suballocStruct->m_BufferAllocation);
|
||||||
|
return suballocStruct->m_BufferAllocation->MapSuballocation(*suballocStruct, outData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VmaBufferAllocator_T::UnmapSuballocation(const VmaBufferSuballocation bufferSuballocation)
|
||||||
|
{
|
||||||
|
VmaBufferSuballocation_T* const suballocStruct = (VmaBufferSuballocation_T*)bufferSuballocation;
|
||||||
|
VMA_ASSERT(suballocStruct->m_BufferAllocation);
|
||||||
|
suballocStruct->m_BufferAllocation->UnmapSuballocation(*suballocStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult VmaBufferAllocator_T::FlushOrInvalidateSuballocations(
|
||||||
|
uint32_t count, const VmaBufferSuballocation* bufferSuballocations,
|
||||||
|
const VkDeviceSize* offsets, const VkDeviceSize* sizes, VMA_CACHE_OPERATION op) const
|
||||||
|
{
|
||||||
|
VkResult res = VK_SUCCESS;
|
||||||
|
for(uint32_t i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
const VmaBufferSuballocation_T* const suballocStruct = (const VmaBufferSuballocation_T*)bufferSuballocations[i];
|
||||||
|
VMA_ASSERT(suballocStruct->m_BufferAllocation);
|
||||||
|
const VkResult localRes = suballocStruct->m_BufferAllocation->FlushOrInvalidateSuballocation(
|
||||||
|
*suballocStruct, offsets[i], sizes[i], op);
|
||||||
|
if(res == VK_SUCCESS)
|
||||||
|
res = localRes;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult VmaBufferAllocator_T::CreateBufferAllocation(VkDeviceSize size)
|
||||||
|
{
|
||||||
|
const VkAllocationCallbacks* const allocationCallbacks = m_Allocator->GetAllocationCallbacks();
|
||||||
|
|
||||||
|
VmaBufferAllocation_T* bufferAllocation = vma_new(allocationCallbacks, VmaBufferAllocation_T)(this);
|
||||||
|
VkBufferCreateInfo bufCreateInfo = m_CreateInfo.bufferCreateInfo;
|
||||||
|
bufCreateInfo.size = size;
|
||||||
|
VkResult res = bufferAllocation->Init(
|
||||||
|
bufCreateInfo,
|
||||||
|
m_CreateInfo.allocationCreateInfo,
|
||||||
|
(m_CreateInfo.flags & VMA_BUFFER_ALLOCATOR_CREATE_LINEAR_ALGORITHM_BIT) != 0);
|
||||||
|
if(res == VK_SUCCESS)
|
||||||
|
{
|
||||||
|
m_BufferAllocations.push_back(bufferAllocation); // TODO where to insert?
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vma_delete(allocationCallbacks, bufferAllocation);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _VMA_BUFFER_ALLOCATOR_T_FUNCTIONS
|
||||||
|
|
||||||
#ifndef _VMA_PUBLIC_INTERFACE
|
#ifndef _VMA_PUBLIC_INTERFACE
|
||||||
VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(
|
VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(
|
||||||
@ -17805,6 +18219,208 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(VmaVirtualBlock V
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // VMA_STATS_STRING_ENABLED
|
#endif // VMA_STATS_STRING_ENABLED
|
||||||
|
|
||||||
|
VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferAllocator(
|
||||||
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
const VmaBufferAllocatorCreateInfo* VMA_NOT_NULL pCreateInfo,
|
||||||
|
VmaBufferAllocator VMA_NULLABLE* VMA_NOT_NULL pBufferAllocator)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(allocator != VK_NULL_HANDLE && pCreateInfo);
|
||||||
|
VMA_ASSERT(pCreateInfo->bufferCreateInfo.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
|
||||||
|
VMA_ASSERT(pCreateInfo->maxBufferCount >= pCreateInfo->minBufferCount);
|
||||||
|
VMA_ASSERT(VmaIsPow2(pCreateInfo->minSuballocationAlignment));
|
||||||
|
|
||||||
|
VMA_DEBUG_LOG("vmaCreateBufferAllocator");
|
||||||
|
//VMA_DEBUG_GLOBAL_MUTEX_LOCK; // Not using, as this is a higher-level API that uses public VMA functions with this lock under the hood.
|
||||||
|
|
||||||
|
*pBufferAllocator = vma_new(allocator->GetAllocationCallbacks(), VmaBufferAllocator_T)(allocator, *pCreateInfo);
|
||||||
|
VkResult res = (*pBufferAllocator)->Init();
|
||||||
|
if(res < 0)
|
||||||
|
{
|
||||||
|
vma_delete(allocator->GetAllocationCallbacks(), *pBufferAllocator);
|
||||||
|
*pBufferAllocator = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBufferAllocator(
|
||||||
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
VmaBufferAllocator VMA_NULLABLE bufferAllocator)
|
||||||
|
{
|
||||||
|
if(bufferAllocator != VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
VMA_DEBUG_LOG("vmaDestroyBufferAllocator");
|
||||||
|
//VMA_DEBUG_GLOBAL_MUTEX_LOCK; // Not using, as this is a higher-level API that uses public VMA functions with this lock under the hood.
|
||||||
|
vma_delete(allocator->GetAllocationCallbacks(), bufferAllocator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VMA_CALL_PRE VkResult VMA_CALL_POST vmaBufferAllocatorAllocate(
|
||||||
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
VmaBufferAllocator VMA_NULLABLE bufferAllocator,
|
||||||
|
const VmaBufferSuballocationCreateInfo* VMA_NOT_NULL pCreateInfo,
|
||||||
|
VmaBufferSuballocation VMA_NULLABLE* VMA_NOT_NULL pBufferSuballocation,
|
||||||
|
VmaBufferSuballocationInfo* VMA_NULLABLE pBufferSuballocationInfo)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(allocator != VK_NULL_HANDLE && bufferAllocator != VK_NULL_HANDLE &&
|
||||||
|
pCreateInfo && pBufferSuballocation);
|
||||||
|
VMA_ASSERT(pCreateInfo->size > 0 && VmaIsPow2(pCreateInfo->alignment));
|
||||||
|
|
||||||
|
VMA_DEBUG_LOG("vmaBufferAllocatorAllocate");
|
||||||
|
//VMA_DEBUG_GLOBAL_MUTEX_LOCK; // Not using, as this is a higher-level API that uses public VMA functions with this lock under the hood.
|
||||||
|
|
||||||
|
return bufferAllocator->Allocate(*pCreateInfo, *pBufferSuballocation, pBufferSuballocationInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
VMA_CALL_PRE void VMA_CALL_POST vmaBufferAllocatorFree(
|
||||||
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
||||||
|
VmaBufferSuballocation VMA_NULLABLE bufferSuballocation)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(allocator != VK_NULL_HANDLE && bufferAllocator != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
VMA_DEBUG_LOG("vmaBufferAllocatorFree");
|
||||||
|
//VMA_DEBUG_GLOBAL_MUTEX_LOCK; // Not using, as this is a higher-level API that uses public VMA functions with this lock under the hood.
|
||||||
|
|
||||||
|
if(bufferSuballocation != VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
bufferAllocator->Free(bufferSuballocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VMA_CALL_PRE void VMA_CALL_POST vmaGetBufferSuballocationInfo(
|
||||||
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
||||||
|
VmaBufferSuballocation VMA_NOT_NULL bufferSuballocation,
|
||||||
|
VmaBufferSuballocationInfo* VMA_NOT_NULL pBufferSuballocationInfo)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(allocator != VK_NULL_HANDLE && bufferAllocator != VK_NULL_HANDLE &&
|
||||||
|
bufferSuballocation != VK_NULL_HANDLE && pBufferSuballocationInfo);
|
||||||
|
|
||||||
|
VMA_DEBUG_LOG("vmaGetBufferSuballocationInfo");
|
||||||
|
//VMA_DEBUG_GLOBAL_MUTEX_LOCK; // Not using, as this is a higher-level API that uses public VMA functions with this lock under the hood.
|
||||||
|
|
||||||
|
bufferAllocator->GetSuballocationInfo(bufferSuballocation, *pBufferSuballocationInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
VMA_CALL_PRE void VMA_CALL_POST vmaSetBufferSuballocationUserData(
|
||||||
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
||||||
|
VmaBufferSuballocation VMA_NOT_NULL bufferSuballocation,
|
||||||
|
void* VMA_NULLABLE pUserData)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(allocator != VK_NULL_HANDLE && bufferAllocator != VK_NULL_HANDLE &&
|
||||||
|
bufferSuballocation != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
VMA_DEBUG_LOG("vmaSetBufferSuballocationUserData");
|
||||||
|
//VMA_DEBUG_GLOBAL_MUTEX_LOCK; // Not using, as this is a higher-level API that uses public VMA functions with this lock under the hood.
|
||||||
|
|
||||||
|
bufferAllocator->SetSuballocationUserData(bufferSuballocation, pUserData);
|
||||||
|
}
|
||||||
|
|
||||||
|
VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapBufferSuballocation(
|
||||||
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
||||||
|
VmaBufferSuballocation VMA_NOT_NULL bufferSuballocation,
|
||||||
|
void* VMA_NULLABLE* VMA_NOT_NULL ppData)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(allocator != VK_NULL_HANDLE && bufferAllocator != VK_NULL_HANDLE &&
|
||||||
|
bufferSuballocation != VK_NULL_HANDLE && ppData);
|
||||||
|
|
||||||
|
VMA_DEBUG_LOG("vmaMapBufferSuballocation");
|
||||||
|
//VMA_DEBUG_GLOBAL_MUTEX_LOCK; // Not using, as this is a higher-level API that uses public VMA functions with this lock under the hood.
|
||||||
|
|
||||||
|
return bufferAllocator->MapSuballocation(bufferSuballocation, *ppData);
|
||||||
|
}
|
||||||
|
|
||||||
|
VMA_CALL_PRE void VMA_CALL_POST vmaUnmapBufferSuballocation(
|
||||||
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
||||||
|
VmaBufferSuballocation VMA_NOT_NULL bufferSuballocation)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(allocator != VK_NULL_HANDLE && bufferAllocator != VK_NULL_HANDLE &&
|
||||||
|
bufferSuballocation != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
VMA_DEBUG_LOG("vmaMapBufferSuballocation");
|
||||||
|
//VMA_DEBUG_GLOBAL_MUTEX_LOCK; // Not using, as this is a higher-level API that uses public VMA functions with this lock under the hood.
|
||||||
|
|
||||||
|
bufferAllocator->UnmapSuballocation(bufferSuballocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushBufferSuballocation(
|
||||||
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
||||||
|
VmaBufferSuballocation VMA_NOT_NULL bufferSuballocation,
|
||||||
|
VkDeviceSize offset,
|
||||||
|
VkDeviceSize size)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(allocator != VK_NULL_HANDLE && bufferAllocator != VK_NULL_HANDLE &&
|
||||||
|
bufferSuballocation != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
VMA_DEBUG_LOG("vmaFlushBufferSuballocation");
|
||||||
|
//VMA_DEBUG_GLOBAL_MUTEX_LOCK; // Not using, as this is a higher-level API that uses public VMA functions with this lock under the hood.
|
||||||
|
|
||||||
|
return bufferAllocator->FlushOrInvalidateSuballocations(1, &bufferSuballocation, &offset, &size, VMA_CACHE_FLUSH);
|
||||||
|
}
|
||||||
|
|
||||||
|
VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateBufferSuballocation(
|
||||||
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
||||||
|
VmaBufferSuballocation VMA_NOT_NULL bufferSuballocation,
|
||||||
|
VkDeviceSize offset,
|
||||||
|
VkDeviceSize size)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(allocator != VK_NULL_HANDLE && bufferAllocator != VK_NULL_HANDLE &&
|
||||||
|
bufferSuballocation != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
VMA_DEBUG_LOG("vmaInvalidateBufferSuballocation");
|
||||||
|
//VMA_DEBUG_GLOBAL_MUTEX_LOCK; // Not using, as this is a higher-level API that uses public VMA functions with this lock under the hood.
|
||||||
|
|
||||||
|
return bufferAllocator->FlushOrInvalidateSuballocations(1, &bufferSuballocation, &offset, &size, VMA_CACHE_INVALIDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushBufferSuballocations(
|
||||||
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
||||||
|
uint32_t bufferSuballocationCount,
|
||||||
|
const VmaBufferSuballocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pBufferSuballocations,
|
||||||
|
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pOffsets,
|
||||||
|
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pSizes)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(allocator != VK_NULL_HANDLE && bufferAllocator != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
VMA_DEBUG_LOG("vmaFlushBufferSuballocations");
|
||||||
|
//VMA_DEBUG_GLOBAL_MUTEX_LOCK; // Not using, as this is a higher-level API that uses public VMA functions with this lock under the hood.
|
||||||
|
|
||||||
|
if(bufferSuballocationCount > 0)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(pBufferSuballocations && pOffsets && pSizes);
|
||||||
|
return bufferAllocator->FlushOrInvalidateSuballocations(bufferSuballocationCount, pBufferSuballocations, pOffsets, pSizes, VMA_CACHE_FLUSH);
|
||||||
|
}
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateBufferSuballocations(
|
||||||
|
VmaAllocator VMA_NOT_NULL allocator,
|
||||||
|
VmaBufferAllocator VMA_NOT_NULL bufferAllocator,
|
||||||
|
uint32_t bufferSuballocationCount,
|
||||||
|
const VmaBufferSuballocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pBufferSuballocations,
|
||||||
|
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pOffsets,
|
||||||
|
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(bufferSuballocationCount) pSizes)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(allocator != VK_NULL_HANDLE && bufferAllocator != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
VMA_DEBUG_LOG("vmaInvalidateBufferSuballocations");
|
||||||
|
//VMA_DEBUG_GLOBAL_MUTEX_LOCK; // Not using, as this is a higher-level API that uses public VMA functions with this lock under the hood.
|
||||||
|
|
||||||
|
if(bufferSuballocationCount > 0)
|
||||||
|
{
|
||||||
|
VMA_ASSERT(pBufferSuballocations && pOffsets && pSizes);
|
||||||
|
return bufferAllocator->FlushOrInvalidateSuballocations(bufferSuballocationCount, pBufferSuballocations, pOffsets, pSizes, VMA_CACHE_INVALIDATE);
|
||||||
|
}
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // _VMA_PUBLIC_INTERFACE
|
#endif // _VMA_PUBLIC_INTERFACE
|
||||||
#endif // VMA_IMPLEMENTATION
|
#endif // VMA_IMPLEMENTATION
|
||||||
|
|
||||||
|
101
src/Tests.cpp
101
src/Tests.cpp
@ -7676,6 +7676,102 @@ static void BasicTestAllocatePages()
|
|||||||
vmaDestroyPool(g_hAllocator, pool);
|
vmaDestroyPool(g_hAllocator, pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void TestBufferAllocator()
|
||||||
|
{
|
||||||
|
wprintf(L"Test buffer allocator\n");
|
||||||
|
VkResult res;
|
||||||
|
RandomNumberGenerator rand{1242134};
|
||||||
|
|
||||||
|
VmaBufferAllocatorCreateInfo allocatorCreateInfo = {};
|
||||||
|
allocatorCreateInfo.bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
allocatorCreateInfo.bufferCreateInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||||
|
allocatorCreateInfo.bufferCreateInfo.size = 8ull * 1024 * 1024; // TODO also test 0 - auto size.
|
||||||
|
allocatorCreateInfo.allocationCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
||||||
|
allocatorCreateInfo.allocationCreateInfo.flags =
|
||||||
|
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
||||||
|
VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||||
|
|
||||||
|
// Create BufferAllocator.
|
||||||
|
VmaBufferAllocator bufferAllocator = VK_NULL_HANDLE;
|
||||||
|
res = vmaCreateBufferAllocator(g_hAllocator, &allocatorCreateInfo, &bufferAllocator);
|
||||||
|
TEST(res == VK_SUCCESS && bufferAllocator);
|
||||||
|
|
||||||
|
std::vector<VmaBufferSuballocation> suballocs;
|
||||||
|
for(size_t i = 0; i < 10; ++i)
|
||||||
|
{
|
||||||
|
// Create test BufferSuballocation.
|
||||||
|
void* const userData = (void*)(uintptr_t)245342345;
|
||||||
|
constexpr VkDeviceSize suballocSize = 1024;
|
||||||
|
VmaBufferSuballocationCreateInfo suballocCreateInfo = {};
|
||||||
|
suballocCreateInfo.size = suballocSize;
|
||||||
|
suballocCreateInfo.pUserData = userData;
|
||||||
|
VmaBufferSuballocation suballoc = VK_NULL_HANDLE;
|
||||||
|
VmaBufferSuballocationInfo suballocInfo = {};
|
||||||
|
// TODO test also with last parameter = null.
|
||||||
|
res = vmaBufferAllocatorAllocate(g_hAllocator, bufferAllocator, &suballocCreateInfo, &suballoc, &suballocInfo);
|
||||||
|
TEST(res == VK_SUCCESS && suballoc != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
TEST(suballocInfo.allocation != VK_NULL_HANDLE);
|
||||||
|
TEST(suballocInfo.buffer != VK_NULL_HANDLE);
|
||||||
|
TEST(suballocInfo.bufferLocalOffset == 0);
|
||||||
|
TEST(suballocInfo.pUserData = userData);
|
||||||
|
TEST(suballocInfo.size == suballocSize);
|
||||||
|
|
||||||
|
// Testing mapped ptr
|
||||||
|
VmaAllocationInfo allocInfo = {};
|
||||||
|
vmaGetAllocationInfo(g_hAllocator, suballocInfo.allocation, &allocInfo);
|
||||||
|
TEST(suballocInfo.pMappedData != nullptr);
|
||||||
|
TEST(suballocInfo.pMappedData == (char*)allocInfo.pMappedData + suballocInfo.bufferLocalOffset);
|
||||||
|
|
||||||
|
// Test vmaGetBufferSuballocationInfo.
|
||||||
|
VmaBufferSuballocationInfo suballocInfo2 = {};
|
||||||
|
vmaGetBufferSuballocationInfo(g_hAllocator, bufferAllocator, suballoc, &suballocInfo2);
|
||||||
|
TEST(suballocInfo2.allocation == suballocInfo.allocation &&
|
||||||
|
suballocInfo2.buffer == suballocInfo.buffer &&
|
||||||
|
suballocInfo2.bufferLocalOffset == suballocInfo.bufferLocalOffset &&
|
||||||
|
suballocInfo2.size == suballocInfo.size &&
|
||||||
|
suballocInfo2.pMappedData == suballocInfo.pMappedData &&
|
||||||
|
suballocInfo2.pUserData == suballocInfo.pUserData);
|
||||||
|
|
||||||
|
// Test changing pUserData.
|
||||||
|
void* const userData2 = (void*)(uintptr_t)57632234;
|
||||||
|
vmaSetBufferSuballocationUserData(g_hAllocator, bufferAllocator, suballoc, userData2);
|
||||||
|
vmaGetBufferSuballocationInfo(g_hAllocator, bufferAllocator, suballoc, &suballocInfo2);
|
||||||
|
TEST(suballocInfo2.pUserData == userData2);
|
||||||
|
|
||||||
|
// Random calls to flush/invalidate just to test they don't crash.
|
||||||
|
vmaFlushBufferSuballocation(g_hAllocator, bufferAllocator, suballoc, 0, suballocSize);
|
||||||
|
vmaInvalidateBufferSuballocation(g_hAllocator, bufferAllocator, suballoc, 0, suballocSize);
|
||||||
|
const VkDeviceSize zero = 0;
|
||||||
|
vmaFlushBufferSuballocations(g_hAllocator, bufferAllocator, 1, &suballoc, &zero, &suballocSize);
|
||||||
|
vmaInvalidateBufferSuballocations(g_hAllocator, bufferAllocator, 1, &suballoc, &zero, &suballocSize);
|
||||||
|
|
||||||
|
// Testing map/unmap, on the already mapped suballocation.
|
||||||
|
void* mappedPtr;
|
||||||
|
res = vmaMapBufferSuballocation(g_hAllocator, bufferAllocator, suballoc, &mappedPtr);
|
||||||
|
TEST(res == VK_SUCCESS);
|
||||||
|
TEST(mappedPtr == suballocInfo.pMappedData);
|
||||||
|
res = vmaMapBufferSuballocation(g_hAllocator, bufferAllocator, suballoc, &mappedPtr);
|
||||||
|
TEST(res == VK_SUCCESS);
|
||||||
|
TEST(mappedPtr == suballocInfo.pMappedData);
|
||||||
|
vmaUnmapBufferSuballocation(g_hAllocator, bufferAllocator, suballoc);
|
||||||
|
vmaUnmapBufferSuballocation(g_hAllocator, bufferAllocator, suballoc);
|
||||||
|
|
||||||
|
suballocs.push_back(suballoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the BufferSuballocations, in random order.
|
||||||
|
while(!suballocs.empty())
|
||||||
|
{
|
||||||
|
const size_t indexToFree = rand.Generate() % suballocs.size();
|
||||||
|
vmaBufferAllocatorFree(g_hAllocator, bufferAllocator, suballocs[indexToFree]);
|
||||||
|
suballocs.erase(suballocs.begin() + indexToFree);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy BufferAllocator.
|
||||||
|
vmaDestroyBufferAllocator(g_hAllocator, bufferAllocator);
|
||||||
|
}
|
||||||
|
|
||||||
// Test the testing environment.
|
// Test the testing environment.
|
||||||
static void TestGpuData()
|
static void TestGpuData()
|
||||||
{
|
{
|
||||||
@ -7978,8 +8074,10 @@ void Test()
|
|||||||
{
|
{
|
||||||
wprintf(L"TESTING:\n");
|
wprintf(L"TESTING:\n");
|
||||||
|
|
||||||
if(false)
|
if(true)
|
||||||
{
|
{
|
||||||
|
TestBufferAllocator();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Temporarily insert custom tests here:
|
// Temporarily insert custom tests here:
|
||||||
return;
|
return;
|
||||||
@ -8022,6 +8120,7 @@ void Test()
|
|||||||
|
|
||||||
BasicTestTLSF();
|
BasicTestTLSF();
|
||||||
BasicTestAllocatePages();
|
BasicTestAllocatePages();
|
||||||
|
TestBufferAllocator();
|
||||||
|
|
||||||
if (VK_KHR_buffer_device_address_enabled)
|
if (VK_KHR_buffer_device_address_enabled)
|
||||||
TestBufferDeviceAddress();
|
TestBufferDeviceAddress();
|
||||||
|
Loading…
Reference in New Issue
Block a user