Skip to content

Commit 70a683e

Browse files
Added support for multiple Vulkan memory blocks in custom pools with VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT. Works with free-at-once and stack, doesn't work with double stack or ring buffer.
Added new structure members VmaPoolStats::blockCount.
1 parent ee79c63 commit 70a683e

File tree

2 files changed

+323
-119
lines changed

2 files changed

+323
-119
lines changed

src/Tests.cpp

Lines changed: 142 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,14 +1839,139 @@ static void TestLinearAllocator()
18391839
bufInfo.clear();
18401840
}
18411841

1842-
// Try to create pool with maxBlockCount higher than 1. It should fail.
1842+
vmaDestroyPool(g_hAllocator, pool);
1843+
}
1844+
1845+
static void TestLinearAllocatorMultiBlock()
1846+
{
1847+
wprintf(L"Test linear allocator multi block\n");
1848+
1849+
RandomNumberGenerator rand{345673};
1850+
1851+
VkBufferCreateInfo sampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
1852+
sampleBufCreateInfo.size = 1024 * 1024;
1853+
sampleBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
1854+
1855+
VmaAllocationCreateInfo sampleAllocCreateInfo = {};
1856+
sampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
1857+
1858+
VmaPoolCreateInfo poolCreateInfo = {};
1859+
poolCreateInfo.flags = VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT;
1860+
VkResult res = vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &sampleBufCreateInfo, &sampleAllocCreateInfo, &poolCreateInfo.memoryTypeIndex);
1861+
assert(res == VK_SUCCESS);
1862+
1863+
VmaPool pool = nullptr;
1864+
res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);
1865+
assert(res == VK_SUCCESS);
1866+
1867+
VkBufferCreateInfo bufCreateInfo = sampleBufCreateInfo;
1868+
1869+
VmaAllocationCreateInfo allocCreateInfo = {};
1870+
allocCreateInfo.pool = pool;
1871+
1872+
std::vector<BufferInfo> bufInfo;
1873+
VmaAllocationInfo allocInfo;
1874+
1875+
// Test one-time free.
18431876
{
1844-
VmaPoolCreateInfo altPoolCreateInfo = poolCreateInfo;
1845-
altPoolCreateInfo.maxBlockCount = 2;
1877+
// Allocate buffers until we move to a second block.
1878+
VkDeviceMemory lastMem = VK_NULL_HANDLE;
1879+
for(uint32_t i = 0; ; ++i)
1880+
{
1881+
BufferInfo newBufInfo;
1882+
res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
1883+
&newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
1884+
assert(res == VK_SUCCESS);
1885+
bufInfo.push_back(newBufInfo);
1886+
if(lastMem && allocInfo.deviceMemory != lastMem)
1887+
{
1888+
break;
1889+
}
1890+
lastMem = allocInfo.deviceMemory;
1891+
}
1892+
1893+
assert(bufInfo.size() > 2);
18461894

1847-
VmaPool altPool = nullptr;
1848-
res = vmaCreatePool(g_hAllocator, &altPoolCreateInfo, &altPool);
1849-
assert(res != VK_SUCCESS);
1895+
// Make sure that pool has now two blocks.
1896+
VmaPoolStats poolStats = {};
1897+
vmaGetPoolStats(g_hAllocator, pool, &poolStats);
1898+
assert(poolStats.blockCount == 2);
1899+
1900+
// Destroy all the buffers in random order.
1901+
while(!bufInfo.empty())
1902+
{
1903+
const size_t indexToDestroy = rand.Generate() % bufInfo.size();
1904+
const BufferInfo& currBufInfo = bufInfo[indexToDestroy];
1905+
vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
1906+
bufInfo.erase(bufInfo.begin() + indexToDestroy);
1907+
}
1908+
1909+
// Make sure that pool has now at most one block.
1910+
vmaGetPoolStats(g_hAllocator, pool, &poolStats);
1911+
assert(poolStats.blockCount <= 1);
1912+
}
1913+
1914+
// Test stack.
1915+
{
1916+
// Allocate buffers until we move to a second block.
1917+
VkDeviceMemory lastMem = VK_NULL_HANDLE;
1918+
for(uint32_t i = 0; ; ++i)
1919+
{
1920+
BufferInfo newBufInfo;
1921+
res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
1922+
&newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
1923+
assert(res == VK_SUCCESS);
1924+
bufInfo.push_back(newBufInfo);
1925+
if(lastMem && allocInfo.deviceMemory != lastMem)
1926+
{
1927+
break;
1928+
}
1929+
lastMem = allocInfo.deviceMemory;
1930+
}
1931+
1932+
assert(bufInfo.size() > 2);
1933+
1934+
// Add few more buffers.
1935+
for(uint32_t i = 0; i < 5; ++i)
1936+
{
1937+
BufferInfo newBufInfo;
1938+
res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
1939+
&newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
1940+
assert(res == VK_SUCCESS);
1941+
bufInfo.push_back(newBufInfo);
1942+
}
1943+
1944+
// Make sure that pool has now two blocks.
1945+
VmaPoolStats poolStats = {};
1946+
vmaGetPoolStats(g_hAllocator, pool, &poolStats);
1947+
assert(poolStats.blockCount == 2);
1948+
1949+
// Delete half of buffers, LIFO.
1950+
for(size_t i = 0, countToDelete = bufInfo.size() / 2; i < countToDelete; ++i)
1951+
{
1952+
const BufferInfo& currBufInfo = bufInfo.back();
1953+
vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
1954+
bufInfo.pop_back();
1955+
}
1956+
1957+
// Add one more buffer.
1958+
BufferInfo newBufInfo;
1959+
res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
1960+
&newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
1961+
assert(res == VK_SUCCESS);
1962+
bufInfo.push_back(newBufInfo);
1963+
1964+
// Make sure that pool has now one block.
1965+
vmaGetPoolStats(g_hAllocator, pool, &poolStats);
1966+
assert(poolStats.blockCount == 1);
1967+
1968+
// Delete all the remaining buffers, LIFO.
1969+
while(!bufInfo.empty())
1970+
{
1971+
const BufferInfo& currBufInfo = bufInfo.back();
1972+
vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
1973+
bufInfo.pop_back();
1974+
}
18501975
}
18511976

18521977
vmaDestroyPool(g_hAllocator, pool);
@@ -3841,6 +3966,16 @@ void Test()
38413966
{
38423967
wprintf(L"TESTING:\n");
38433968

3969+
if(false)
3970+
{
3971+
// # Temporarily insert custom tests here
3972+
TestLinearAllocator();
3973+
ManuallyTestLinearAllocator();
3974+
TestLinearAllocatorMultiBlock();
3975+
BenchmarkLinearAllocator();
3976+
return;
3977+
}
3978+
38443979
// # Simple tests
38453980

38463981
TestBasics();
@@ -3857,6 +3992,7 @@ void Test()
38573992
TestMappingMultithreaded();
38583993
TestLinearAllocator();
38593994
ManuallyTestLinearAllocator();
3995+
TestLinearAllocatorMultiBlock();
38603996
BenchmarkLinearAllocator();
38613997
TestDefragmentationSimple();
38623998
TestDefragmentationFull();

0 commit comments

Comments
 (0)