From 80a07979f5253690a0c276e1aeade65d4454ba45 Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Fri, 4 Mar 2022 16:33:16 +0100 Subject: [PATCH] Improvements in documentation, especially regarding defragmentation --- docs/html/allocation_annotation.html | 31 +--- docs/html/annotated.html | 2 +- docs/html/defragmentation.html | 103 ++++++++++--- docs/html/globals.html | 2 +- docs/html/globals_func.html | 2 +- docs/html/group__group__alloc.html | 20 +-- docs/html/group__group__init.html | 4 +- docs/html/search/all_11.js | 2 +- docs/html/search/functions_0.js | 2 +- docs/html/struct_vma_allocation_info.html | 2 +- .../struct_vma_defragmentation_context.html | 2 +- .../struct_vma_defragmentation_stats.html | 4 +- docs/html/vk__mem__alloc_8h.html | 12 +- include/vk_mem_alloc.h | 143 ++++++++++++------ 14 files changed, 211 insertions(+), 120 deletions(-) diff --git a/docs/html/allocation_annotation.html b/docs/html/allocation_annotation.html index 2d93add..8e6b8c9 100644 --- a/docs/html/allocation_annotation.html +++ b/docs/html/allocation_annotation.html @@ -71,7 +71,7 @@ $(function() {

Allocation user data

-

You can annotate allocations with your own information, e.g. for debugging purposes. To do that, fill VmaAllocationCreateInfo::pUserData field when creating an allocation. It is an opaque void* pointer. You can use it e.g. as a pointer, some handle, index, key, ordinal number or any other value that would associate the allocation with your custom metadata.

+

You can annotate allocations with your own information, e.g. for debugging purposes. To do that, fill VmaAllocationCreateInfo::pUserData field when creating an allocation. It is an opaque void* pointer. You can use it e.g. as a pointer, some handle, index, key, ordinal number or any other value that would associate the allocation with your custom metadata. It it useful to identify appropriate data structures in your engine given VmaAllocation, e.g. when doing Defragmentation.

VkBufferCreateInfo bufCreateInfo = ...
MyBufferMetadata* pMetadata = CreateBufferMetadata();
@@ -100,30 +100,13 @@ Allocation user data

Values of (non-zero) allocations' pUserData are printed in JSON report created by vmaBuildStatsString() in hexadecimal form.

Allocation names

-

There is alternative mode available where pUserData pointer is used to point to a null-terminated string, giving a name to the allocation. To use this mode, set VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT flag in VmaAllocationCreateInfo::flags. Then pUserData passed as VmaAllocationCreateInfo::pUserData or argument to vmaSetAllocationUserData() must be either null or a pointer to a null-terminated string. The library creates internal copy of the string, so the pointer you pass doesn't need to be valid for whole lifetime of the allocation. You can free it after the call.

-
VkImageCreateInfo imageInfo = ...
-
-
std::string imageName = "Texture: ";
+

An allocation can also carry a null-terminated string, giving a name to the allocation. To set it, call vmaSetAllocationName(). The library creates internal copy of the string, so the pointer you pass doesn't need to be valid for whole lifetime of the allocation. You can free it after the call.

+
std::string imageName = "Texture: ";
imageName += fileName;
-
-
VmaAllocationCreateInfo allocCreateInfo = {};
-
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
- -
allocCreateInfo.pUserData = imageName.c_str();
-
-
VkImage image;
-
VmaAllocation allocation;
-
vmaCreateImage(allocator, &imageInfo, &allocCreateInfo, &image, &allocation, nullptr);
-
VkResult vmaCreateImage(VmaAllocator allocator, const VkImageCreateInfo *pImageCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, VkImage *pImage, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)
Function similar to vmaCreateBuffer().
-
@ VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT
Definition: vk_mem_alloc.h:562
-
VmaAllocationCreateFlags flags
Use VmaAllocationCreateFlagBits enum.
Definition: vk_mem_alloc.h:1225
-

The value of pUserData pointer of the allocation will be different than the one you passed when setting allocation's name - pointing to a buffer managed internally that holds copy of the string.

-
-
vmaGetAllocationInfo(allocator, allocation, &allocInfo);
-
const char* imageName = (const char*)allocInfo.pUserData;
-
printf("Image name: %s\n", imageName);
-

That string is also printed in JSON report created by vmaBuildStatsString().

-
Note
Passing string name to VMA allocation doesn't automatically set it to the Vulkan buffer or image created with it. You must do it manually using an extension like VK_EXT_debug_utils, which is independent of this library.
+
vmaSetAllocationName(allocator, allocation, imageName.c_str());
+
void vmaSetAllocationName(VmaAllocator allocator, VmaAllocation allocation, const char *pName)
Sets pName in given allocation to new value.
+

The string can be later retrieved by inspecting VmaAllocationInfo::pName. It is also printed in JSON report created by vmaBuildStatsString().

+
Note
Setting string name to VMA allocation doesn't automatically set it to the Vulkan buffer or image created with it. You must do it manually using an extension like VK_EXT_debug_utils, which is independent of this library.
diff --git a/docs/html/annotated.html b/docs/html/annotated.html index 99cfd69..ba12732 100644 --- a/docs/html/annotated.html +++ b/docs/html/annotated.html @@ -78,7 +78,7 @@ $(function() {  CVmaDefragmentationInfoParameters for defragmentation  CVmaDefragmentationMoveSingle move of an allocation to be done for defragmentation  CVmaDefragmentationPassMoveInfoParameters for incremental defragmentation steps - CVmaDefragmentationStatsStatistics returned for defragmentation process in function vmaEndDefragmentation() + CVmaDefragmentationStatsStatistics returned for defragmentation process in function vmaEndDefragmentation()  CVmaDetailedStatisticsMore detailed statistics than VmaStatistics  CVmaDeviceMemoryCallbacksSet of callbacks that the library will call for vkAllocateMemory and vkFreeMemory  CVmaPoolRepresents custom memory pool diff --git a/docs/html/defragmentation.html b/docs/html/defragmentation.html index 26e13ae..7fe71fc 100644 --- a/docs/html/defragmentation.html +++ b/docs/html/defragmentation.html @@ -86,41 +86,106 @@ $(function() {
res = vmaBeginDefragmentationPass(allocator, defragCtx, &pass);
if(res == VK_SUCCESS)
break;
-
else if(res == VK_INCOMPLETE)
+
else if(res != VK_INCOMPLETE)
+
// Handle error...
+
+
for(uint32_t i = 0; i < pass.moveCount; ++i)
{
-
for(uint32_t i = 0; i < pass.moveCount; ++i)
-
{
-
//- Inspect pass.pMoves[i].srcAllocation, identify what buffer or image it represents.
-
//- Recreate and bind this buffer or image at pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset.
-
//- Issue a vkCmdCopyBuffer/vkCmdCopyImage to copy its content to the new place.
-
}
-
//- Make sure the copy commands finished executing.
-
//- Update appropriate descriptors to point to the new places.
-
res = vmaEndDefragmentationPass(allocator, defragCtx, &pass);
-
if(res == VK_SUCCESS)
-
break;
-
else if(res != VK_INCOMPLETE)
-
// Handle error...
+
// Inspect pass.pMoves[i].srcAllocation, identify what buffer/image it represents.
+
VmaAllocationInfo allocInfo;
+
vmaGetAllocationInfo(allocator, pMoves[i].srcAllocation, &allocInfo);
+
MyEngineResourceData* resData = (MyEngineResourceData*)allocInfo.pUserData;
+
+
// Recreate and bind this buffer/image at: pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset.
+
VkImageCreateInfo imgCreateInfo = ...
+
VkImage newImg;
+
res = vkCreateImage(device, &imgCreateInfo, nullptr, &newImg);
+
// Check res...
+
res = vKBindImageMemory(device, newImg, pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset);
+
// Check res...
+
+
// Issue a vkCmdCopyBuffer/vkCmdCopyImage to copy its content to the new place.
+
vkCmdCopyImage(cmdBuf, resData->img, ..., newImg, ...);
}
-
else
+
+
// Make sure the copy commands finished executing.
+
vkWaitForFences(...);
+
+
// Destroy old buffers/images bound with pass.pMoves[i].srcAllocation.
+
for(uint32_t i = 0; i < pass.moveCount; ++i)
+
{
+
// ...
+
vkDestroyImage(device, resData->img, nullptr);
+
}
+
+
// Update appropriate descriptors to point to the new places...
+
+
res = vmaEndDefragmentationPass(allocator, defragCtx, &pass);
+
if(res == VK_SUCCESS)
+
break;
+
else if(res != VK_INCOMPLETE)
// Handle error...
}
-
vmaEndDefragmentation(allocator, defragCtx, nullptr);
-
VkResult vmaEndDefragmentation(VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationStats *pStats)
Ends defragmentation process.
+
vmaEndDefragmentation(allocator, defragCtx, nullptr);
+
void vmaEndDefragmentation(VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationStats *pStats)
Ends defragmentation process.
+
void vmaGetAllocationInfo(VmaAllocator allocator, VmaAllocation allocation, VmaAllocationInfo *pAllocationInfo)
Returns current information about specified allocation.
VkResult vmaBeginDefragmentationPass(VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationPassMoveInfo *pPassInfo)
Starts single defragmentation pass.
VkResult vmaBeginDefragmentation(VmaAllocator allocator, const VmaDefragmentationInfo *pInfo, VmaDefragmentationContext *pContext)
Begins defragmentation process.
VkResult vmaEndDefragmentationPass(VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationPassMoveInfo *pPassInfo)
Ends single defragmentation pass.
@ VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT
Definition: vk_mem_alloc.h:707
+
Parameters of VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().
Definition: vk_mem_alloc.h:1338
+
void * pUserData
Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vma...
Definition: vk_mem_alloc.h:1385
An opaque object that represents started defragmentation process.
Parameters for defragmentation.
Definition: vk_mem_alloc.h:1401
VmaPool pool
Custom pool to be defragmented.
Definition: vk_mem_alloc.h:1408
VmaDefragmentationFlags flags
Use combination of VmaDefragmentationFlagBits.
Definition: vk_mem_alloc.h:1403
+
VkDeviceMemory dstMemory
Destination memory block where the allocation should be moved.
Definition: vk_mem_alloc.h:1429
+
VkDeviceSize dstOffset
Destination offset where the allocation should be moved.
Definition: vk_mem_alloc.h:1431
Parameters for incremental defragmentation steps.
Definition: vk_mem_alloc.h:1441
uint32_t moveCount
Number of elements in the pMoves array.
Definition: vk_mem_alloc.h:1443
-

You can defragment a specific custom pool by setting VmaDefragmentationInfo::pool (like in the example above) or all the default pools by setting this member to null.

+
VmaDefragmentationMove * pMoves
Array of moves to be performed by the user in the current defragmentation pass.
Definition: vk_mem_alloc.h:1467
+

Although functions like vmaCreateBuffer(), vmaCreateImage(), vmaDestroyBuffer(), vmaDestroyImage() create/destroy an allocation and a buffer/image at once, these are just a shortcut for creating the resource, allocating memory, and binding them together. Defragmentation works on memory allocations only. You must handle the rest manually. Defragmentation is an iterative process that should repreat "passes" as long as related functions return VK_INCOMPLETE not VK_SUCCESS. In each pass:

+
    +
  1. vmaBeginDefragmentationPass() function call:
      +
    • Calculates and returns the list of allocations to be moved in this pass. Note this can be a time-consuming process.
    • +
    • Reserves destination memory for them by creating internal allocations. Returns their VkDeviceMemory + offset.
    • +
    +
  2. +
  3. Inside the pass, you should:
      +
    • Inspect the returned list of allocations to be moved.
    • +
    • Create new buffers/images and bind them at the returned destination VkDeviceMemory + offset.
    • +
    • Copy data from source to destination resources if necessary.
    • +
    • Destroy the source buffers/images, but NOT their allocations.
    • +
    +
  4. +
  5. vmaEndDefragmentationPass() function call:
      +
    • Frees the source memory reserved for the allocations that are moved.
    • +
    • Modifies VmaAllocation objects that are moved to point to the destination reserved memory.
    • +
    • Frees VkDeviceMemory blocks that became empty.
    • +
    +
  6. +

Unlike in previous iterations of the defragmentation API, there is no list of "movable" allocations passed as a parameter. Defragmentation algorithm tries to move all suitable allocations. You can, however, refuse to move some of them inside a defragmentation pass, by setting pass.pMoves[i].operation to VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE. This is not recommended and may result in suboptimal packing of the allocations after defragmentation. If you cannot ensure any allocation can be moved, it is better to keep movable allocations separate in a custom pool.

-

You can also decide to destroy an allocation instead of moving it. You should then set pass.pMoves[i].operation to VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY.

+

Inside a pass, for each allocation that should be moved:

+ +

You can defragment a specific custom pool by setting VmaDefragmentationInfo::pool (like in the example above) or all the default pools by setting this member to null.

+

Defragmentation is always performed in each pool separately. Allocations are never moved between different Vulkan memory types. The size of the destination memory reserved for a moved allocation is the same as the original one. Alignment of an allocation as it was determined using vkGetBufferMemoryRequirements() etc. is also respected after defragmentation. Buffers/images should be recreated with the same VkBufferCreateInfo / VkImageCreateInfo parameters as the original ones.

You can perform the defragmentation incrementally to limit the number of allocations and bytes to be moved in each pass, e.g. to call it in sync with render frames and not to experience too big hitches. See members: VmaDefragmentationInfo::maxBytesPerPass, VmaDefragmentationInfo::maxAllocationsPerPass.

It is also safe to perform the defragmentation asynchronously to render frames and other Vulkan and VMA usage, possibly from multiple threads, with the exception that allocations returned in VmaDefragmentationPassMoveInfo::pMoves shouldn't be destroyed until the defragmentation pass is ended.

Note
Defragmentation is not supported in custom pools created with VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT.
diff --git a/docs/html/globals.html b/docs/html/globals.html index af9f5b6..29b0229 100644 --- a/docs/html/globals.html +++ b/docs/html/globals.html @@ -185,7 +185,7 @@ $(function() {
  • vmaDestroyVirtualBlock() : vk_mem_alloc.h
  • VmaDetailedStatistics : vk_mem_alloc.h
  • VmaDeviceMemoryCallbacks : vk_mem_alloc.h
  • -
  • vmaEndDefragmentation() : vk_mem_alloc.h
  • +
  • vmaEndDefragmentation() : vk_mem_alloc.h
  • vmaEndDefragmentationPass() : vk_mem_alloc.h
  • vmaFindMemoryTypeIndex() : vk_mem_alloc.h
  • vmaFindMemoryTypeIndexForBufferInfo() : vk_mem_alloc.h
  • diff --git a/docs/html/globals_func.html b/docs/html/globals_func.html index 36108da..e9f54e2 100644 --- a/docs/html/globals_func.html +++ b/docs/html/globals_func.html @@ -95,7 +95,7 @@ $(function() {
  • vmaDestroyImage() : vk_mem_alloc.h
  • vmaDestroyPool() : vk_mem_alloc.h
  • vmaDestroyVirtualBlock() : vk_mem_alloc.h
  • -
  • vmaEndDefragmentation() : vk_mem_alloc.h
  • +
  • vmaEndDefragmentation() : vk_mem_alloc.h
  • vmaEndDefragmentationPass() : vk_mem_alloc.h
  • vmaFindMemoryTypeIndex() : vk_mem_alloc.h
  • vmaFindMemoryTypeIndexForBufferInfo() : vk_mem_alloc.h
  • diff --git a/docs/html/group__group__alloc.html b/docs/html/group__group__alloc.html index 73a91e2..719170e 100644 --- a/docs/html/group__group__alloc.html +++ b/docs/html/group__group__alloc.html @@ -95,7 +95,7 @@ Classes  Parameters for incremental defragmentation steps. More...
      struct  VmaDefragmentationStats - Statistics returned for defragmentation process in function vmaEndDefragmentation(). More...
    + Statistics returned for defragmentation process in function vmaEndDefragmentation(). More...
      struct  VmaPool  Represents custom memory pool. More...
    @@ -152,7 +152,7 @@ Typedefs  Parameters for incremental defragmentation steps. More...
      typedef struct VmaDefragmentationStats VmaDefragmentationStats - Statistics returned for defragmentation process in function vmaEndDefragmentation(). More...
    + Statistics returned for defragmentation process in function vmaEndDefragmentation(). More...
      - - - + + + @@ -525,7 +525,7 @@ Functions

    @@ -310,9 +310,9 @@ Functions

    VkResult vmaBeginDefragmentation (VmaAllocator allocator, const VmaDefragmentationInfo *pInfo, VmaDefragmentationContext *pContext)
     Begins defragmentation process. More...
     
    VkResult vmaEndDefragmentation (VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationStats *pStats)
     Ends defragmentation process. More...
     
    void vmaEndDefragmentation (VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationStats *pStats)
     Ends defragmentation process. More...
     
    VkResult vmaBeginDefragmentationPass (VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationPassMoveInfo *pPassInfo)
     Starts single defragmentation pass. More...
     
    -

    Statistics returned for defragmentation process in function vmaEndDefragmentation().

    +

    Statistics returned for defragmentation process in function vmaEndDefragmentation().

    @@ -1087,7 +1087,7 @@ Functions - +
    allocatorAllocator object.
    pInfoStructure filled with parameters of defragmentation.
    [out]pContextContext object that must be passed to vmaEndDefragmentation() to finish defragmentation.
    [out]pContextContext object that must be passed to vmaEndDefragmentation() to finish defragmentation.
    @@ -1773,14 +1773,14 @@ Functions - -

    ◆ vmaEndDefragmentation()

    + +

    ◆ vmaEndDefragmentation()

    - + diff --git a/docs/html/group__group__init.html b/docs/html/group__group__init.html index 1ab6ae8..411ae7c 100644 --- a/docs/html/group__group__init.html +++ b/docs/html/group__group__init.html @@ -98,7 +98,7 @@ Typedefs - + @@ -221,7 +221,7 @@ Functions
    VkResult vmaEndDefragmentation void vmaEndDefragmentation ( VmaAllocator  allocator,
     Flags for created VmaAllocator. More...
     
    typedef VkFlags VmaAllocatorCreateFlags
     See #VmaAllocatorCreateFlagBigs. More...
     See VmaAllocatorCreateFlagBits. More...
     
    typedef void(VKAPI_PTR * PFN_vmaAllocateDeviceMemoryFunction) (VmaAllocator allocator, uint32_t memoryType, VkDeviceMemory memory, VkDeviceSize size, void *pUserData)
     Callback function called after successful vkAllocateMemory. More...
    -

    See #VmaAllocatorCreateFlagBigs.

    +

    See VmaAllocatorCreateFlagBits.

    diff --git a/docs/html/search/all_11.js b/docs/html/search/all_11.js index df54bf0..223e908 100644 --- a/docs/html/search/all_11.js +++ b/docs/html/search/all_11.js @@ -148,7 +148,7 @@ var searchData= ['vmadestroyvirtualblock_145',['vmaDestroyVirtualBlock',['../group__group__virtual.html#ga3795f7783ae2c182cede067d656f66a5',1,'vk_mem_alloc.h']]], ['vmadetailedstatistics_146',['VmaDetailedStatistics',['../struct_vma_detailed_statistics.html',1,'VmaDetailedStatistics'],['../group__group__stats.html#ga9ab0c535a6ca655dc63b8609ab4b8394',1,'VmaDetailedStatistics(): vk_mem_alloc.h']]], ['vmadevicememorycallbacks_147',['VmaDeviceMemoryCallbacks',['../struct_vma_device_memory_callbacks.html',1,'VmaDeviceMemoryCallbacks'],['../group__group__init.html#ga77692d3c8770ea8882d573206bd27b2b',1,'VmaDeviceMemoryCallbacks(): vk_mem_alloc.h']]], - ['vmaenddefragmentation_148',['vmaEndDefragmentation',['../group__group__alloc.html#ga729a594b45ae1681096940a44f3eb174',1,'vk_mem_alloc.h']]], + ['vmaenddefragmentation_148',['vmaEndDefragmentation',['../group__group__alloc.html#ga59f01ca3d53d50b7cca9b442b77a3e87',1,'vk_mem_alloc.h']]], ['vmaenddefragmentationpass_149',['vmaEndDefragmentationPass',['../group__group__alloc.html#gaded05a445742a00718ee766144c5c226',1,'vk_mem_alloc.h']]], ['vmafindmemorytypeindex_150',['vmaFindMemoryTypeIndex',['../group__group__alloc.html#gaef15a94b58fbcb0fe706d5720e84a74a',1,'vk_mem_alloc.h']]], ['vmafindmemorytypeindexforbufferinfo_151',['vmaFindMemoryTypeIndexForBufferInfo',['../group__group__alloc.html#gae790ab9ffaf7667fb8f62523e6897888',1,'vk_mem_alloc.h']]], diff --git a/docs/html/search/functions_0.js b/docs/html/search/functions_0.js index d2633bd..b71cc15 100644 --- a/docs/html/search/functions_0.js +++ b/docs/html/search/functions_0.js @@ -30,7 +30,7 @@ var searchData= ['vmadestroyimage_27',['vmaDestroyImage',['../group__group__alloc.html#gae50d2cb3b4a3bfd4dd40987234e50e7e',1,'vk_mem_alloc.h']]], ['vmadestroypool_28',['vmaDestroyPool',['../group__group__alloc.html#ga5485779c8f1948238fc4e92232fa65e1',1,'vk_mem_alloc.h']]], ['vmadestroyvirtualblock_29',['vmaDestroyVirtualBlock',['../group__group__virtual.html#ga3795f7783ae2c182cede067d656f66a5',1,'vk_mem_alloc.h']]], - ['vmaenddefragmentation_30',['vmaEndDefragmentation',['../group__group__alloc.html#ga729a594b45ae1681096940a44f3eb174',1,'vk_mem_alloc.h']]], + ['vmaenddefragmentation_30',['vmaEndDefragmentation',['../group__group__alloc.html#ga59f01ca3d53d50b7cca9b442b77a3e87',1,'vk_mem_alloc.h']]], ['vmaenddefragmentationpass_31',['vmaEndDefragmentationPass',['../group__group__alloc.html#gaded05a445742a00718ee766144c5c226',1,'vk_mem_alloc.h']]], ['vmafindmemorytypeindex_32',['vmaFindMemoryTypeIndex',['../group__group__alloc.html#gaef15a94b58fbcb0fe706d5720e84a74a',1,'vk_mem_alloc.h']]], ['vmafindmemorytypeindexforbufferinfo_33',['vmaFindMemoryTypeIndexForBufferInfo',['../group__group__alloc.html#gae790ab9ffaf7667fb8f62523e6897888',1,'vk_mem_alloc.h']]], diff --git a/docs/html/struct_vma_allocation_info.html b/docs/html/struct_vma_allocation_info.html index 5ed38f0..96fb9d7 100644 --- a/docs/html/struct_vma_allocation_info.html +++ b/docs/html/struct_vma_allocation_info.html @@ -184,7 +184,7 @@ Public Attributes

    Custom allocation name that was set with vmaSetAllocationName().

    It can change after call to vmaSetAllocationName() for this allocation.

    -

    Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with additional flag VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED].

    +

    Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with additional flag VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED].

    diff --git a/docs/html/struct_vma_defragmentation_context.html b/docs/html/struct_vma_defragmentation_context.html index fee98aa..0a9f27e 100644 --- a/docs/html/struct_vma_defragmentation_context.html +++ b/docs/html/struct_vma_defragmentation_context.html @@ -70,7 +70,7 @@ $(function() { More...

    Detailed Description

    An opaque object that represents started defragmentation process.

    -

    Fill structure VmaDefragmentationInfo and call function vmaBeginDefragmentation() to create it. Call function vmaEndDefragmentation() to destroy it.

    +

    Fill structure VmaDefragmentationInfo and call function vmaBeginDefragmentation() to create it. Call function vmaEndDefragmentation() to destroy it.


    The documentation for this struct was generated from the following file: diff --git a/docs/html/struct_vma_defragmentation_stats.html b/docs/html/struct_vma_defragmentation_stats.html index 86d9c11..1eba434 100644 --- a/docs/html/struct_vma_defragmentation_stats.html +++ b/docs/html/struct_vma_defragmentation_stats.html @@ -69,7 +69,7 @@ $(function() {
    -

    Statistics returned for defragmentation process in function vmaEndDefragmentation(). +

    Statistics returned for defragmentation process in function vmaEndDefragmentation(). More...

    @@ -88,7 +88,7 @@ Public Attributes

     

    Detailed Description

    -

    Statistics returned for defragmentation process in function vmaEndDefragmentation().

    +

    Statistics returned for defragmentation process in function vmaEndDefragmentation().

    Member Data Documentation

    ◆ allocationsMoved

    diff --git a/docs/html/vk__mem__alloc_8h.html b/docs/html/vk__mem__alloc_8h.html index 86c5415..2228030 100644 --- a/docs/html/vk__mem__alloc_8h.html +++ b/docs/html/vk__mem__alloc_8h.html @@ -122,7 +122,7 @@ Classes  Parameters for incremental defragmentation steps. More...
      struct  VmaDefragmentationStats - Statistics returned for defragmentation process in function vmaEndDefragmentation(). More...
    + Statistics returned for defragmentation process in function vmaEndDefragmentation(). More...
      struct  VmaVirtualBlockCreateInfo  Parameters of created VmaVirtualBlock object to be passed to vmaCreateVirtualBlock(). More...
    @@ -153,7 +153,7 @@ Typedefs  Flags for created VmaAllocator. More...
      typedef VkFlags VmaAllocatorCreateFlags - See #VmaAllocatorCreateFlagBigs. More...
    + See VmaAllocatorCreateFlagBits. More...
      typedef enum VmaMemoryUsage VmaMemoryUsage  Intended usage of the allocated memory. More...
    @@ -240,7 +240,7 @@ Typedefs  Parameters for incremental defragmentation steps. More...
      typedef struct VmaDefragmentationStats VmaDefragmentationStats - Statistics returned for defragmentation process in function vmaEndDefragmentation(). More...
    + Statistics returned for defragmentation process in function vmaEndDefragmentation(). More...
      typedef struct VmaVirtualBlockCreateInfo VmaVirtualBlockCreateInfo  Parameters of created VmaVirtualBlock object to be passed to vmaCreateVirtualBlock(). More...
    @@ -472,9 +472,9 @@ Functions VkResult vmaBeginDefragmentation (VmaAllocator allocator, const VmaDefragmentationInfo *pInfo, VmaDefragmentationContext *pContext)  Begins defragmentation process. More...
      -VkResult vmaEndDefragmentation (VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationStats *pStats) - Ends defragmentation process. More...
    -  +void vmaEndDefragmentation (VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationStats *pStats) + Ends defragmentation process. More...
    +  VkResult vmaBeginDefragmentationPass (VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationPassMoveInfo *pPassInfo)  Starts single defragmentation pass. More...
      diff --git a/include/vk_mem_alloc.h b/include/vk_mem_alloc.h index a841483..b246f71 100644 --- a/include/vk_mem_alloc.h +++ b/include/vk_mem_alloc.h @@ -426,7 +426,7 @@ typedef enum VmaAllocatorCreateFlagBits VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VmaAllocatorCreateFlagBits; -/// See #VmaAllocatorCreateFlagBigs. +/// See #VmaAllocatorCreateFlagBits. typedef VkFlags VmaAllocatorCreateFlags; /** @} */ @@ -1388,7 +1388,7 @@ typedef struct VmaAllocationInfo It can change after call to vmaSetAllocationName() for this allocation. Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with - additional flag VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED]. + additional flag #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED]. */ const char* VMA_NULLABLE pName; } VmaAllocationInfo; @@ -18267,31 +18267,72 @@ for(;;) res = vmaBeginDefragmentationPass(allocator, defragCtx, &pass); if(res == VK_SUCCESS) break; - else if(res == VK_INCOMPLETE) + else if(res != VK_INCOMPLETE) + // Handle error... + + for(uint32_t i = 0; i < pass.moveCount; ++i) { - for(uint32_t i = 0; i < pass.moveCount; ++i) - { - //- Inspect pass.pMoves[i].srcAllocation, identify what buffer or image it represents. - //- Recreate and bind this buffer or image at pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset. - //- Issue a vkCmdCopyBuffer/vkCmdCopyImage to copy its content to the new place. - } - //- Make sure the copy commands finished executing. - //- Update appropriate descriptors to point to the new places. - res = vmaEndDefragmentationPass(allocator, defragCtx, &pass); - if(res == VK_SUCCESS) - break; - else if(res != VK_INCOMPLETE) - // Handle error... + // Inspect pass.pMoves[i].srcAllocation, identify what buffer/image it represents. + VmaAllocationInfo allocInfo; + vmaGetAllocationInfo(allocator, pMoves[i].srcAllocation, &allocInfo); + MyEngineResourceData* resData = (MyEngineResourceData*)allocInfo.pUserData; + + // Recreate and bind this buffer/image at: pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset. + VkImageCreateInfo imgCreateInfo = ... + VkImage newImg; + res = vkCreateImage(device, &imgCreateInfo, nullptr, &newImg); + // Check res... + res = vKBindImageMemory(device, newImg, pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset); + // Check res... + + // Issue a vkCmdCopyBuffer/vkCmdCopyImage to copy its content to the new place. + vkCmdCopyImage(cmdBuf, resData->img, ..., newImg, ...); } - else + + // Make sure the copy commands finished executing. + vkWaitForFences(...); + + // Destroy old buffers/images bound with pass.pMoves[i].srcAllocation. + for(uint32_t i = 0; i < pass.moveCount; ++i) + { + // ... + vkDestroyImage(device, resData->img, nullptr); + } + + // Update appropriate descriptors to point to the new places... + + res = vmaEndDefragmentationPass(allocator, defragCtx, &pass); + if(res == VK_SUCCESS) + break; + else if(res != VK_INCOMPLETE) // Handle error... } vmaEndDefragmentation(allocator, defragCtx, nullptr); \endcode -You can defragment a specific custom pool by setting VmaDefragmentationInfo::pool -(like in the example above) or all the default pools by setting this member to null. +Although functions like vmaCreateBuffer(), vmaCreateImage(), vmaDestroyBuffer(), vmaDestroyImage() +create/destroy an allocation and a buffer/image at once, these are just a shortcut for +creating the resource, allocating memory, and binding them together. +Defragmentation works on memory allocations only. You must handle the rest manually. +Defragmentation is an iterative process that should repreat "passes" as long as related functions +return `VK_INCOMPLETE` not `VK_SUCCESS`. +In each pass: + +1. vmaBeginDefragmentationPass() function call: + - Calculates and returns the list of allocations to be moved in this pass. + Note this can be a time-consuming process. + - Reserves destination memory for them by creating internal allocations. + Returns their `VkDeviceMemory` + offset. +2. Inside the pass, **you should**: + - Inspect the returned list of allocations to be moved. + - Create new buffers/images and bind them at the returned destination `VkDeviceMemory` + offset. + - Copy data from source to destination resources if necessary. + - Destroy the source buffers/images, but NOT their allocations. +3. vmaEndDefragmentationPass() function call: + - Frees the source memory reserved for the allocations that are moved. + - Modifies #VmaAllocation objects that are moved to point to the destination reserved memory. + - Frees `VkDeviceMemory` blocks that became empty. Unlike in previous iterations of the defragmentation API, there is no list of "movable" allocations passed as a parameter. Defragmentation algorithm tries to move all suitable allocations. @@ -18300,8 +18341,31 @@ You can, however, refuse to move some of them inside a defragmentation pass, by This is not recommended and may result in suboptimal packing of the allocations after defragmentation. If you cannot ensure any allocation can be moved, it is better to keep movable allocations separate in a custom pool. -You can also decide to destroy an allocation instead of moving it. -You should then set `pass.pMoves[i].operation` to #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY. +Inside a pass, for each allocation that should be moved: + +- You should copy its data from the source to the destination place by calling e.g. `vkCmdCopyBuffer()`, `vkCmdCopyImage()`. + - You need to make sure these commands finished executing before destroying the source buffers/images and before calling vmaEndDefragmentationPass(). +- If a resource doesn't contain any meaningful data, e.g. it is a transient color attachment image to be cleared, + filled, and used temporarily in each rendering frame, you can just recreate this image + without copying its data. +- If the resource is in `HOST_VISIBLE` and `HOST_COHERENT` memory, you can copy its data on the CPU + using `memcpy()`. +- If you cannot move the allocation, you can set `pass.pMoves[i].operation` to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE. + This will cancel the move. + - vmaEndDefragmentationPass() will then free the destination memory + not the source memory of the allocation, leaving it unchanged. +- If you decide the allocation is unimportant and can be destroyed instead of moved (e.g. it wasn't used for long time), + you can set `pass.pMoves[i].operation` to #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY. + - vmaEndDefragmentationPass() will then free both source and destination memory, and will destroy the #VmaAllocation object. + +You can defragment a specific custom pool by setting VmaDefragmentationInfo::pool +(like in the example above) or all the default pools by setting this member to null. + +Defragmentation is always performed in each pool separately. +Allocations are never moved between different Vulkan memory types. +The size of the destination memory reserved for a moved allocation is the same as the original one. +Alignment of an allocation as it was determined using `vkGetBufferMemoryRequirements()` etc. is also respected after defragmentation. +Buffers/images should be recreated with the same `VkBufferCreateInfo` / `VkImageCreateInfo` parameters as the original ones. You can perform the defragmentation incrementally to limit the number of allocations and bytes to be moved in each pass, e.g. to call it in sync with render frames and not to experience too big hitches. @@ -18385,6 +18449,8 @@ To do that, fill VmaAllocationCreateInfo::pUserData field when creating an allocation. It is an opaque `void*` pointer. You can use it e.g. as a pointer, some handle, index, key, ordinal number or any other value that would associate the allocation with your custom metadata. +It it useful to identify appropriate data structures in your engine given #VmaAllocation, +e.g. when doing \ref defragmentation. \code VkBufferCreateInfo bufCreateInfo = ... @@ -18415,44 +18481,21 @@ vmaBuildStatsString() in hexadecimal form. \section allocation_names Allocation names -There is alternative mode available where `pUserData` pointer is used to point to -a null-terminated string, giving a name to the allocation. To use this mode, -set #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT flag in VmaAllocationCreateInfo::flags. -Then `pUserData` passed as VmaAllocationCreateInfo::pUserData or argument to -vmaSetAllocationUserData() must be either null or a pointer to a null-terminated string. +An allocation can also carry a null-terminated string, giving a name to the allocation. +To set it, call vmaSetAllocationName(). The library creates internal copy of the string, so the pointer you pass doesn't need to be valid for whole lifetime of the allocation. You can free it after the call. \code -VkImageCreateInfo imageInfo = ... - std::string imageName = "Texture: "; imageName += fileName; - -VmaAllocationCreateInfo allocCreateInfo = {}; -allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; -allocCreateInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT; -allocCreateInfo.pUserData = imageName.c_str(); - -VkImage image; -VmaAllocation allocation; -vmaCreateImage(allocator, &imageInfo, &allocCreateInfo, &image, &allocation, nullptr); +vmaSetAllocationName(allocator, allocation, imageName.c_str()); \endcode -The value of `pUserData` pointer of the allocation will be different than the one -you passed when setting allocation's name - pointing to a buffer managed -internally that holds copy of the string. +The string can be later retrieved by inspecting VmaAllocationInfo::pName. +It is also printed in JSON report created by vmaBuildStatsString(). -\code -VmaAllocationInfo allocInfo; -vmaGetAllocationInfo(allocator, allocation, &allocInfo); -const char* imageName = (const char*)allocInfo.pUserData; -printf("Image name: %s\n", imageName); -\endcode - -That string is also printed in JSON report created by vmaBuildStatsString(). - -\note Passing string name to VMA allocation doesn't automatically set it to the Vulkan buffer or image created with it. +\note Setting string name to VMA allocation doesn't automatically set it to the Vulkan buffer or image created with it. You must do it manually using an extension like VK_EXT_debug_utils, which is independent of this library.