如何正确分享VkDeviceMemory?什么是VkExternalMemoryBufferCreateInfoKHR?

时间:2018-04-25 11:14:56

标签: vulkan

这是我previous帖子的延续。简而言之 - 我有多个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. 创建应参与的VkBufferVkDeviceMemory 在实际渲染中。使用VkImportMemoryFdInfoKHR创建的内存 VkMemoryAllocateInfo::pNext字段中的结构,我在其中使用 我早先得到的手柄。

  4. 最后记录一个命令缓冲区,用于绑定步骤3中的缓冲区。

  5. 正如我之前写的那样 - 我看到了输出,但调试层告诉我:

      

    层MEM:vkCmdBindVertexBuffers():无法读取无效区域   内存分配0x17为绑定缓冲区对象0x16,请填写   使用前的记忆。

    我不确定为什么。以及图层如何知道内存无效。在任何情况下,我看起来都不对,我不应该担心这个警告。还是应该?

    另一个问题是关于VkExternalMemoryBufferCreateInfoKHR中使用的VkBufferCreateInfo::pNext。文档对我来说并不清楚它的作用 - 它所拥有的所有信息都是某种句柄的类型。哪个处理?该应用程序与相同的 指定此结构。

    更新:图层警告似乎是bug

1 个答案:

答案 0 :(得分:2)

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

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

  

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

此结构用于通知vulkan实例可能共享有问题的缓冲区,这可能会影响Vulkan驱动程序在内部如何管理它。

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