Vulkan® Memory Allocator (VMA)技术剖析计划

2020/10/14 在文章最后增加了一条Vulkan内存分配信息

2020/10/15 修改原先说明当使用Vulkan 1.2时VMA的行为

2020/10/20 修改结构图,增加VmaDeviceMemoryBlock、VmaBlockMetadata和VmaBlockMetadata_Generic类的结构图


目前正在使用Vulkan搭建引擎,目前处于起步阶段,打算写得差不多了开源出来。当设计VkBuffer、VkImage和VkMemory时当时考虑到自己写一个内存管理分配器,手里也没有什么好的参考材料,查阅Vulkan资料时偶然之间查阅到AMD公司有一个开源的Vulkan内存管理项目:Vulkan® Memory Allocator (VMA)就打算研究研究并将其加入到引擎中,顺便将研究结果分享一下,目前还在同步研究中。


目前VMA并没有包括Vulkan中所有的内存相关操作,比如Transfer,导入导出外部内存等。VMA实现了最常见的内存相关管理。

VMA的在线文档可能要梯子(我是没打开),你可以从VMA的Github中获取文档。

VMA文档说最新版本的VMA支持Vulkan1.0和Vulkan 1.1,我看了一下源码Vulkan1.2也行(内部用的Vulkan1.1,Vulkan1.2内存标准没啥变化)

说明:

1.(修改“Vulkan1.2内存标准没啥变化”这句话)当使用Vulkan 1.2时在创建 VmaAllocator 时可以使用 VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT 用于指定VMA内部获取设备内存地址。VMA内部其实是使用在低于Vulkan 1.1版本为扩展而Vulkan 1.2中成为核心标准的 VK_KHR_buffer_device_address扩展,Vulkan 1.2 标准中为调用如下函数获取:

// Provided by VK_VERSION_1_2
uint64_t vkGetDeviceMemoryOpaqueCaptureAddress(
    VkDevice                                    device,
    const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo
);

如果在创建VmaAllocator时传入的 VmaAllocatorCreateInfo::vulkanApiVersion 为Vulkan 1.2 版本的话,如果你使用的Vulkan版本小于Vulkan 1.2的话(该版本为vulkan_core.h中声明的Vulkan版本),不出意外会收到异常提示框,该异常的断言在VmaAllocator的构造函数内定义如下:

#if VMA_VULKAN_VERSION < 1002000
    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 2, 0))
    {
        VMA_ASSERT(0 && "vulkanApiVersion >= VK_API_VERSION_1_2 but required Vulkan version is disabled by preprocessor macros.");
    }
#endif

VMA_VULKAN_VERSION 的声明如下:

#if !defined(VMA_VULKAN_VERSION)
    #if defined(VK_VERSION_1_2)
        #define VMA_VULKAN_VERSION 1002000
    #elif defined(VK_VERSION_1_1)
        #define VMA_VULKAN_VERSION 1001000
    #else
        #define VMA_VULKAN_VERSION 1000000
    #endif
#endif

 


相关资料:

AMD Vulkan 官网

Vulkan Memory Allocator(VMA)

侯捷 C++内存管理 从平地到万丈高楼

 

AMD 还写了DX12的内存管理项目(真贴心)

D3D12 Memory Allocator (D3D12MA)


由于内存管理算是一个复杂的问题,如果感觉自己对于内存分配之类的掌握比较薄弱的话推荐先看一遍侯捷 C++内存管理 从平地到万丈高楼。有关很多内存管理共性,比如union、定点内存分配之类的话题讲的很清楚(不得不说侯捷老师真是太牛逼了)。


目前画了个结构图,仅供参考。

VMA结构图

  • VkDeviceMemory在VmaDeviceMemoryBlock中
  • 在VMA中要进行内存分配(GPU端的分配),在经过一系列分配筛选后最后会落入如下函数中
VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory)
{
    /*...*/
    // VULKAN CALL vkAllocateMemory.
    VkResult res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory);
    /*...*/
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值