[Mesa-dev] [PATCH 7/7] anv: Implement VK_KHX_external_memory_fd (v2)

Chad Versace chadversary at chromium.org
Tue Feb 28 18:58:40 UTC 2017


From: Jason Ekstrand <jason.ekstrand at intel.com>


v2 (chadv):
  - Rebase.
  - Fix vkGetPhysicalDeviceImageFormatProperties2KHR when
    handleType == 0.
  - Move handleType-independency comments out of handleType-switch, in
    vkGetPhysicalDeviceExternalBufferPropertiesKHX.  Reduces diff in
    future dma_buf patches.

Co-authored-with: Chad Versace <chadversary at chromium.org>
---

On my branch wip/anv-external-memory.
  http://git.kiwitree.net/cgit/~chadv/mesa/log/?h=wip/anv-external-memory

 src/intel/vulkan/anv_device.c           | 90 +++++++++++++++++++++++++++++----
 src/intel/vulkan/anv_entrypoints_gen.py |  1 +
 src/intel/vulkan/anv_formats.c          | 59 ++++++++++++++++++---
 3 files changed, 133 insertions(+), 17 deletions(-)

diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index 024e19f91b9..ec88547368a 100644
--- a/src/intel/vulkan/anv_device.c
+++ b/src/intel/vulkan/anv_device.c
@@ -310,6 +310,10 @@ static const VkExtensionProperties device_extensions[] = {
       .extensionName = VK_KHX_EXTERNAL_MEMORY_EXTENSION_NAME,
       .specVersion = 1,
    },
+   {
+      .extensionName = VK_KHX_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
+      .specVersion = 1,
+   },
 };
 
 static void *
@@ -1400,7 +1404,7 @@ VkResult anv_AllocateMemory(
 {
    ANV_FROM_HANDLE(anv_device, device, _device);
    struct anv_device_memory *mem;
-   VkResult result;
+   VkResult result = VK_SUCCESS;
 
    assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
 
@@ -1418,18 +1422,50 @@ VkResult anv_AllocateMemory(
    if (mem == NULL)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
-   /* The kernel is going to give us whole pages anyway */
-   uint64_t alloc_size = align_u64(pAllocateInfo->allocationSize, 4096);
-
-   result = anv_bo_init_new(&mem->bo, device, alloc_size);
-   if (result != VK_SUCCESS)
-      goto fail;
-
    mem->type_index = pAllocateInfo->memoryTypeIndex;
-
    mem->map = NULL;
    mem->map_size = 0;
 
+   const VkImportMemoryFdInfoKHX *fd_info =
+      vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHX);
+
+   /* The Vulkan spec permits handleType to be 0, in which case the struct is
+    * ignored.
+    */
+   if (fd_info && fd_info->handleType) {
+      /* At the moment, we only support the OPAQUE_FD memory type which is
+       * just a GEM buffer.
+       */
+      assert(fd_info->handleType ==
+             VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHX);
+
+      uint32_t gem_handle = anv_gem_fd_to_handle(device, fd_info->fd);
+      if (!gem_handle) {
+         result = vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX);
+         goto fail;
+      }
+
+      /* From the Vulkan spec:
+       *
+       *    "Importing memory from a file descriptor transfers ownership of
+       *    the file descriptor from the application to the Vulkan
+       *    implementation. The application must not perform any operations on
+       *    the file descriptor after a successful import."
+       *
+       * If the import fails, we leave the file descriptor open.
+       */
+      close(fd_info->fd);
+
+      anv_bo_init(&mem->bo, gem_handle, pAllocateInfo->allocationSize);
+   } else {
+      /* The kernel is going to give us whole pages anyway */
+      uint64_t alloc_size = align_u64(pAllocateInfo->allocationSize, 4096);
+
+      result = anv_bo_init_new(&mem->bo, device, alloc_size);
+      if (result != VK_SUCCESS)
+         goto fail;
+   }
+
    *pMem = anv_device_memory_to_handle(mem);
 
    return VK_SUCCESS;
@@ -1440,6 +1476,42 @@ VkResult anv_AllocateMemory(
    return result;
 }
 
+VkResult anv_GetMemoryFdKHX(
+    VkDevice                                    device_h,
+    VkDeviceMemory                              memory_h,
+    VkExternalMemoryHandleTypeFlagBitsKHX       handleType,
+    int*                                        pFd)
+{
+   ANV_FROM_HANDLE(anv_device, dev, device_h);
+   ANV_FROM_HANDLE(anv_device_memory, mem, memory_h);
+
+   /* We support only one handle type. */
+   assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHX);
+
+   int fd = anv_gem_handle_to_fd(dev, mem->bo.gem_handle);
+   if (fd == -1)
+      return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX);
+
+   *pFd = fd;
+
+   return VK_SUCCESS;
+}
+
+VkResult anv_GetMemoryFdPropertiesKHX(
+    VkDevice                                    device_h,
+    VkExternalMemoryHandleTypeFlagBitsKHX       handleType,
+    int                                         fd,
+    VkMemoryFdPropertiesKHX*                    pMemoryFdProperties)
+{
+   /* The valid usage section for this function says:
+    *
+    *    "handleType must not be one of the handle types defined as opaque."
+    *
+    * Since we only handle opaque handles for now, there are no FD properties.
+    */
+   return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX;
+}
+
 void anv_FreeMemory(
     VkDevice                                    _device,
     VkDeviceMemory                              _mem,
diff --git a/src/intel/vulkan/anv_entrypoints_gen.py b/src/intel/vulkan/anv_entrypoints_gen.py
index d8816a581a2..530163c9eff 100644
--- a/src/intel/vulkan/anv_entrypoints_gen.py
+++ b/src/intel/vulkan/anv_entrypoints_gen.py
@@ -39,6 +39,7 @@ supported_extensions = [
    'VK_KHR_xlib_surface',
    'VK_KHX_external_memory',
    'VK_KHX_external_memory_capabilities',
+   'VK_KHX_external_memory_fd',
 ]
 
 # We generate a static hash table for entry point lookup
diff --git a/src/intel/vulkan/anv_formats.c b/src/intel/vulkan/anv_formats.c
index f91ba437f1e..196a7516dfa 100644
--- a/src/intel/vulkan/anv_formats.c
+++ b/src/intel/vulkan/anv_formats.c
@@ -656,6 +656,17 @@ VkResult anv_GetPhysicalDeviceImageFormatProperties(
                                           pImageFormatProperties);
 }
 
