Vulkan系列教程—VMA教程—虚拟分配器
Posted 赵新政
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vulkan系列教程—VMA教程—虚拟分配器相关的知识,希望对你有一定的参考价值。
文章目录
- 前言
- Virtual Allocator
- 一、生成Virtual Block
- 二、分配Virtual Allocation
- 三、内存释放(Deallocation)
- 四、分配携带参数(Allocation parameters)
- 五、内存对齐与单位(Alignment and units)
- 六、静态信息(Statistics)
- 七、额外考量(Additional considerations)
- 总结
前言
本文为Vulkan® Memory Allocator系列系列教程,定时更新,请大家关注。如果需要深入学习Vulkan的同学,可以点击课程链接,学习链接
Vulkan学习群:594715138
CSDN课程链接:《Vulkan原理与实战—铸造渲染核武器—基石篇》
Virtual Allocator
VMA有一个额外的特性,其核心的分配算法通过一套叫做“Virtual Allocator”来导出给用户使用。这个功能是说,通常使用VMA我们都碰不到Pool当中的内存块儿(blocks),但是现在我们可以独立一块block进行操作了。当然,这样的内存块你可以拿来做各种需求,甚至跟Vulkan无关。
一、生成Virtual Block
为了使用这个功能,VMA并没有给到我们一个Allocator这样的对象。我们所需要做的就是创建一个单独的VmaVirtualBlock来代表(管理)我们想创建的每一个内存块(block)。
- 填写 VmaVirtualBlockCreateInfo结构体。
- 调用 vmaCreateVirtualBlock()来创建新的VmaVirtualBlock对象。
代码如下(示例):
VmaVirtualBlockCreateInfo blockCreateInfo = ;
blockCreateInfo.size = 1048576; // 1 MB
VmaVirtualBlock block;
VkResult res = vmaCreateVirtualBlock(&blockCreateInfo, &block);
二、分配Virtual Allocation
VmaVirtualBlock这个结构体,内部会追踪其分配出去的内存(Occupied Regions)与空闲的内存(Free Region),它与VMA核心的Allocator使用的是同一套分配代码。当你需要分配一个Allocation的时候,传入一个VkDeviceSize参数引用,这个量会被用作Offset(相对于当前这个Block)。
为了创建这样一个Allocation,我们需要:
- 填写 VmaVirtualAllocationCreateInfo结构体。
- 调用 vmaVirtualAllocate()函数。从其中获得VkDeviceSize offset作为本Allocation的起点。
代码如下(示例):
VmaVirtualAllocationCreateInfo allocCreateInfo = ;
allocCreateInfo.size = 4096; // 4 KB
VkDeviceSize allocOffset;
res = vmaVirtualAllocate(block, &allocCreateInfo, &allocOffset);
if(res == VK_SUCCESS)
// Use the 4 KB of your memory starting at allocOffset.
else
// Allocation failed - no space for it could be found. Handle this error!
三、内存释放(Deallocation)
当Allocation不再需要的时候,我们可以调用vmaVirtualFree()来释放内存。你只能够将需要释放的Offset传入(这个Offset就代表了这块内存了)。
当整个Block都不再需要了,你可以通过调用vmaDestroyVirtualBlock()来释放整个Block。但是你必须在释放Block之前,先将每一个Allocation都释放掉。如果你不想一个个手动释放Allocation,那就需要调用 vmaClearVirtualBlock()来释放本Block当中的所有Allocation(这个特性在普通的VMA分配器中是没有的)。
代码如下(示例):
vmaVirtualFree(block, allocOffset);
vmaDestroyVirtualBlock(block)
四、分配携带参数(Allocation parameters)
你可以使用vmaSetVirtualAllocationUserData()来向已经分配的Allocation中设置用户参数。其默认的参数是null。与之前讲过的用户参数相同,它可以被传入各种各样的用户信息。
代码如下(示例):
struct CustomAllocData
std::string m_AllocName;
;
CustomAllocData* allocData = new CustomAllocData();
allocData->m_AllocName = "My allocation 1";
vmaSetVirtualAllocationUserData(block, allocOffset, allocData);
这个指针可以在后面被获取到,通过调用 vmaGetVirtualAllocationInfo(),相关信息会被填写到 VmaVirtualAllocationInfo这个结构当中。注意!当你新new了一个对象,把它传进去作为用户参数,可别忘了在Allocation被释放后,手动释放自己的这块对象内存哦。
代码如下(示例):
VmaVirtualAllocationInfo allocInfo;
vmaGetVirtualAllocationInfo(block, allocOffset, &allocInfo);
delete (CustomAllocData*)allocInfo.pUserData;
vmaVirtualFree(block, allocOffset);
五、内存对齐与单位(Alignment and units)
使用Bytes(字节)来作为Size跟Offset的单位,看上去很自然。如果有一个Allocation,需要被对齐到一个数字上(比如4Byte),你可以使用一个可选参数来设置,即 VmaVirtualAllocationCreateInfo::alignment 。
代码如下(示例):
VmaVirtualAllocationCreateInfo allocCreateInfo = ;
allocCreateInfo.size = 4096; // 4 KB
allocCreateInfo.alignment = 4; // Returned offset must be a multiply of 4 B
VkDeviceSize allocOffset;
res = vmaVirtualAllocate(block, &allocCreateInfo, &allocOffset);
六、静态信息(Statistics)
你可以通过 vmaCalculateVirtualBlockStats()来获取一个Block的静态信息。这个函数会填充 VmaStatInfo这个结构体—就像VMA通常使用的一样。
代码如下(示例):
VmaStatInfo statInfo;
vmaCalculateVirtualBlockStats(block, &statInfo);
printf("My virtual block has %llu bytes used by %u virtual allocations\\n",
statInfo.usedBytes, statInfo.allocationCount);
你也可以通过vmaBuildVirtualBlockStatsString()获取到一个Block的所有信息,并且以JSON形式给到。拿到的String必须在后面通过 vmaFreeVirtualBlockStatsString()释放掉。
七、额外考量(Additional considerations)
“Virtual Allocator”这一组功能,是在一个单独的Block上操作的。用户需要自己维护所有的Blocks,当一个Block不足够分配的时候还需要做新的Block,删除空白的Block以及决策一个新的Allocation分配到底优先选取哪一个Block。
系统也给到了一些可选的分配算法,就好像用户自定义内存池里面讲述的。你可以在 VmaVirtualBlockCreateFlagBits 里面找到各种Flags。你可以在Custom Memory Pool(用户自定义内存池)这一章找到算法解释。
总结
以上就是今天的内容,大家对于vulkan的学习,也可以参考我出品的vulkan系列教程,下面给大家贴出链接。
请大家移步CSDN站内进行学习:
CSDN课程链接:《Vulkan原理与实战—铸造渲染核武器—基石篇》
以上是关于Vulkan系列教程—VMA教程—虚拟分配器的主要内容,如果未能解决你的问题,请参考以下文章