nikitablack
nikitablack

Reputation: 4663

How to correctly share VkDeviceMemory? What is VkExternalMemoryBufferCreateInfoKHR for?

This is a continuation of my previous post. In short - I have multiple VkDevice's (and multiple everything - swapchains, command buffers etc) and I want to render the same geometry with these resources, i.e. I don't want to upload the data multiple times. As @Ekzuzy pointed out I could use VK_KHR_external_memory. I tried and actually it works, but I have some questions remaining as well as debug layer complains.

This are the most important steps:

  1. Include all required extensions:

    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. Create a device local memory with a data. It intended to be a shared memory:

    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 objects here are temporary and are destroyed after the copying is finished. Staging memory too. Device local memory created with VkExportMemoryAllocateInfoKHR structure in VkMemoryAllocateInfo::pNext field. Memory handle obtained with vkGetMemoryFdKHR call. After that step I have a memory with a data in the device and a handle pointing to it.

  3. Create VkBuffer and VkDeviceMemory which should participate in actual rendering. Memory created with VkImportMemoryFdInfoKHR structure in VkMemoryAllocateInfo::pNext field, where I use the handle which I got earlier.

  4. Finally record a command buffer where bind a buffer from step 3.

As I wrote before - I see the output, but the debug layer tells me:

layer MEM: vkCmdBindVertexBuffers(): Cannot read invalid region of memory allocation 0x17 for bound Buffer object 0x16, please fill the memory before using.

I'm not sure why. And how the layer knows that the memory is invalid. In any case it looks wrong to me and I should not worry about this warning. Or should?

Another question is about VkExternalMemoryBufferCreateInfoKHR which is used in VkBufferCreateInfo::pNext. The documentation is not clear to me what it does - all information it have is the type of some handle. Which handle? And the application works the same with and without this struct specified.

Update: it seems that the layer warning is a bug.

Upvotes: 3

Views: 4271

Answers (1)

Jherico
Jherico

Reputation: 29240

VkExternalMemoryBufferCreateInfoKHR is for creating memory that is shared across APIs, or potentially across Vulkan instances or devices where the underlying physical device is the same.

There is an example of using the external memory API to share texture image information between OpenGL and Vulkan in my examples repository here. This example uses the Win32 HANDLE versions of the API, but the functionality is equivalent to the FD versions, just with a different type for storing the identifier to be passed between different APIs.

Another question is about VkExternalMemoryBufferCreateInfoKHR which is used in VkBufferCreateInfo::pNext

This structure is used to inform the vulkan instance that the buffer in question may be shared, which may impact how the Vulkan driver manages it internally.

I think this structure is used when a Vulkan buffer is being created from external memory. During buffer (or image) creation, you'd use this structure to mark that the image would be backed by external memory, then instead of the normal allocation you'd set the pNext of the MemoryAllocateInfo to a ImportMemoryHostPointerInfoEXT instance containing the shared handle. I suspect it's not used in my example because there I use Vulkan only for exporting, and the GL side does the importing. If you're using Vulkan on both the export and import side, you may need it.

Upvotes: 3

Related Questions