+static const VkExternalMemoryPropertiesKHX prime_fd_props = {
+   /* If we can handle external, then we can both import and export it. */
+   .externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHX |
+                             VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHX,
+   /* For the moment, let's not support mixing and matching */
+   .exportFromImportedHandleTypes =
+      VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHX,
+   .compatibleHandleTypes =
+      VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHX,
+};
+
 VkResult anv_GetPhysicalDeviceImageFormatProperties2KHR(
     VkPhysicalDevice                            physicalDevice,
     const VkPhysicalDeviceImageFormatInfo2KHR*  base_info,
@@ -702,13 +713,23 @@ VkResult anv_GetPhysicalDeviceImageFormatProperties2KHR(
     *    present and VkExternalImageFormatPropertiesKHX will be ignored.
     */
    if (external_info->handleType != 0) {
-      /* FINISHME: Support at least one external memory type for images. */
-      (void) external_props;
-
-      result = vk_errorf(VK_ERROR_FORMAT_NOT_SUPPORTED,
-                         "unsupported VkExternalMemoryTypeFlagBitsKHX 0x%x",
-                         external_info->handleType);
-      goto fail;
+      switch (external_info->handleType) {
+      case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHX:
+         external_props->externalMemoryProperties = prime_fd_props;
+         break;
+      default:
+         /* From the Vulkan 1.0.42 spec:
+          *
+          *    If handleType is not compatible with the [parameters] specified
+          *    in VkPhysicalDeviceImageFormatInfo2KHR, then
+          *    vkGetPhysicalDeviceImageFormatProperties2KHR returns
+          *    VK_ERROR_FORMAT_NOT_SUPPORTED.
+          */
+         result = vk_errorf(VK_ERROR_FORMAT_NOT_SUPPORTED,
+                            "unsupported VkExternalMemoryTypeFlagBitsKHX 0x%x",
+                            external_info->handleType);
+         goto fail;
+      }
    }
 
    return VK_SUCCESS;
@@ -757,8 +778,30 @@ void anv_GetPhysicalDeviceExternalBufferPropertiesKHX(
     const VkPhysicalDeviceExternalBufferInfoKHX* pExternalBufferInfo,
     VkExternalBufferPropertiesKHX*               pExternalBufferProperties)
 {
-   anv_finishme("Handle external buffers");
+   /* The Vulkan 1.0.42 spec says "handleType must be a valid
+    * VkExternalMemoryHandleTypeFlagBitsKHX value" in
+    * VkPhysicalDeviceExternalBufferInfoKHX. This differs from
+    * VkPhysicalDeviceExternalImageFormatInfoKHX, which surprisingly permits
+    * handleType == 0.
+    */
+   assert(pExternalBufferInfo->handleType != 0);
+
+   /* All of the current flags are for sparse which we don't support yet.
+    * Even when we do support it, doing sparse on external memory sounds
+    * sketchy.  Also, just disallowing flags is the safe option.
+    */
+   if (pExternalBufferInfo->flags)
+      goto unsupported;
+
+   switch (pExternalBufferInfo->handleType) {
+   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHX:
+      pExternalBufferProperties->externalMemoryProperties = prime_fd_props;
+      return;
+   default:
+      goto unsupported;
+   }
 
+ unsupported:
    pExternalBufferProperties->externalMemoryProperties =
       (VkExternalMemoryPropertiesKHX) {0};
 }
-- 
2.11.1



More information about the mesa-dev mailing list