如何在Vulkan中重新分配缓冲区
Vulkan 中推荐的内存管理方法是对缓冲区进行子分配,例如参见下图。
我正在尝试实施“好的”方法。我有一个系统可以告诉我内存分配中的哪个位置可用,因此我可以绑定单个大缓冲区的子区域。但是,我找不到执行此操作的机制,或者只是误解了正在发生的事情,因为绑定函数将缓冲区作为输入和偏移量。除了通过现有缓冲区,我看不到如何指定绑定的大小。
所以我想有几个问题:
- 下图中的虚线矩形只是绑定,还是额外的缓冲区?
- 如果它们是绑定,我如何告诉 Vulkan(理想情况下使用 VMA)使用缓冲区的该部分?
- 如果它们是额外的缓冲区,我该如何创建它们?
- 如果两者都不是,它们是什么?
我已经阅读了一些自定义分配器,但它们似乎遵循“坏”方法,将偏移量返回到大型分配中以进行绑定,因此仍然有大量缓冲区但分配计数较低。需要明确的是,除了通过 VMA 之外,我没有使用自定义分配器回调;我上面提到的“系统”位于 VMA 调用之上。
任何指针非常感谢!
回答
下图中的虚线矩形只是绑定,还是额外的缓冲区?
它们代表实际数据。所以“索引”块是包含顶点索引的存储范围。
如果它们是绑定,我如何告诉 Vulkan(理想情况下使用 VMA)使用缓冲区的该部分?
这取决于您如何将其VkBuffer用作资源的特定性质。一般而言,每个使用 aVkBuffer作为资源的函数都采用一个字节偏移量,表示从哪里开始读取。许多此类函数还采用与偏移量相结合的大小,表示可以通过该特定资源读取的全部数据量。
例如,vkCmdBindVertexBuffers获取一个VkBuffers数组,对于每个数组,VkBuffer它还需要一个字节偏移量,表示该顶点缓冲区的起点。 VkDescriptorBufferInfo,表示描述符使用的缓冲区的结构,采用VkBuffer、字节偏移量和大小。
顶点缓冲区(和索引缓冲区)绑定没有大小,但它们不需要一个. 它们的有效大小由与它们一起使用的渲染命令(以及由它读取的索引数据)定义。如果使用 100 个 32 位索引进行渲染,则期望索引缓冲区的大小减去起始偏移量后至少应为 400 字节。如果不是,UB 结果。
- It should also be noted that NVIDIA's recommendations are for *NVIDIA's* hardware. While it's not good to have bunches of buffers for no reason, the assumption they're making is that a particular piece of hardware will provide memory that allows for both vertex and uniform storage. So you must temper the suggestion with the knowledge that you may *need* to separate these things because hardware just doesn't allow it. Or because you might need to stream vertex data, and it might be faster to read directly from CPU memory than to do transfer operations.