<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Feb 28, 2017 at 10:58 AM, Chad Versace <span dir="ltr"><<a href="mailto:chadversary@chromium.org" target="_blank">chadversary@chromium.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Jason Ekstrand <<a href="mailto:jason.ekstrand@intel.com">jason.ekstrand@intel.com</a>><br>
<br>
<br>
v2 (chadv):<br>
  - Rebase.<br>
  - Fix vkGetPhysicalDeviceImageFormat<wbr>Properties2KHR when<br>
    handleType == 0.<br>
  - Move handleType-independency comments out of handleType-switch, in<br>
    vkGetPhysicalDeviceExternalBuf<wbr>ferPropertiesKHX.  Reduces diff in<br>
    future dma_buf patches.<br>
<br>
Co-authored-with: Chad Versace <<a href="mailto:chadversary@chromium.org">chadversary@chromium.org</a>><br>
---<br>
<br>
On my branch wip/anv-external-memory.<br>
  <a href="http://git.kiwitree.net/cgit/~chadv/mesa/log/?h=wip/anv-external-memory" rel="noreferrer" target="_blank">http://git.kiwitree.net/cgit/~<wbr>chadv/mesa/log/?h=wip/anv-<wbr>external-memory</a><br>
<br>
 src/intel/vulkan/anv_device.c           | 90 +++++++++++++++++++++++++++++-<wbr>---<br>
 src/intel/vulkan/anv_<wbr>entrypoints_gen.py |  1 +<br>
 src/intel/vulkan/anv_formats.c          | 59 ++++++++++++++++++---<br>
 3 files changed, 133 insertions(+), 17 deletions(-)<br>
<br>
diff --git a/src/intel/vulkan/anv_device.<wbr>c b/src/intel/vulkan/anv_device.<wbr>c<br>
index 024e19f91b9..ec88547368a 100644<br>
--- a/src/intel/vulkan/anv_device.<wbr>c<br>
+++ b/src/intel/vulkan/anv_device.<wbr>c<br>
@@ -310,6 +310,10 @@ static const VkExtensionProperties device_extensions[] = {<br>
       .extensionName = VK_KHX_EXTERNAL_MEMORY_<wbr>EXTENSION_NAME,<br>
       .specVersion = 1,<br>
    },<br>
+   {<br>
+      .extensionName = VK_KHX_EXTERNAL_MEMORY_FD_<wbr>EXTENSION_NAME,<br>
+      .specVersion = 1,<br>
+   },<br>
 };<br>
<br>
 static void *<br>
