首页 > 解决方案 > 如何正确共享 VkDeviceMemory?VkExternalMemoryBufferCreateInfoKHR 有什么用?

问题描述

这是我一篇文章的延续。简而言之 - 我有多个VkDevice(和多个一切- 交换链、命令缓冲区等),我想用这些资源渲染相同的几何图形,即我不想多次上传数据。正如@Ekzuzy 指出的那样,我可以使用VK_KHR_external_memory. 我试过了,实际上它有效,但我还有一些问题以及调试层抱怨。

这是最重要的步骤:

  1. 包括所有必需的扩展:

    instanceExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
    instanceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
    instanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
    instanceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
    deviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
    deviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
    deviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
    deviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
    deviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
    
  2. 使用数据创建设备本地内存。它打算成为共享内存:

    a) create_staging_buffer_and_memory
    b) copy_data_to_staging_buffer
    c) create_device_local_buffer_and_memory
    d) copy_staging_buffer_to_device_local_buffer
    e) create_memory_handle
    

    VkBuffer这里的对象是临时的,复制完成后会被销毁。分期记忆也是。使用字段中的VkExportMemoryAllocateInfoKHR结构 创建的设备本地内存。通过调用VkMemoryAllocateInfo::pNext获得的内存句柄。vkGetMemoryFdKHR在该步骤之后,我有一个内存,其中包含设备中的数据和指向它的句柄。

  3. 创建VkBuffer并且VkDeviceMemory应该参与实际渲染。VkImportMemoryFdInfoKHR 使用字段中的结构创建的内存VkMemoryAllocateInfo::pNext,我使用之前获得的句柄。

  4. 最后记录一个命令缓冲区,其中从 step 绑定一个缓冲区3

正如我之前所写 - 我看到了输出,但调试层告诉我:

layer MEM: vkCmdBindVertexBuffers(): Cannot read invalid region of memory allocation 0x17 for bound Buffer object 0x16, 请在使用前填充内存。

我不确定为什么。以及层如何知道内存无效。无论如何,这对我来说是错误的,我不应该担心这个警告。还是应该?

另一个问题是关于VkExternalMemoryBufferCreateInfoKHR哪个用于VkBufferCreateInfo::pNext. 我不清楚文档的作用-它拥有的所有信息都是某个句柄的类型。哪个把手?并且应用程序在指定指定此结构的情况下都可以正常工作。

更新:似乎图层警告是一个错误

标签: vulkan

解决方案


VkExternalMemoryBufferCreateInfoKHR用于创建跨 API 共享的内存,或者可能跨底层物理设备相同的Vulkan 实例或设备共享的内存。

在我的示例存储库中,有一个使用外部存储器 API 在 OpenGL 和 Vulkan 之间共享纹理图像信息的示例。此示例使用 API 的 Win32 HANDLE 版本,但功能与 FD 版本相同,只是用于存储要在不同 API 之间传递的标识符的类型不同。

另一个问题是关于在 VkBufferCreateInfo::pNext 中使用的 VkExternalMemoryBufferCreateInfoKHR

此结构用于通知 vulkan 实例相关缓冲区可能是共享的,这可能会影响 Vulkan 驱动程序在内部管理它的方式。

认为当外部存储器创建 Vulkan 缓冲区时会使用此结构。在缓冲区(或图像)创建期间,您将使用此结构来标记图像将由外部内存支持,然后您将pNextMemoryAllocateInfo设置为ImportMemoryHostPointerInfoEXT包含共享句柄的实例,而不是正常分配。我怀疑它没有在我的示例中使用,因为我使用 Vulkan 仅用于导出,而 GL 端进行导入。如果您在导出和导入端都使用 Vulkan,则可能需要它。


推荐阅读