mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
synced 2024-11-14 04:11:48 +00:00
More implementation and first tests.
Crashing for now - need more refactoring.
This commit is contained in:
parent
7acc6c0ca8
commit
54b7eccc35
@ -2194,6 +2194,30 @@ struct VmaVirtualBlockCreateInfo
|
|||||||
const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks;
|
const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// TODO
|
||||||
|
typedef enum VmaVirtualAllocationCreateFlagBits {
|
||||||
|
/** Allocation will be created from upper stack in a double stack pool.
|
||||||
|
|
||||||
|
This flag is only allowed for virtual blocks created with #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT flag.
|
||||||
|
*/
|
||||||
|
VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT,
|
||||||
|
/** Allocation strategy that tries to minimize memory usage.
|
||||||
|
*/
|
||||||
|
VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT,
|
||||||
|
/** Allocation strategy that tries to minimize allocation time.
|
||||||
|
*/
|
||||||
|
VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT,
|
||||||
|
/** Allocation strategy that tries to minimize memory fragmentation.
|
||||||
|
*/
|
||||||
|
VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT,
|
||||||
|
/** A bit mask to extract only `STRATEGY` bits from entire set of flags.
|
||||||
|
*/
|
||||||
|
VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK = VMA_ALLOCATION_CREATE_STRATEGY_MASK,
|
||||||
|
|
||||||
|
VMA_VIRTUAL_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||||
|
} VmaVirtualAllocationCreateFlagBits;
|
||||||
|
typedef VkFlags VmaVirtualAllocationCreateFlags;
|
||||||
|
|
||||||
/// Parameters of created virtual allocation to be passed to vma TODO.
|
/// Parameters of created virtual allocation to be passed to vma TODO.
|
||||||
struct VmaVirtualAllocationCreateInfo
|
struct VmaVirtualAllocationCreateInfo
|
||||||
{
|
{
|
||||||
@ -2207,6 +2231,10 @@ struct VmaVirtualAllocationCreateInfo
|
|||||||
Must be power of two. Special value 0 has the same meaning as 1 - means no special alignment is required, so allocation can start at any offset.
|
Must be power of two. Special value 0 has the same meaning as 1 - means no special alignment is required, so allocation can start at any offset.
|
||||||
*/
|
*/
|
||||||
VkDeviceSize alignment;
|
VkDeviceSize alignment;
|
||||||
|
/** \brief TODO
|
||||||
|
|
||||||
|
*/
|
||||||
|
VmaVirtualAllocationCreateFlags flags;
|
||||||
/** \brief Custom pointer to be associated with the allocation.
|
/** \brief Custom pointer to be associated with the allocation.
|
||||||
|
|
||||||
It can be fetched or changed later.
|
It can be fetched or changed later.
|
||||||
@ -6831,22 +6859,43 @@ public:
|
|||||||
const VkAllocationCallbacks m_AllocationCallbacks;
|
const VkAllocationCallbacks m_AllocationCallbacks;
|
||||||
|
|
||||||
VmaVirtualBlock_T(const VmaVirtualBlockCreateInfo& createInfo);
|
VmaVirtualBlock_T(const VmaVirtualBlockCreateInfo& createInfo);
|
||||||
~VmaVirtualBlock_T();
|
~VmaVirtualBlock_T()
|
||||||
VkResult Init();
|
{
|
||||||
|
vma_delete(GetAllocationCallbacks(), m_Metadata);
|
||||||
|
}
|
||||||
|
VkResult Init()
|
||||||
|
{
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
const VkAllocationCallbacks* GetAllocationCallbacks() const
|
const VkAllocationCallbacks* GetAllocationCallbacks() const
|
||||||
{
|
{
|
||||||
return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : VMA_NULL;
|
return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : VMA_NULL;
|
||||||
}
|
}
|
||||||
bool IsEmpty() const;
|
bool IsEmpty() const
|
||||||
void GetAllocationInfo(VkDeviceSize offset, VmaVirtualAllocationInfo& outInfo) const;
|
{
|
||||||
|
return m_Metadata->IsEmpty();
|
||||||
|
}
|
||||||
|
void GetAllocationInfo(VkDeviceSize offset, VmaVirtualAllocationInfo& outInfo) const
|
||||||
|
{
|
||||||
|
m_Metadata->GetAllocationInfo(offset, outInfo);
|
||||||
|
}
|
||||||
VkResult Allocate(const VmaVirtualAllocationCreateInfo& createInfo, VkDeviceSize& outOffset);
|
VkResult Allocate(const VmaVirtualAllocationCreateInfo& createInfo, VkDeviceSize& outOffset);
|
||||||
void Free(VkDeviceSize offset);
|
void Free(VkDeviceSize offset)
|
||||||
void Clear();
|
{
|
||||||
void SetAllocationUserData(VkDeviceSize offset, void* userData);
|
m_Metadata->FreeAtOffset(offset);
|
||||||
|
}
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
m_Metadata->Clear();
|
||||||
|
}
|
||||||
|
void SetAllocationUserData(VkDeviceSize offset, void* userData)
|
||||||
|
{
|
||||||
|
m_Metadata->SetAllocationUserData(offset, userData);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
VmaBlockMetadata* m_Metadata;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -16596,48 +16645,49 @@ VmaVirtualBlock_T::VmaVirtualBlock_T(const VmaVirtualBlockCreateInfo& createInfo
|
|||||||
m_AllocationCallbacksSpecified(createInfo.pAllocationCallbacks != VMA_NULL),
|
m_AllocationCallbacksSpecified(createInfo.pAllocationCallbacks != VMA_NULL),
|
||||||
m_AllocationCallbacks(createInfo.pAllocationCallbacks != VMA_NULL ? *createInfo.pAllocationCallbacks : VmaEmptyAllocationCallbacks)
|
m_AllocationCallbacks(createInfo.pAllocationCallbacks != VMA_NULL ? *createInfo.pAllocationCallbacks : VmaEmptyAllocationCallbacks)
|
||||||
{
|
{
|
||||||
//TODO
|
const uint32_t algorithm = createInfo.flags & VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK;
|
||||||
|
switch(algorithm)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_Generic)(VK_NULL_HANDLE, true);
|
||||||
|
break;
|
||||||
|
case VMA_VIRTUAL_BLOCK_CREATE_BUDDY_ALGORITHM_BIT:
|
||||||
|
m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_Buddy)(VK_NULL_HANDLE, true);
|
||||||
|
break;
|
||||||
|
case VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT:
|
||||||
|
m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_Linear)(VK_NULL_HANDLE, true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
VMA_ASSERT(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
VmaVirtualBlock_T::~VmaVirtualBlock_T()
|
m_Metadata->Init(createInfo.size);
|
||||||
{
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
VkResult VmaVirtualBlock_T::Init()
|
|
||||||
{
|
|
||||||
//TODO
|
|
||||||
return VK_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VmaVirtualBlock_T::IsEmpty() const
|
|
||||||
{
|
|
||||||
return true;//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
void VmaVirtualBlock_T::GetAllocationInfo(VkDeviceSize offset, VmaVirtualAllocationInfo& outInfo) const
|
|
||||||
{
|
|
||||||
//TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult VmaVirtualBlock_T::Allocate(const VmaVirtualAllocationCreateInfo& createInfo, VkDeviceSize& outOffset)
|
VkResult VmaVirtualBlock_T::Allocate(const VmaVirtualAllocationCreateInfo& createInfo, VkDeviceSize& outOffset)
|
||||||
{
|
{
|
||||||
return VK_ERROR_DEVICE_LOST;//TODO
|
outOffset = VK_WHOLE_SIZE;
|
||||||
}
|
VmaAllocationRequest request = {};
|
||||||
|
if(m_Metadata->CreateAllocationRequest(
|
||||||
void VmaVirtualBlock_T::Free(VkDeviceSize offset)
|
0, // currentFrameIndex - unimportant
|
||||||
|
0, // frameInUseCount - unimportant
|
||||||
|
1, // bufferImageGranularity
|
||||||
|
createInfo.size, // allocSize
|
||||||
|
VMA_MAX(createInfo.alignment, 1llu), // allocAlignment
|
||||||
|
(createInfo.flags & VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0, // upperAddress
|
||||||
|
VMA_SUBALLOCATION_TYPE_UNKNOWN, // allocType - unimportant
|
||||||
|
false, // canMakeOthersLost
|
||||||
|
createInfo.flags & VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK, // strategy
|
||||||
|
&request))
|
||||||
{
|
{
|
||||||
//TODO
|
m_Metadata->Alloc(request,
|
||||||
|
VMA_SUBALLOCATION_TYPE_UNKNOWN, // type - unimportant
|
||||||
|
createInfo.size, // allocSize
|
||||||
|
createInfo.pUserData);
|
||||||
|
outOffset = request.offset;
|
||||||
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
||||||
void VmaVirtualBlock_T::Clear()
|
|
||||||
{
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
void VmaVirtualBlock_T::SetAllocationUserData(VkDeviceSize offset, void* userData)
|
|
||||||
{
|
|
||||||
//TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
125
src/Tests.cpp
125
src/Tests.cpp
@ -31,6 +31,7 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
static const char* CODE_DESCRIPTION = "Foo";
|
static const char* CODE_DESCRIPTION = "Foo";
|
||||||
|
static constexpr VkDeviceSize MEGABYTE = 1024 * 1024;
|
||||||
|
|
||||||
extern VkCommandBuffer g_hTemporaryCommandBuffer;
|
extern VkCommandBuffer g_hTemporaryCommandBuffer;
|
||||||
extern const VkAllocationCallbacks* g_Allocs;
|
extern const VkAllocationCallbacks* g_Allocs;
|
||||||
@ -2686,6 +2687,126 @@ static void TestBasics()
|
|||||||
TestInvalidAllocations();
|
TestInvalidAllocations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void TestVirtualBlocks()
|
||||||
|
{
|
||||||
|
wprintf(L"Test virtual blocks\n");
|
||||||
|
|
||||||
|
const VkDeviceSize blockSize = 16 * MEGABYTE;
|
||||||
|
const VkDeviceSize alignment = 256;
|
||||||
|
|
||||||
|
// # Create block 16 MB
|
||||||
|
|
||||||
|
VmaVirtualBlockCreateInfo blockCreateInfo = {};
|
||||||
|
blockCreateInfo.pAllocationCallbacks = g_Allocs;
|
||||||
|
blockCreateInfo.size = blockSize;
|
||||||
|
VmaVirtualBlock block;
|
||||||
|
TEST(vmaCreateVirtualBlock(&blockCreateInfo, &block) == VK_SUCCESS && block);
|
||||||
|
|
||||||
|
// # Allocate 8 MB
|
||||||
|
|
||||||
|
VmaVirtualAllocationCreateInfo allocCreateInfo = {};
|
||||||
|
allocCreateInfo.alignment = alignment;
|
||||||
|
allocCreateInfo.pUserData = (void*)(uintptr_t)1;
|
||||||
|
allocCreateInfo.size = 8 * MEGABYTE;
|
||||||
|
VkDeviceSize alloc0Offset;
|
||||||
|
TEST(vmaVirtualAllocate(block, &allocCreateInfo, &alloc0Offset) == VK_SUCCESS && alloc0Offset < blockSize);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// # Validate the allocation
|
||||||
|
|
||||||
|
VIRTUAL_ALLOCATION_INFO allocInfo = {};
|
||||||
|
block->GetAllocationInfo(alloc0Offset, &allocInfo);
|
||||||
|
CHECK_BOOL( allocInfo.size == allocDesc.Size );
|
||||||
|
CHECK_BOOL( allocInfo.pUserData == allocDesc.pUserData );
|
||||||
|
|
||||||
|
// # Check SetUserData
|
||||||
|
|
||||||
|
block->SetAllocationUserData(alloc0Offset, (void*)(uintptr_t)2);
|
||||||
|
block->GetAllocationInfo(alloc0Offset, &allocInfo);
|
||||||
|
CHECK_BOOL( allocInfo.pUserData == (void*)(uintptr_t)2 );
|
||||||
|
|
||||||
|
// # Allocate 4 MB
|
||||||
|
|
||||||
|
allocDesc.Size = 4 * MEGABYTE;
|
||||||
|
allocDesc.Alignment = alignment;
|
||||||
|
UINT64 alloc1Offset;
|
||||||
|
CHECK_HR( block->Allocate(&allocDesc, &alloc1Offset) );
|
||||||
|
CHECK_BOOL( alloc1Offset < blockSize );
|
||||||
|
CHECK_BOOL( alloc1Offset + 4 * MEGABYTE <= alloc0Offset || alloc0Offset + 8 * MEGABYTE <= alloc1Offset ); // Check if they don't overlap.
|
||||||
|
|
||||||
|
// # Allocate another 8 MB - it should fail
|
||||||
|
|
||||||
|
allocDesc.Size = 8 * MEGABYTE;
|
||||||
|
allocDesc.Alignment = alignment;
|
||||||
|
UINT64 alloc2Offset;
|
||||||
|
CHECK_BOOL( FAILED(block->Allocate(&allocDesc, &alloc2Offset)) );
|
||||||
|
CHECK_BOOL( alloc2Offset == UINT64_MAX );
|
||||||
|
|
||||||
|
// # Free the 4 MB block. Now allocation of 8 MB should succeed.
|
||||||
|
|
||||||
|
block->FreeAllocation(alloc1Offset);
|
||||||
|
CHECK_HR( block->Allocate(&allocDesc, &alloc2Offset) );
|
||||||
|
CHECK_BOOL( alloc2Offset < blockSize );
|
||||||
|
CHECK_BOOL( alloc2Offset + 4 * MEGABYTE <= alloc0Offset || alloc0Offset + 8 * MEGABYTE <= alloc2Offset ); // Check if they don't overlap.
|
||||||
|
|
||||||
|
// # Calculate statistics
|
||||||
|
|
||||||
|
StatInfo statInfo = {};
|
||||||
|
block->CalculateStats(&statInfo);
|
||||||
|
CHECK_BOOL(statInfo.AllocationCount == 2);
|
||||||
|
CHECK_BOOL(statInfo.BlockCount == 1);
|
||||||
|
CHECK_BOOL(statInfo.UsedBytes == blockSize);
|
||||||
|
CHECK_BOOL(statInfo.UnusedBytes + statInfo.UsedBytes == blockSize);
|
||||||
|
|
||||||
|
// # Generate JSON dump
|
||||||
|
|
||||||
|
WCHAR* json = nullptr;
|
||||||
|
block->BuildStatsString(&json);
|
||||||
|
{
|
||||||
|
std::wstring str(json);
|
||||||
|
CHECK_BOOL( str.find(L"\"UserData\": 1") != std::wstring::npos );
|
||||||
|
CHECK_BOOL( str.find(L"\"UserData\": 2") != std::wstring::npos );
|
||||||
|
}
|
||||||
|
block->FreeStatsString(json);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// # Free alloc0, leave alloc2 unfreed.
|
||||||
|
|
||||||
|
vmaVirtualFree(block, alloc0Offset);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// # Test alignment
|
||||||
|
|
||||||
|
{
|
||||||
|
constexpr size_t allocCount = 10;
|
||||||
|
UINT64 allocOffset[allocCount] = {};
|
||||||
|
for(size_t i = 0; i < allocCount; ++i)
|
||||||
|
{
|
||||||
|
const bool alignment0 = i == allocCount - 1;
|
||||||
|
allocDesc.Size = i * 3 + 15;
|
||||||
|
allocDesc.Alignment = alignment0 ? 0 : 8;
|
||||||
|
CHECK_HR(block->Allocate(&allocDesc, &allocOffset[i]));
|
||||||
|
if(!alignment0)
|
||||||
|
{
|
||||||
|
CHECK_BOOL(allocOffset[i] % allocDesc.Alignment == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = allocCount; i--; )
|
||||||
|
{
|
||||||
|
block->FreeAllocation(allocOffset[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Final cleanup
|
||||||
|
|
||||||
|
block->FreeAllocation(alloc2Offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//vmaClearVirtualBlock(block);
|
||||||
|
vmaDestroyVirtualBlock(block);
|
||||||
|
}
|
||||||
|
|
||||||
static void TestAllocationVersusResourceSize()
|
static void TestAllocationVersusResourceSize()
|
||||||
{
|
{
|
||||||
wprintf(L"Test allocation versus resource size\n");
|
wprintf(L"Test allocation versus resource size\n");
|
||||||
@ -6561,16 +6682,18 @@ void Test()
|
|||||||
{
|
{
|
||||||
wprintf(L"TESTING:\n");
|
wprintf(L"TESTING:\n");
|
||||||
|
|
||||||
if(false)
|
if(true)
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Temporarily insert custom tests here:
|
// Temporarily insert custom tests here:
|
||||||
|
TestVirtualBlocks();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// # Simple tests
|
// # Simple tests
|
||||||
|
|
||||||
TestBasics();
|
TestBasics();
|
||||||
|
TestVirtualBlocks();
|
||||||
TestAllocationVersusResourceSize();
|
TestAllocationVersusResourceSize();
|
||||||
//TestGpuData(); // Not calling this because it's just testing the testing environment.
|
//TestGpuData(); // Not calling this because it's just testing the testing environment.
|
||||||
#if VMA_DEBUG_MARGIN
|
#if VMA_DEBUG_MARGIN
|
||||||
|
Loading…
Reference in New Issue
Block a user