我遇到了以下难题,试图使用Vulkan Hpp唯一句柄来存储缓冲区及其分配的内存。我申报手柄
vk::UniqueBuffer vertex_buffer;
vk::UniqueDeviceMemory vertex_buffer_memory;并使用vk::Device::createBufferUnique和vk::Device::allocateMemoryUnique填充它们。这些需要按这个顺序调用,因为后者取决于前者的内存需求(通过vk::Device::getBufferMemoryRequirements获得)。但是,这会导致vertex_memory_buffer在vertex_buffer之前被销毁,并触发来自验证层的以下警告:
Validation Warning: [ CHASSIS ] Object 0: handle = 0x558599c91fc0, type = VK_OBJECT_TYPE_DEVICE; Object 1: handle = 0x1b000000001b, type = VK_OBJECT_TYPE_BUFFER; Object 2: handle = 0x1c000000001c, type = VK_OBJECT_TYPE_DEVICE_MEMORY; | MessageID = 0x7366b7dd |
VK Object VkBuffer 0x1b000000001b[] still has a reference to mem obj VkDeviceMemory 0x1c000000001c[].实际上,我查找的所有C示例首先销毁缓冲区,然后释放内存。当然,我可以使用某种变通方法来确保在这里也会发生同样的事情(例如,默认初始化vertex_buffer_memory并在创建vertex_buffer之后分配给它),但这实际上违背了惟一句柄的目的(这正是使资源管理自动化)。除非我误解了什么,Vulkan API的设计和RAII之间似乎有不兼容之处。解决这个问题的正确方法是什么?
发布于 2020-11-01 14:54:26
这些需要按这个顺序调用,因为后者取决于前者的内存需求。
不,他们没有。您确实需要获得适合该缓冲区的内存需求,但不需要使用特定的VkBuffer对象。
最好在应用程序开始时计算一次需求,方法是创建代表特定用例的VkBuffer。也就是说,创建一定数量的VkBuffer实例,表示您将使用的所有类型的缓冲区。
缓冲区的内存需求并不是特定于该VkBuffer对象的;有一个Vulkan规范中的一系列规则定义了两个VkBuffer的需求在什么情况下是相同的。因此,如果您创建了一个类似于您实际使用的VkBuffer,您可以获得相应的需求,并知道为这些需求分配的内存将适用于您计划使用的内存。
只要遵守这些规则,就不需要逆转这些对象的初始化顺序。
而且,只为一个缓冲区或图像分配内存也是个坏主意。Vulkan不是OpenGL,你不应该像对待glBufferStorage那样对待vkAllocateMemory和vkCreateBuffer。分配大量内存,然后根据需要将其细分为缓冲区(和图像)。您还可以使用像VulkanMemoryAllocator这样的内存管理器来为您处理内存管理。
https://stackoverflow.com/questions/64632038
复制相似问题