@@ -1400,7 +1404,7 @@ VkResult anv_AllocateMemory(<br>
 {<br>
    ANV_FROM_HANDLE(anv_device, device, _device);<br>
    struct anv_device_memory *mem;<br>
-   VkResult result;<br>
+   VkResult result = VK_SUCCESS;<br>
<br>
    assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_<wbr>ALLOCATE_INFO);<br>
<br>
@@ -1418,18 +1422,50 @@ VkResult anv_AllocateMemory(<br>
    if (mem == NULL)<br>
       return vk_error(VK_ERROR_OUT_OF_HOST_<wbr>MEMORY);<br>
<br>
-   /* The kernel is going to give us whole pages anyway */<br>
-   uint64_t alloc_size = align_u64(pAllocateInfo-><wbr>allocationSize, 4096);<br>
-<br>
-   result = anv_bo_init_new(&mem->bo, device, alloc_size);<br>
-   if (result != VK_SUCCESS)<br>
-      goto fail;<br>
-<br>
    mem->type_index = pAllocateInfo-><wbr>memoryTypeIndex;<br>
-<br>
    mem->map = NULL;<br>
    mem->map_size = 0;<br>
<br>
+   const VkImportMemoryFdInfoKHX *fd_info =<br>
+      vk_find_struct_const(<wbr>pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHX);<br>
+<br>
+   /* The Vulkan spec permits handleType to be 0, in which case the struct is<br>
+    * ignored.<br>
+    */<br>
+   if (fd_info && fd_info->handleType) {<br>
+      /* At the moment, we only support the OPAQUE_FD memory type which is<br>
+       * just a GEM buffer.<br>
+       */<br>
+      assert(fd_info->handleType ==<br>
+             VK_EXTERNAL_MEMORY_HANDLE_<wbr>TYPE_OPAQUE_FD_BIT_KHX);<br>
+<br>
+      uint32_t gem_handle = anv_gem_fd_to_handle(device, fd_info->fd);<br>
+      if (!gem_handle) {<br>
+         result = vk_error(VK_ERROR_INVALID_<wbr>EXTERNAL_HANDLE_KHX);<br>
+         goto fail;<br>
+      }<br>
+<br>
+      /* From the Vulkan spec:<br>
+       *<br>
+       *    "Importing memory from a file descriptor transfers ownership of<br>
+       *    the file descriptor from the application to the Vulkan<br>
+       *    implementation. The application must not perform any operations on<br>
+       *    the file descriptor after a successful import."<br>
+       *<br>
+       * If the import fails, we leave the file descriptor open.<br>
+       */<br>
+      close(fd_info->fd);<br>
+<br>
+      anv_bo_init(&mem->bo, gem_handle, pAllocateInfo->allocationSize)<wbr>;<br>
+   } else {<br>
+      /* The kernel is going to give us whole pages anyway */<br>
+      uint64_t alloc_size = align_u64(pAllocateInfo-><wbr>allocationSize, 4096);<br>
+<br>
+      result = anv_bo_init_new(&mem->bo, device, alloc_size);<br>
+      if (result != VK_SUCCESS)<br>
+         goto fail;<br>
+   }<br>
+<br>
    *pMem = anv_device_memory_to_handle(<wbr>mem);<br>
<br>
    return VK_SUCCESS;<br>
@@ -1440,6 +1476,42 @@ VkResult anv_AllocateMemory(<br>
    return result;<br>
 }<br>
<br>
+VkResult anv_GetMemoryFdKHX(<br>
+    VkDevice                                    device_h,<br>
+    VkDeviceMemory                              memory_h,<br>
+    VkExternalMemoryHandleTypeFlag<wbr>BitsKHX       handleType,<br>
+    int*                                        pFd)<br>
+{<br>
+   ANV_FROM_HANDLE(anv_device, dev, device_h);<br>
+   ANV_FROM_HANDLE(anv_device_<wbr>memory, mem, memory_h);<br>
+<br>
+   /* We support only one handle type. */<br>
+   assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_<wbr>TYPE_OPAQUE_FD_BIT_KHX);<br>
+<br>
+   int fd = anv_gem_handle_to_fd(dev, mem->bo.gem_handle);<br>
+   if (fd == -1)<br>
+      return vk_error(VK_ERROR_INVALID_<wbr>EXTERNAL_HANDLE_KHX);<br>
+<br>
+   *pFd = fd;<br>
+<br>
+   return VK_SUCCESS;<br>
+}<br>
+<br>
+VkResult anv_GetMemoryFdPropertiesKHX(<br>
+    VkDevice                                    device_h,<br>
+    VkExternalMemoryHandleTypeFlag<wbr>BitsKHX       handleType,<br>
+    int                                         fd,<br>
+    VkMemoryFdPropertiesKHX*                    pMemoryFdProperties)<br>
+{<br>
+   /* The valid usage section for this function says:<br>
+    *<br>
+    *    "handleType must not be one of the handle types defined as opaque."<br>
+    *<br>
+    * Since we only handle opaque handles for now, there are no FD properties.<br>
+    */<br>
+   return VK_ERROR_INVALID_EXTERNAL_<wbr>HANDLE_KHX;<br>
+}<br>
+<br>
 void anv_FreeMemory(<br>
     VkDevice                                    _device,<br>
     VkDeviceMemory                              _mem,<br>
diff --git a/src/intel/vulkan/anv_<wbr>entrypoints_gen.py b/src/intel/vulkan/anv_<wbr>entrypoints_gen.py<br>
index d8816a581a2..530163c9eff 100644<br>
--- a/src/intel/vulkan/anv_<wbr>entrypoints_gen.py<br>
+++ b/src/intel/vulkan/anv_<wbr>entrypoints_gen.py<br>
@@ -39,6 +39,7 @@ supported_extensions = [<br>
    'VK_KHR_xlib_surface',<br>
    'VK_KHX_external_memory',<br>
    'VK_KHX_external_memory_<wbr>capabilities',<br>
+   'VK_KHX_external_memory_fd',<br>
 ]<br>
<br>
 # We generate a static hash table for entry point lookup<br>
diff --git a/src/intel/vulkan/anv_<wbr>formats.c b/src/intel/vulkan/anv_<wbr>formats.c<br>
index f91ba437f1e..196a7516dfa 100644<br>
--- a/src/intel/vulkan/anv_<wbr>formats.c<br>
+++ b/src/intel/vulkan/anv_<wbr>formats.c<br>
@@ -656,6 +656,17 @@ VkResult anv_<wbr>GetPhysicalDeviceImageFormatPr<wbr>operties(<br>
                                           pImageFormatProperties);<br>
 }<br>
<br>
+static const VkExternalMemoryPropertiesKHX prime_fd_props = {<br>
+   /* If we can handle external, then we can both import and export it. */<br>
+   .externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_<wbr>EXPORTABLE_BIT_KHX |<br>
+                             VK_EXTERNAL_MEMORY_FEATURE_<wbr>IMPORTABLE_BIT_KHX,<br>
+   /* For the moment, let's not support mixing and matching */<br>
+   .exportFromImportedHandleTypes =<br>
+      VK_EXTERNAL_MEMORY_HANDLE_<wbr>TYPE_OPAQUE_FD_BIT_KHX,<br>
+   .compatibleHandleTypes =<br>
+      VK_EXTERNAL_MEMORY_HANDLE_<wbr>TYPE_OPAQUE_FD_BIT_KHX,<br>
+};<br>
+<br>
 VkResult anv_<wbr>GetPhysicalDeviceImageFormatPr<wbr>operties2KHR(<br>
     VkPhysicalDevice                            physicalDevice,<br>
     const VkPhysicalDeviceImageFormatInf<wbr>o2KHR*  base_info,<br>
@@ -702,13 +713,23 @@ VkResult anv_<wbr>GetPhysicalDeviceImageFormatPr<wbr>operties2KHR(<br>
     *    present and VkExternalImageFormatPropertie<wbr>sKHX will be ignored.<br>
     */<br>
    if (external_info->handleType != 0) {<br>
-      /* FINISHME: Support at least one external memory type for images. */<br>
-      (void) external_props;<br>
-<br>
-      result = vk_errorf(VK_ERROR_FORMAT_NOT_<wbr>SUPPORTED,<br>
-                         "unsupported VkExternalMemoryTypeFlagBitsKH<wbr>X 0x%x",<br>
-                         external_info->handleType);<br>
-      goto fail;<br>
+      switch (external_info->handleType) {<br>
+      case VK_EXTERNAL_MEMORY_HANDLE_<wbr>TYPE_OPAQUE_FD_BIT_KHX:<br>
+         external_props-><wbr>externalMemoryProperties = prime_fd_props;<br>
+         break;<br>
+      default:<br>
+         /* From the Vulkan 1.0.42 spec:<br>
+          *<br>
+          *    If handleType is not compatible with the [parameters] specified<br>
+          *    in VkPhysicalDeviceImageFormatInf<wbr>o2KHR, then<br>
+          *    vkGetPhysicalDeviceImageFormat<wbr>Properties2KHR returns<br>
+          *    VK_ERROR_FORMAT_NOT_SUPPORTED.<br>
+          */<br>
+         result = vk_errorf(VK_ERROR_FORMAT_NOT_<wbr>SUPPORTED,<br>
+                            "unsupported VkExternalMemoryTypeFlagBitsKH<wbr>X 0x%x",<br>
+                            external_info->handleType);<br>
+         goto fail;<br>
+      }<br>
    }<br>
<br>
    return VK_SUCCESS;<br>
@@ -757,8 +778,30 @@ void anv_<wbr>GetPhysicalDeviceExternalBuffe<wbr>rPropertiesKHX(<br>
     const VkPhysicalDeviceExternalBuffer<wbr>InfoKHX* pExternalBufferInfo,<br>
     VkExternalBufferPropertiesKHX*               pExternalBufferProperties)<br>
 {<br>
-   anv_finishme("Handle external buffers");<br>
+   /* The Vulkan 1.0.42 spec says "handleType must be a valid<br>
+    * VkExternalMemoryHandleTypeFlag<wbr>BitsKHX value" in<br>
+    * VkPhysicalDeviceExternalBuffer<wbr>InfoKHX. This differs from<br>
+    * VkPhysicalDeviceExternalImageF<wbr>ormatInfoKHX, which surprisingly permits<br>
+    * handleType == 0.<br></blockquote><div><br></div><div>It's not that surprising.  It lets the user just always chain in the struct but makes it behave as if it weren't there if handleType == 0.  For this entrypoint, they won't be calling it unless they actually want to query something.<br><br></div><div>Changes look good to me.  I'll pull this patch into my tree.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+    */<br>
+   assert(pExternalBufferInfo-><wbr>handleType != 0);<br>
+<br>
+   /* All of the current flags are for sparse which we don't support yet.<br>
+    * Even when we do support it, doing sparse on external memory sounds<br>
+    * sketchy.  Also, just disallowing flags is the safe option.<br>
+    */<br>
+   if (pExternalBufferInfo->flags)<br>
+      goto unsupported;<br>
+<br>
+   switch (pExternalBufferInfo-><wbr>handleType) {<br>
+   case VK_EXTERNAL_MEMORY_HANDLE_<wbr>TYPE_OPAQUE_FD_BIT_KHX:<br>
+      pExternalBufferProperties-><wbr>externalMemoryProperties = prime_fd_props;<br>
+      return;<br>
+   default:<br>
+      goto unsupported;<br>
+   }<br>
<br>
+ unsupported:<br>
    pExternalBufferProperties-><wbr>externalMemoryProperties =<br>
       (<wbr>VkExternalMemoryPropertiesKHX) {0};<br>
 }<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.11.1<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>