From ab16036dd5e79a41f10b6bfad4591870d90f9a04 Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Tue, 1 Feb 2022 17:57:17 +0100 Subject: [PATCH] Updated tests and documentation for VMA_DEBUG_MARGIN Fixed type of VmaVirtualBlockCreateInfo::flags. Rebuilt the docs. --- docs/gfx/Margins_2.png | Bin 367 -> 6542 bytes docs/html/debugging_memory_usage.html | 6 +- docs/html/functions.html | 2 +- docs/html/functions_vars.html | 2 +- docs/html/group__group__virtual.html | 12 +- docs/html/search/all_5.js | 2 +- docs/html/search/variables_4.js | 2 +- ...vma_virtual_block_create_info-members.html | 2 +- .../struct_vma_virtual_block_create_info.html | 12 +- docs/html/vk__mem__alloc_8h.html | 6 +- include/vk_mem_alloc.h | 15 +- src/Tests.cpp | 132 ++++++++++++------ 12 files changed, 123 insertions(+), 70 deletions(-) diff --git a/docs/gfx/Margins_2.png b/docs/gfx/Margins_2.png index 6f75877c1426b3935dfa8d2c3bccdd869f5dae2e..e0aefbcc037f9c3544489f50c9d8e7091eec8672 100644 GIT binary patch literal 6542 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 delta 280 zcmeA(e$O;PS%85p$=lt9;XeZq7^~NOo*XG5$MuMfk5|cThWMp`$&C^k_18UJ978H@ zy}k30w^>1gCBS2sXKYLCn~?dtH*m~dde+r*-p{vGit}{Y=a;wkZQQ)5 z?5OLFe)`|A72pSDF`&(^7K|GnuAzo6mQ>xm`%7k{3=*7thmm$dYIk<(8X z|4`WKXM5yDoo(B{-)B!a%YB;AZu3Mjm%kFurUp|_#sAxVvx&u(%r@V%?XT`plm&U- M)78&qol`;+047F%#Q*>R diff --git a/docs/html/debugging_memory_usage.html b/docs/html/debugging_memory_usage.html index 31493a4..bcff6dc 100644 --- a/docs/html/debugging_memory_usage.html +++ b/docs/html/debugging_memory_usage.html @@ -82,23 +82,23 @@ Memory initialization Margins

By default, allocations are laid out in memory blocks next to each other if possible (considering required alignment, bufferImageGranularity, and nonCoherentAtomSize).

Allocations without margin

-

Define macro VMA_DEBUG_MARGIN to some non-zero value (e.g. 16) to enforce specified number of bytes as a margin before and after every allocation.

+

Define macro VMA_DEBUG_MARGIN to some non-zero value (e.g. 16) to enforce specified number of bytes as a margin after every allocation.

#define VMA_DEBUG_MARGIN 16
#include "vk_mem_alloc.h"

Allocations with margin

If your bug goes away after enabling margins, it means it may be caused by memory being overwritten outside of allocation boundaries. It is not 100% certain though. Change in application behavior may also be caused by different order and distribution of allocations across memory blocks after margins are applied.

-

The margin is applied also before first and after last allocation in a block. It may occur only once between two adjacent allocations.

Margins work with all types of memory.

Margin is applied only to allocations made out of memory blocks and not to dedicated allocations, which have their own memory block of specific size. It is thus not applied to allocations made using VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag or those automatically decided to put into dedicated allocations, e.g. due to its large size or recommended by VK_KHR_dedicated_allocation extension. Margins are also not active in custom pools created with VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag.

Margins appear in JSON dump as part of free space.

Note that enabling margins increases memory usage and fragmentation.

+

Margins do not apply to Virtual allocator.

Corruption detection

You can additionally define macro VMA_DEBUG_DETECT_CORRUPTION to 1 to enable validation of contents of the margins.

#define VMA_DEBUG_MARGIN 16
#define VMA_DEBUG_DETECT_CORRUPTION 1
#include "vk_mem_alloc.h"
-

When this feature is enabled, number of bytes specified as VMA_DEBUG_MARGIN (it must be multiply of 4) before and after every allocation is filled with a magic number. This idea is also know as "canary". Memory is automatically mapped and unmapped if necessary.

+

When this feature is enabled, number of bytes specified as VMA_DEBUG_MARGIN (it must be multiply of 4) after every allocation is filled with a magic number. This idea is also know as "canary". Memory is automatically mapped and unmapped if necessary.

This number is validated automatically when the allocation is destroyed. If it is not equal to the expected value, VMA_ASSERT() is executed. It clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation, which indicates a serious bug.

You can also explicitly request checking margins of all allocations in all memory blocks that belong to specified memory types by using function vmaCheckCorruption(), or in memory blocks that belong to specified custom pool, by using function vmaCheckPoolCorruption().

Margin validation (corruption detection) works only for memory types that are HOST_VISIBLE and HOST_COHERENT.

diff --git a/docs/html/functions.html b/docs/html/functions.html index 6e00a0b..d034e97 100644 --- a/docs/html/functions.html +++ b/docs/html/functions.html @@ -99,7 +99,7 @@ $(function() {

- f -

diff --git a/docs/html/functions_vars.html b/docs/html/functions_vars.html index bc2b8e8..44eaba4 100644 --- a/docs/html/functions_vars.html +++ b/docs/html/functions_vars.html @@ -99,7 +99,7 @@ $(function() {

- f -

diff --git a/docs/html/group__group__virtual.html b/docs/html/group__group__virtual.html index 94af5db..680207e 100644 --- a/docs/html/group__group__virtual.html +++ b/docs/html/group__group__virtual.html @@ -95,10 +95,10 @@ Classes

Typedefs

typedef enum VmaVirtualBlockCreateFlagBits VmaVirtualBlockCreateFlagBits - Flags to be passed as VmaVirtualBlockCreateInfo::flags. More...
+ Flags to be passed as VmaVirtualBlockCreateInfo::flags. More...
  typedef VkFlags VmaVirtualBlockCreateFlags - Flags to be passed as VmaVirtualBlockCreateInfo::flags. See VmaVirtualBlockCreateFlagBits. More...
+ Flags to be passed as VmaVirtualBlockCreateInfo::flags. See VmaVirtualBlockCreateFlagBits. More...
  typedef enum VmaVirtualAllocationCreateFlagBits VmaVirtualAllocationCreateFlagBits  Flags to be passed as VmaVirtualAllocationCreateInfo::flags. More...
@@ -127,7 +127,7 @@ Enumerations   VMA_VIRTUAL_BLOCK_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} - Flags to be passed as VmaVirtualBlockCreateInfo::flags. More...
+ Flags to be passed as VmaVirtualBlockCreateInfo::flags. More...
  enum  VmaVirtualAllocationCreateFlagBits {
  VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT @@ -252,7 +252,7 @@ Functions
-

Flags to be passed as VmaVirtualBlockCreateInfo::flags.

+

Flags to be passed as VmaVirtualBlockCreateInfo::flags.

@@ -268,7 +268,7 @@ Functions @@ -330,7 +330,7 @@ Functions
-

Flags to be passed as VmaVirtualBlockCreateInfo::flags.

+

Flags to be passed as VmaVirtualBlockCreateInfo::flags.

- - - + + + @@ -89,14 +89,14 @@ Public Attributes

Detailed Description

Parameters of created VmaVirtualBlock object to be passed to vmaCreateVirtualBlock().

Member Data Documentation

- -

◆ flags

+ +

◆ flags

Enumerator
VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT 

Enables alternative, linear allocation algorithm in this virtual block.

Specify this flag to enable linear allocation algorithm, which always creates new allocations after last one and doesn't reuse space from allocations freed in between. It trades memory consumption for simplified algorithm and data structure, which has better performance and uses less memory for metadata.

diff --git a/docs/html/search/all_5.js b/docs/html/search/all_5.js index 0bcc998..00173a3 100644 --- a/docs/html/search/all_5.js +++ b/docs/html/search/all_5.js @@ -1,4 +1,4 @@ var searchData= [ - ['flags_0',['flags',['../struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346',1,'VmaAllocatorCreateInfo::flags()'],['../struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b',1,'VmaAllocationCreateInfo::flags()'],['../struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446',1,'VmaPoolCreateInfo::flags()'],['../struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9',1,'VmaDefragmentationInfo2::flags()'],['../struct_vma_virtual_block_create_info.html#a5838b15c053a0370420e4e1d82d09c09',1,'VmaVirtualBlockCreateInfo::flags()'],['../struct_vma_virtual_allocation_create_info.html#ab10e16956cc4bf20ced9de77d1129ea4',1,'VmaVirtualAllocationCreateInfo::flags()']]] + ['flags_0',['flags',['../struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346',1,'VmaAllocatorCreateInfo::flags()'],['../struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b',1,'VmaAllocationCreateInfo::flags()'],['../struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446',1,'VmaPoolCreateInfo::flags()'],['../struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9',1,'VmaDefragmentationInfo2::flags()'],['../struct_vma_virtual_block_create_info.html#aaab9bf7e2d228c02ab6d90a72a6e6912',1,'VmaVirtualBlockCreateInfo::flags()'],['../struct_vma_virtual_allocation_create_info.html#ab10e16956cc4bf20ced9de77d1129ea4',1,'VmaVirtualAllocationCreateInfo::flags()']]] ]; diff --git a/docs/html/search/variables_4.js b/docs/html/search/variables_4.js index 0bcc998..00173a3 100644 --- a/docs/html/search/variables_4.js +++ b/docs/html/search/variables_4.js @@ -1,4 +1,4 @@ var searchData= [ - ['flags_0',['flags',['../struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346',1,'VmaAllocatorCreateInfo::flags()'],['../struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b',1,'VmaAllocationCreateInfo::flags()'],['../struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446',1,'VmaPoolCreateInfo::flags()'],['../struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9',1,'VmaDefragmentationInfo2::flags()'],['../struct_vma_virtual_block_create_info.html#a5838b15c053a0370420e4e1d82d09c09',1,'VmaVirtualBlockCreateInfo::flags()'],['../struct_vma_virtual_allocation_create_info.html#ab10e16956cc4bf20ced9de77d1129ea4',1,'VmaVirtualAllocationCreateInfo::flags()']]] + ['flags_0',['flags',['../struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346',1,'VmaAllocatorCreateInfo::flags()'],['../struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b',1,'VmaAllocationCreateInfo::flags()'],['../struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446',1,'VmaPoolCreateInfo::flags()'],['../struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9',1,'VmaDefragmentationInfo2::flags()'],['../struct_vma_virtual_block_create_info.html#aaab9bf7e2d228c02ab6d90a72a6e6912',1,'VmaVirtualBlockCreateInfo::flags()'],['../struct_vma_virtual_allocation_create_info.html#ab10e16956cc4bf20ced9de77d1129ea4',1,'VmaVirtualAllocationCreateInfo::flags()']]] ]; diff --git a/docs/html/struct_vma_virtual_block_create_info-members.html b/docs/html/struct_vma_virtual_block_create_info-members.html index 231cc5c..732a4cd 100644 --- a/docs/html/struct_vma_virtual_block_create_info-members.html +++ b/docs/html/struct_vma_virtual_block_create_info-members.html @@ -68,7 +68,7 @@ $(function() {

This is the complete list of members for VmaVirtualBlockCreateInfo, including all inherited members.

- +
flagsVmaVirtualBlockCreateInfo
flagsVmaVirtualBlockCreateInfo
pAllocationCallbacksVmaVirtualBlockCreateInfo
sizeVmaVirtualBlockCreateInfo
diff --git a/docs/html/struct_vma_virtual_block_create_info.html b/docs/html/struct_vma_virtual_block_create_info.html index ecfa529..27e07e4 100644 --- a/docs/html/struct_vma_virtual_block_create_info.html +++ b/docs/html/struct_vma_virtual_block_create_info.html @@ -79,9 +79,9 @@ Public Attributes
VkDeviceSize size
 Total size of the virtual block. More...
 
VmaVirtualBlockCreateFlagBits flags
 Use combination of VmaVirtualBlockCreateFlagBits. More...
 
VmaVirtualBlockCreateFlags flags
 Use combination of VmaVirtualBlockCreateFlagBits. More...
 
const VkAllocationCallbacks * pAllocationCallbacks
 Custom CPU memory allocation callbacks. Optional. More...
 
- +
VmaVirtualBlockCreateFlagBits VmaVirtualBlockCreateInfo::flagsVmaVirtualBlockCreateFlags VmaVirtualBlockCreateInfo::flags
diff --git a/docs/html/vk__mem__alloc_8h.html b/docs/html/vk__mem__alloc_8h.html index 549db9a..b84f804 100644 --- a/docs/html/vk__mem__alloc_8h.html +++ b/docs/html/vk__mem__alloc_8h.html @@ -177,10 +177,10 @@ Typedefs typedef VkFlags VmaDefragmentationFlags   typedef enum VmaVirtualBlockCreateFlagBits VmaVirtualBlockCreateFlagBits - Flags to be passed as VmaVirtualBlockCreateInfo::flags. More...
+ Flags to be passed as VmaVirtualBlockCreateInfo::flags. More...
  typedef VkFlags VmaVirtualBlockCreateFlags - Flags to be passed as VmaVirtualBlockCreateInfo::flags. See VmaVirtualBlockCreateFlagBits. More...
+ Flags to be passed as VmaVirtualBlockCreateInfo::flags. See VmaVirtualBlockCreateFlagBits. More...
  typedef enum VmaVirtualAllocationCreateFlagBits VmaVirtualAllocationCreateFlagBits  Flags to be passed as VmaVirtualAllocationCreateInfo::flags. More...
@@ -330,7 +330,7 @@ Enumerations   VMA_VIRTUAL_BLOCK_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} - Flags to be passed as VmaVirtualBlockCreateInfo::flags. More...
+ Flags to be passed as VmaVirtualBlockCreateInfo::flags. More...
  enum  VmaVirtualAllocationCreateFlagBits {
  VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT diff --git a/include/vk_mem_alloc.h b/include/vk_mem_alloc.h index ce4f48f..2e55fe0 100644 --- a/include/vk_mem_alloc.h +++ b/include/vk_mem_alloc.h @@ -1450,7 +1450,7 @@ typedef struct VmaVirtualBlockCreateInfo /** \brief Use combination of #VmaVirtualBlockCreateFlagBits. */ - VmaVirtualBlockCreateFlagBits flags; + VmaVirtualBlockCreateFlags flags; /** \brief Custom CPU memory allocation callbacks. Optional. @@ -2831,7 +2831,7 @@ If providing your own implementation, you need to implement a subset of std::ato #ifndef VMA_DEBUG_MARGIN /** - Minimum margin before and after every allocation, in bytes. + Minimum margin after every allocation, in bytes. Set nonzero for debugging purposes only. */ #define VMA_DEBUG_MARGIN (0) @@ -2848,7 +2848,7 @@ If providing your own implementation, you need to implement a subset of std::ato #ifndef VMA_DEBUG_DETECT_CORRUPTION /** Define this macro to 1 together with non-zero value of VMA_DEBUG_MARGIN to - enable writing magic value to the margin before and after every allocation and + enable writing magic value to the margin after every allocation and validating it, so that memory corruptions (out-of-bounds writes) are detected. */ #define VMA_DEBUG_DETECT_CORRUPTION (0) @@ -19276,7 +19276,7 @@ By default, allocations are laid out in memory blocks next to each other if poss ![Allocations without margin](../gfx/Margins_1.png) Define macro `VMA_DEBUG_MARGIN` to some non-zero value (e.g. 16) to enforce specified -number of bytes as a margin before and after every allocation. +number of bytes as a margin after every allocation. \code #define VMA_DEBUG_MARGIN 16 @@ -19290,9 +19290,6 @@ being overwritten outside of allocation boundaries. It is not 100% certain thoug Change in application behavior may also be caused by different order and distribution of allocations across memory blocks after margins are applied. -The margin is applied also before first and after last allocation in a block. -It may occur only once between two adjacent allocations. - Margins work with all types of memory. Margin is applied only to allocations made out of memory blocks and not to dedicated @@ -19306,6 +19303,8 @@ Margins appear in [JSON dump](@ref statistics_json_dump) as part of free space. Note that enabling margins increases memory usage and fragmentation. +Margins do not apply to \ref virtual_allocator. + \section debugging_memory_usage_corruption_detection Corruption detection You can additionally define macro `VMA_DEBUG_DETECT_CORRUPTION` to 1 to enable validation @@ -19318,7 +19317,7 @@ of contents of the margins. \endcode When this feature is enabled, number of bytes specified as `VMA_DEBUG_MARGIN` -(it must be multiply of 4) before and after every allocation is filled with a magic number. +(it must be multiply of 4) after every allocation is filled with a magic number. This idea is also know as "canary". Memory is automatically mapped and unmapped if necessary. diff --git a/src/Tests.cpp b/src/Tests.cpp index 6367d41..7663581 100644 --- a/src/Tests.cpp +++ b/src/Tests.cpp @@ -3291,6 +3291,8 @@ static void TestPoolsAndAllocationParameters() void TestHeapSizeLimit() { + wprintf(L"Test heap size limit\n"); + const VkDeviceSize HEAP_SIZE_LIMIT = 100ull * 1024 * 1024; // 100 MB const VkDeviceSize BLOCK_SIZE = 10ull * 1024 * 1024; // 10 MB @@ -3402,58 +3404,109 @@ static void TestDebugMargin() return; } + wprintf(L"Test VMA_DEBUG_MARGIN = %u\n", (uint32_t)VMA_DEBUG_MARGIN); + VkBufferCreateInfo bufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - + bufInfo.size = 256; // Doesn't matter + VmaAllocationCreateInfo allocCreateInfo = {}; allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY; - // Create few buffers of different size. - const size_t BUF_COUNT = 10; - BufferInfo buffers[BUF_COUNT]; - VmaAllocationInfo allocInfo[BUF_COUNT]; - for(size_t i = 0; i < 10; ++i) + VmaPoolCreateInfo poolCreateInfo = {}; + TEST(vmaFindMemoryTypeIndexForBufferInfo( + g_hAllocator, &bufInfo, &allocCreateInfo, &poolCreateInfo.memoryTypeIndex) == VK_SUCCESS); + + for(size_t algorithmIndex = 0; algorithmIndex < 2; ++algorithmIndex) { - bufInfo.size = (VkDeviceSize)(i + 1) * 64; - // Last one will be mapped. - allocCreateInfo.flags = (i == BUF_COUNT - 1) ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0; + poolCreateInfo.flags = (algorithmIndex == 1 ? VMA_POOL_CREATE_TLSF_ALGORITHM_BIT : 0); + VmaPool pool = VK_NULL_HANDLE; + TEST(vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool) == VK_SUCCESS && pool); + + allocCreateInfo.pool = pool; - VkResult res = vmaCreateBuffer(g_hAllocator, &bufInfo, &allocCreateInfo, &buffers[i].Buffer, &buffers[i].Allocation, &allocInfo[i]); + // Create few buffers of different size. + const size_t BUF_COUNT = 10; + BufferInfo buffers[BUF_COUNT]; + VmaAllocationInfo allocInfo[BUF_COUNT]; + for(size_t allocIndex = 0; allocIndex < 10; ++allocIndex) + { + const bool isLast = allocIndex == BUF_COUNT - 1; + bufInfo.size = (VkDeviceSize)(allocIndex + 1) * 256; + // Last one will be mapped. + allocCreateInfo.flags = isLast ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0; + + VkResult res = vmaCreateBuffer(g_hAllocator, &bufInfo, &allocCreateInfo, &buffers[allocIndex].Buffer, &buffers[allocIndex].Allocation, &allocInfo[allocIndex]); + TEST(res == VK_SUCCESS); + + if(isLast) + { + // Fill with data. + TEST(allocInfo[allocIndex].pMappedData != nullptr); + // Uncomment this "+ 1" to overwrite past end of allocation and check corruption detection. + memset(allocInfo[allocIndex].pMappedData, 0xFF, bufInfo.size /* + 1 */); + } + } + + // Check if their offsets preserve margin between them. + std::sort(allocInfo, allocInfo + BUF_COUNT, [](const VmaAllocationInfo& lhs, const VmaAllocationInfo& rhs) -> bool + { + if(lhs.deviceMemory != rhs.deviceMemory) + { + return lhs.deviceMemory < rhs.deviceMemory; + } + return lhs.offset < rhs.offset; + }); + for(size_t i = 1; i < BUF_COUNT; ++i) + { + if(allocInfo[i].deviceMemory == allocInfo[i - 1].deviceMemory) + { + TEST(allocInfo[i].offset >= allocInfo[i - 1].offset + VMA_DEBUG_MARGIN); + } + } + + VkResult res = vmaCheckCorruption(g_hAllocator, UINT32_MAX); TEST(res == VK_SUCCESS); - if(i == BUF_COUNT - 1) + // JSON dump + char* json = nullptr; + vmaBuildStatsString(g_hAllocator, &json, VK_TRUE); + int I = 1; // Put breakpoint here to manually inspect json in a debugger. + vmaFreeStatsString(g_hAllocator, json); + + // Destroy all buffers. + for(size_t i = BUF_COUNT; i--; ) { - // Fill with data. - TEST(allocInfo[i].pMappedData != nullptr); - // Uncomment this "+ 1" to overwrite past end of allocation and check corruption detection. - memset(allocInfo[i].pMappedData, 0xFF, bufInfo.size /* + 1 */); + vmaDestroyBuffer(g_hAllocator, buffers[i].Buffer, buffers[i].Allocation); } + + vmaDestroyPool(g_hAllocator, pool); } +} - // Check if their offsets preserve margin between them. - std::sort(allocInfo, allocInfo + BUF_COUNT, [](const VmaAllocationInfo& lhs, const VmaAllocationInfo& rhs) -> bool +static void TestDebugMarginNotInVirtualAllocator() +{ + constexpr size_t ALLOCATION_COUNT = 10; + for(size_t algorithm = 0; algorithm < 2; ++algorithm) { - if(lhs.deviceMemory != rhs.deviceMemory) + VmaVirtualBlockCreateInfo blockCreateInfo = {}; + blockCreateInfo.size = ALLOCATION_COUNT * MEGABYTE; + blockCreateInfo.flags = (algorithm == 1 ? VMA_VIRTUAL_BLOCK_CREATE_TLSF_ALGORITHM_BIT : 0); + + VmaVirtualBlock block = VK_NULL_HANDLE; + TEST(vmaCreateVirtualBlock(&blockCreateInfo, &block) == VK_SUCCESS); + + // Fill the entire block + VmaVirtualAllocation allocs[ALLOCATION_COUNT]; + for(size_t i = 0; i < ALLOCATION_COUNT; ++i) { - return lhs.deviceMemory < rhs.deviceMemory; + VmaVirtualAllocationCreateInfo allocCreateInfo = {}; + allocCreateInfo.size = 1 * MEGABYTE; + TEST(vmaVirtualAllocate(block, &allocCreateInfo, &allocs[i], nullptr) == VK_SUCCESS); } - return lhs.offset < rhs.offset; - }); - for(size_t i = 1; i < BUF_COUNT; ++i) - { - if(allocInfo[i].deviceMemory == allocInfo[i - 1].deviceMemory) - { - TEST(allocInfo[i].offset >= allocInfo[i - 1].offset + VMA_DEBUG_MARGIN); - } - } - VkResult res = vmaCheckCorruption(g_hAllocator, UINT32_MAX); - TEST(res == VK_SUCCESS); - - // Destroy all buffers. - for(size_t i = BUF_COUNT; i--; ) - { - vmaDestroyBuffer(g_hAllocator, buffers[i].Buffer, buffers[i].Allocation); + vmaClearVirtualBlock(block); + vmaDestroyVirtualBlock(block); } } #endif @@ -6947,21 +7000,21 @@ void Test() // # Simple tests +#if VMA_DEBUG_MARGIN + TestDebugMargin(); + TestDebugMarginNotInVirtualAllocator(); +#else TestBasics(); TestVirtualBlocks(); TestVirtualBlocksAlgorithms(); TestVirtualBlocksAlgorithmsBenchmark(); TestAllocationVersusResourceSize(); //TestGpuData(); // Not calling this because it's just testing the testing environment. -#if VMA_DEBUG_MARGIN - TestDebugMargin(); -#else TestPool_SameSize(); TestPool_MinBlockCount(); TestPool_MinAllocationAlignment(); TestPoolsAndAllocationParameters(); TestHeapSizeLimit(); -#endif #if VMA_DEBUG_INITIALIZE_ALLOCATIONS TestAllocationsInitialization(); #endif @@ -7017,6 +7070,7 @@ void Test() //PerformCustomPoolTest(file); fclose(file); +#endif // #if defined(VMA_DEBUG_MARGIN) && VMA_DEBUG_MARGIN > 0 wprintf(L"Done, all PASSED.\n"); }