Vulkan系列教程—VMA教程(五)—资源重叠(Aliasing/OverLap)


前言

本文为Vulkan® Memory Allocator系列系列教程,定时更新,请大家关注。如果需要深入学习Vulkan的同学,可以点击课程链接,学习链接

Vulkan学习群:594715138

腾讯课堂《Vulkan原理与实战—铸造渲染核武器—基石篇》

网易课堂《Vulkan原理与实战—铸造渲染核武器—基石篇》


Resource aliasing (overlap)资源别名(重叠)

新式图形API(比如Vulkan与Direct3D 12),由于允许人工的设计内存使用方式,都会允许多个Image或者Buffer甚至二者的混合,映射到同一个内存VkDeviceMemory上面。这对于节省显存有极大的好处,但是需要慎重使用。

比如,如果你能够提前知道你整个渲染帧各个内存的使用排序,其中一些textures或者buffers只在RenderPass的某个时间段(range)内被使用,并且你知道这些时间段并不会互相重叠,那么这些textures或者Images就可以被绑定到同一块VkDeviceMemory上面,即便是他们可能拥有完全不同的属性(width,height或者format)。

这种设计在VMA当中也可以使用,但是你必须手动创建你的VkImage以及VkBuffer。然后你需要找到他们的参数最大值,从而进行分配内存,然后进行绑定操作,参数计算如下:

  • allocation size = max(size of each image)
  • allocation alignment = max(alignment of each image)
  • allocation memoryTypeBits = bitwise AND(memoryTypeBits of each image)

下面的案例,展现了两个不同的Image,但是绑定在了同一块内存空间的,并且起始位置都相同(即offset相同),当然,按照其中最大的来设计内存大小:

// A 512x512 texture to be sampled.
VkImageCreateInfo img1CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
img1CreateInfo.imageType = VK_IMAGE_TYPE_2D;
img1CreateInfo.extent.width = 512;
img1CreateInfo.extent.height = 512;
img1CreateInfo.extent.depth = 1;
img1CreateInfo.mipLevels = 10;
img1CreateInfo.arrayLayers = 1;
img1CreateInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
img1CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
img1CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
img1CreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
img1CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
 
// A full screen texture to be used as color attachment.
VkImageCreateInfo img2CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
img2CreateInfo.imageType = VK_IMAGE_TYPE_2D;
img2CreateInfo.extent.width = 1920;
img2CreateInfo.extent.height = 1080;
img2CreateInfo.extent.depth = 1;
img2CreateInfo.mipLevels = 1;
img2CreateInfo.arrayLayers = 1;
img2CreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
img2CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
img2CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
img2CreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
img2CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
 
VkImage img1;
res = vkCreateImage(device, &img1CreateInfo, nullptr, &img1);
VkImage img2;
res = vkCreateImage(device, &img2CreateInfo, nullptr, &img2);
 
VkMemoryRequirements img1MemReq;
vkGetImageMemoryRequirements(device, img1, &img1MemReq);
VkMemoryRequirements img2MemReq;
vkGetImageMemoryRequirements(device, img2, &img2MemReq);
 
VkMemoryRequirements finalMemReq = {};
finalMemReq.size = std::max(img1MemReq.size, img2MemReq.size);
finalMemReq.alignment = std::max(img1MemReq.alignment, img2MemReq.alignment);
finalMemReq.memoryTypeBits = img1MemReq.memoryTypeBits & img2MemReq.memoryTypeBits;
// Validate if(finalMemReq.memoryTypeBits != 0)
 
VmaAllocationCreateInfo allocCreateInfo = {};
allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
 
VmaAllocation alloc;
res = vmaAllocateMemory(allocator, &finalMemReq, &allocCreateInfo, &alloc, nullptr);
 
res = vmaBindImageMemory(allocator, alloc, img1);
res = vmaBindImageMemory(allocator, alloc, img2);
 
// You can use img1, img2 here, but not at the same time!
 
vmaFreeMemory(allocator, alloc);
vkDestroyImage(allocator, img2, nullptr);
vkDestroyImage(allocator, img1, nullptr);

请记住,资源重叠在使用的时候,必须妥善安排同步关系(proper synchronization)。你可以使用MemoryBarrier来防止img1与img2之间的同时使用可能性。

在使用某个资源之前,你也得把他当成uninitialized——即有垃圾数据。比如,你使用完毕img1然后就要用img2了,那么你就得为img2加一个内存屏障(ImageMemoryBarrier),并且这个屏障的oldLayout = VK_IMAGE_LAYOUT_UNDEFINED。

其他考虑:

  • Vulkan也允许一致解释不同重叠资源之间的内容(我也没太懂),可以看Vulkan Specification的11.8“Memory Aliasing”。
  • 你可以创造更加复杂的内存重叠应用情况,比如在一块大的Allocation(内存块)上面,不同的资源的Offset不同。比如,你可以想象一个超大的TextureBuffer,在不同的RenderPass之间使用,很多小的Buffer都会绑定在上面。如果想这么使用的话,可以用vmaBindBufferMemory2() / vmaBindImageMemory2()这两个接口进行绑定。
  • 在为一堆想重叠绑定的资源创建内存之前,你需要检查下每个资源所需要的内存类型是否互相重叠匹配。比如,一些GPU资源类型可能只能用于COLOR_ATTACHMENT的Usage,那么VkBuffer就没办法在上面重叠使用了。所以你需要做好内存类型的检查哦。

总结

以上就是今天的内容,大家对于vulkan的学习,也可以参考我出品的vulkan系列教程,下面给大家贴出链接。

腾讯课堂《Vulkan原理与实战—铸造渲染核武器—基石篇》

网易课堂《Vulkan原理与实战—铸造渲染核武器—基石篇》
在这里插入图片描述

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵新政

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值