<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Aug 13, 2017 at 4:37 AM, Lionel Landwerlin <span dir="ltr"><<a href="mailto:lionel.g.landwerlin@intel.com" target="_blank">lionel.g.landwerlin@intel.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 04/08/17 18:24, Jason Ekstrand wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
---<br>
  src/intel/vulkan/anv_batch_cha<wbr>in.c | 57 +++++++++++++++++++++++++++++-<wbr>-<br>
  src/intel/vulkan/anv_device.c      |  1 +<br>
  src/intel/vulkan/anv_gem.c         | 36 ++++++++++++++++++++<br>
  src/intel/vulkan/anv_private.<wbr>h     | 23 +++++++++----<br>
  src/intel/vulkan/anv_queue.c       | 69 ++++++++++++++++++++++++++++++<wbr>++++++--<br>
  5 files changed, 175 insertions(+), 11 deletions(-)<br>
<br>
diff --git a/src/intel/vulkan/anv_batch_c<wbr>hain.c b/src/intel/vulkan/anv_batch_c<wbr>hain.c<br>
index 65fe366..7a84bbd 100644<br>
--- a/src/intel/vulkan/anv_batch_c<wbr>hain.c<br>
+++ b/src/intel/vulkan/anv_batch_c<wbr>hain.c<br>
@@ -1416,11 +1416,13 @@ anv_cmd_buffer_execbuf(struct anv_device *device,<br>
     struct anv_execbuf execbuf;<br>
     anv_execbuf_init(&execbuf);<br>
  +   int in_fence = -1;<br>
     VkResult result = VK_SUCCESS;<br>
     for (uint32_t i = 0; i < num_in_semaphores; i++) {<br>
        ANV_FROM_HANDLE(anv_semaphore, semaphore, in_semaphores[i]);<br>
-      assert(semaphore->temporary.ty<wbr>pe == ANV_SEMAPHORE_TYPE_NONE);<br>
-      struct anv_semaphore_impl *impl = &semaphore->permanent;<br>
+      struct anv_semaphore_impl *impl =<br>
+         semaphore->temporary.type != ANV_SEMAPHORE_TYPE_NONE ?<br>
+         &semaphore->temporary : &semaphore->permanent;<br>
</blockquote>
<br></span>
I know you're not enabling this until patch 8, but for consistency, shouldn't this be part of patch 1?<br>
</blockquote><div><br></div><div>Yup.  Fixed.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
          switch (impl->type) {<br>
        case ANV_SEMAPHORE_TYPE_BO:<br>
@@ -1429,11 +1431,29 @@ anv_cmd_buffer_execbuf(struct anv_device *device,<br>
           if (result != VK_SUCCESS)<br>
              return result;<br>
           break;<br>
+<br>
+      case ANV_SEMAPHORE_TYPE_SYNC_FILE:<br>
+         if (in_fence == -1) {<br>
+            in_fence = impl->fd;<br>
+         } else {<br>
+            int merge = anv_gem_sync_file_merge(device<wbr>, in_fence, impl->fd);<br>
+            if (merge == -1)<br>
+               return vk_error(VK_ERROR_INVALID_EXTE<wbr>RNAL_HANDLE_KHR);<br>
+<br>
+            close(impl->fd);<br>
+            close(in_fence);<br>
+            in_fence = merge;<br>
+         }<br>
+<br>
+         impl->fd = -1;<br>
+         break;<br>
+<br>
        default:<br>
           break;<br>
        }<br>
     }<br>
  +   bool need_out_fence = false;<br>
     for (uint32_t i = 0; i < num_out_semaphores; i++) {<br>
        ANV_FROM_HANDLE(anv_semaphore, semaphore, out_semaphores[i]);<br>
  @@ -1459,6 +1479,11 @@ anv_cmd_buffer_execbuf(struct anv_device *device,<br>
           if (result != VK_SUCCESS)<br>
              return result;<br>
           break;<br>
+<br>
+      case ANV_SEMAPHORE_TYPE_SYNC_FILE:<br>
+         need_out_fence = true;<br>
+         break;<br>
+<br>
        default:<br>
           break;<br>
        }<br>
@@ -1472,9 +1497,19 @@ anv_cmd_buffer_execbuf(struct anv_device *device,<br>
        setup_empty_execbuf(&execbuf, device);<br>
     }<br>
  +   if (in_fence != -1) {<br>
+      execbuf.execbuf.flags |= I915_EXEC_FENCE_IN;<br>
+      execbuf.execbuf.rsvd2 |= (uint32_t)in_fence;<br>
+   }<br>
+<br>
+   if (need_out_fence)<br>
+      execbuf.execbuf.flags |= I915_EXEC_FENCE_OUT;<br>
       result = anv_device_execbuf(device, &execbuf.execbuf, execbuf.bos);<br>
  +   /* Execbuf does not consume the in_fence.  It's our job to close it. */<br>
+   close(in_fence);<br>
+<br>
     for (uint32_t i = 0; i < num_in_semaphores; i++) {<br>
        ANV_FROM_HANDLE(anv_semaphore, semaphore, in_semaphores[i]);<br>
        /* From the Vulkan 1.0.53 spec:<br>
@@ -1489,6 +1524,24 @@ anv_cmd_buffer_execbuf(struct anv_device *device,<br>
        anv_semaphore_reset_temporary(<wbr>device, semaphore);<br>
     }<br>
  +   if (result == VK_SUCCESS && need_out_fence) {<br>
+      int out_fence = execbuf.execbuf.rsvd2 >> 32;<br>
+      for (uint32_t i = 0; i < num_out_semaphores; i++) {<br>
+         ANV_FROM_HANDLE(anv_<wbr>semaphore, semaphore, out_semaphores[i]);<br>
+         /* Out fences can't have temporary state because that would imply<br>
+          * that we imported a sync file and are trying to signal it.<br>
+          */<br>
+         assert(semaphore->temporary.t<wbr>ype == ANV_SEMAPHORE_TYPE_NONE);<br>
+         struct anv_semaphore_impl *impl = &semaphore->permanent;<br>
+<br>
+         if (impl->type == ANV_SEMAPHORE_TYPE_SYNC_FILE) {<br>
+            assert(impl->fd == -1);<br>
+            impl->fd = dup(out_fence);<br>
+         }<br>
+      }<br>
+      close(out_fence);<br>
+   }<br>
+<br>
     anv_execbuf_finish(&execbuf, &device->alloc);<br>
       return result;<br>
diff --git a/src/intel/vulkan/anv_device.<wbr>c b/src/intel/vulkan/anv_device.<wbr>c<br>
index e82e1e9..3c5f78c 100644<br>
--- a/src/intel/vulkan/anv_device.<wbr>c<br>
+++ b/src/intel/vulkan/anv_device.<wbr>c<br>
@@ -337,6 +337,7 @@ anv_physical_device_init(struc<wbr>t anv_physical_device *device,<br>
        goto fail;<br>
       device->has_exec_async = anv_gem_get_param(fd, I915_PARAM_HAS_EXEC_ASYNC);<br>
+   device->has_exec_fence = anv_gem_get_param(fd, I915_PARAM_HAS_EXEC_FENCE);<br>
       bool swizzled = anv_gem_get_bit6_swizzle(fd, I915_TILING_X);<br>
  diff --git a/src/intel/vulkan/anv_gem.c b/src/intel/vulkan/anv_gem.c<br>
index 36692f5..5b68e9b 100644<br>
--- a/src/intel/vulkan/anv_gem.c<br>
+++ b/src/intel/vulkan/anv_gem.c<br>
@@ -22,6 +22,7 @@<br>
   */<br>
    #include <sys/ioctl.h><br>
+#include <sys/types.h><br>
  #include <sys/mman.h><br>
  #include <string.h><br>
  #include <errno.h><br>
@@ -400,3 +401,38 @@ anv_gem_fd_to_handle(struct anv_device *device, int fd)<br>
       return args.handle;<br>
  }<br>
+<br>
+#ifndef SYNC_IOC_MAGIC<br>
+/* duplicated from linux/sync_file.h to avoid build-time depnedency<br>
</blockquote>
<br></div></div>
nit: dependency<br>
</blockquote><div><br></div><div>Fixed.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ * on new (v4.7) kernel headers.  Once distro's are mostly using<br>
+ * something newer than v4.7 drop this and #include <linux/sync_file.h><br>
+ * instead.<br>
+ */<br>
+struct sync_merge_data {<br>
+   char  name[32];<br>
+   __s32 fd2;<br>
+   __s32 fence;<br>
+   __u32 flags;<br>
+   __u32 pad;<br>
+};<br>
+<br>
+#define SYNC_IOC_MAGIC '>'<br>
+#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data)<br>
+#endif<br>
+<br>
+int<br>
+anv_gem_sync_file_merge(struc<wbr>t anv_device *device, int fd1, int fd2)<br>
+{<br>
+   const char name[] = "anv merge fence";<br>
+   struct sync_merge_data args = {<br>
+      .fd2 = fd2,<br>
+      .fence = -1,<br>
+   };<br>
+   memcpy(<a href="http://args.name" rel="noreferrer" target="_blank">args.name</a>, name, sizeof(name));<br>
+<br>
+   int ret = anv_ioctl(fd1, SYNC_IOC_MERGE, &args);<br>
+   if (ret == -1)<br>
+      return -1;<br>
+<br>
+   return args.fence;<br>
+}<br>
diff --git a/src/intel/vulkan/anv_private<wbr>.h b/src/intel/vulkan/anv_private<wbr>.h<br>
index bc67bb6..5c7b3b4 100644<br>
--- a/src/intel/vulkan/anv_private<wbr>.h<br>
+++ b/src/intel/vulkan/anv_private<wbr>.h<br>
@@ -652,6 +652,7 @@ struct anv_physical_device {<br>
      struct isl_device                           isl_dev;<br>
      int                                         cmd_parser_version;<br>
      bool                                        has_exec_async;<br>
+    bool                                        has_exec_fence;<br>
        uint32_t                                    eu_total;<br>
      uint32_t                                    subslice_total;<br>
@@ -810,6 +811,7 @@ uint32_t anv_gem_fd_to_handle(struct anv_device *device, int fd);<br>
  int anv_gem_set_caching(struct anv_device *device, uint32_t gem_handle, uint32_t caching);<br>
  int anv_gem_set_domain(struct anv_device *device, uint32_t gem_handle,<br>
                         uint32_t read_domains, uint32_t write_domain);<br>
+int anv_gem_sync_file_merge(struct anv_device *device, int fd1, int fd2);<br>
    VkResult anv_bo_init_new(struct anv_bo *bo, struct anv_device *device, uint64_t size);<br>
  @@ -1735,17 +1737,26 @@ enum anv_semaphore_type {<br>
     ANV_SEMAPHORE_TYPE_NONE = 0,<br>
     ANV_SEMAPHORE_TYPE_DUMMY,<br>
     ANV_SEMAPHORE_TYPE_BO,<br>
+   ANV_SEMAPHORE_TYPE_SYNC_FILE,<br>
  };<br>
    struct anv_semaphore_impl {<br>
     enum anv_semaphore_type type;<br>
  -   /* A BO representing this semaphore when type == ANV_SEMAPHORE_TYPE_BO.<br>
-    * This BO will be added to the object list on any execbuf2 calls for<br>
-    * which this semaphore is used as a wait or signal fence.  When used as<br>
-    * a signal fence, the EXEC_OBJECT_WRITE flag will be set.<br>
-    */<br>
-   struct anv_bo *bo;<br>
+   union {<br>
+      /* A BO representing this semaphore when type == ANV_SEMAPHORE_TYPE_BO.<br>
+       * This BO will be added to the object list on any execbuf2 calls for<br>
+       * which this semaphore is used as a wait or signal fence.  When used as<br>
+       * a signal fence, the EXEC_OBJECT_WRITE flag will be set.<br>
+       */<br>
+      struct anv_bo *bo;<br>
+<br>
+      /* The sync file descriptor when type == AKV_SEMAPHORE_TYPE_SYNC_FILE.<br>
+       * If the semaphore is in the unsignaled state due to either just being<br>
+       * created or because it has been used for a wait, fd will be -1.<br>
+       */<br>
+      int fd;<br>
+   };<br>
  };<br>
    struct anv_semaphore {<br>
diff --git a/src/intel/vulkan/anv_queue.c b/src/intel/vulkan/anv_queue.c<br>
index 039dfd7..1f27028 100644<br>
--- a/src/intel/vulkan/anv_queue.c<br>
+++ b/src/intel/vulkan/anv_queue.c<br>
@@ -571,6 +571,11 @@ VkResult anv_CreateSemaphore(<br>
         * EXEC_OBJECT_ASYNC bit set.<br>
         */<br>
        assert(!(semaphore->permanent.<wbr>bo->flags & EXEC_OBJECT_ASYNC));<br>
+   } else if (handleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_T<wbr>YPE_SYNC_FD_BIT_KHR) {<br>
+      assert(handleTypes == VK_EXTERNAL_SEMAPHORE_HANDLE_T<wbr>YPE_SYNC_FD_BIT_KHR);<br>
+<br>
+      semaphore->permanent.type = ANV_SEMAPHORE_TYPE_SYNC_FILE;<br>
+      semaphore->permanent.fd = -1;<br>
     } else {<br>
        assert(!"Unknown handle type");<br>
        vk_free2(&device->alloc, pAllocator, semaphore);<br>
@@ -597,6 +602,10 @@ anv_semaphore_impl_cleanup(str<wbr>uct anv_device *device,<br>
     case ANV_SEMAPHORE_TYPE_BO:<br>
        anv_bo_cache_release(device, &device->bo_cache, impl->bo);<br>
        return;<br>
+<br>
+   case ANV_SEMAPHORE_TYPE_SYNC_FILE:<br>
+      close(impl->fd);<br>
+      return;<br>
     }<br>
       unreachable("Invalid semaphore type");<br>
@@ -635,6 +644,8 @@ void anv_GetPhysicalDeviceExternalS<wbr>emaphorePropertiesKHR(<br>
      const VkPhysicalDeviceExternalSemaph<wbr>oreInfoKHR* pExternalSemaphoreInfo,<br>
      VkExternalSemaphorePropertiesK<wbr>HR*           pExternalSemaphoreProperties)<br>
  {<br>
+   ANV_FROM_HANDLE(anv_physical_<wbr>device, device, physicalDevice);<br>
+<br>
     switch (pExternalSemaphoreInfo->handl<wbr>eType) {<br>
     case VK_EXTERNAL_SEMAPHORE_HANDLE_T<wbr>YPE_OPAQUE_FD_BIT_KHR:<br>
        pExternalSemaphoreProperties-><wbr>exportFromImportedHandleTypes =<br>
@@ -644,13 +655,27 @@ void anv_GetPhysicalDeviceExternalS<wbr>emaphorePropertiesKHR(<br>
        pExternalSemaphoreProperties-><wbr>externalSemaphoreFeatures =<br>
           VK_EXTERNAL_SEMAPHORE_<wbr>FEATURE_EXPORTABLE_BIT_KHR |<br>
           VK_EXTERNAL_SEMAPHORE_<wbr>FEATURE_IMPORTABLE_BIT_KHR;<br>
+      return;<br>
+<br>
+   case VK_EXTERNAL_SEMAPHORE_HANDLE_T<wbr>YPE_SYNC_FD_BIT_KHR:<br>
+      if (device->has_exec_fence) {<br>
+         pExternalSemaphoreProperties-<wbr>>exportFromImportedHandleTypes = 0;<br>
+         pExternalSemaphoreProperties-<wbr>>compatibleHandleTypes =<br>
+            VK_EXTERNAL_SEMAPHORE_HANDLE_T<wbr>YPE_SYNC_FD_BIT_KHR;<br>
+         pExternalSemaphoreProperties-<wbr>>externalSemaphoreFeatures =<br>
+            VK_EXTERNAL_SEMAPHORE_FEATURE_<wbr>EXPORTABLE_BIT_KHR |<br>
+            VK_EXTERNAL_SEMAPHORE_FEATURE_<wbr>IMPORTABLE_BIT_KHR;<br>
+         return;<br>
+      }<br>
        break;<br>
       default:<br>
-      pExternalSemaphoreProperties-><wbr>exportFromImportedHandleTypes = 0;<br>
-      pExternalSemaphoreProperties-><wbr>compatibleHandleTypes = 0;<br>
-      pExternalSemaphoreProperties-><wbr>externalSemaphoreFeatures = 0;<br>
+      break;<br>
     }<br>
+<br>
+   pExternalSemaphoreProperties-<wbr>>exportFromImportedHandleTypes = 0;<br>
+   pExternalSemaphoreProperties-<wbr>>compatibleHandleTypes = 0;<br>
+   pExternalSemaphoreProperties-<wbr>>externalSemaphoreFeatures = 0;<br>
  }<br>
    VkResult anv_ImportSemaphoreFdKHR(<br>
@@ -682,6 +707,13 @@ VkResult anv_ImportSemaphoreFdKHR(<br>
        break;<br>
     }<br>
  +   case VK_EXTERNAL_SEMAPHORE_HANDLE_T<wbr>YPE_SYNC_FD_BIT_KHR:<br>
+      new_impl = (struct anv_semaphore_impl) {<br>
+         .type = ANV_SEMAPHORE_TYPE_SYNC_FILE,<br>
+         .fd = fd,<br>
+      };<br>
+      break;<br>
+<br>
     default:<br>
        return vk_error(VK_ERROR_INVALID_EXTE<wbr>RNAL_HANDLE_KHR);<br>
     }<br>
@@ -690,6 +722,9 @@ VkResult anv_ImportSemaphoreFdKHR(<br>
        anv_semaphore_impl_cleanup(dev<wbr>ice, &semaphore->temporary);<br>
        semaphore->temporary = new_impl;<br>
     } else {<br>
+      /* SYNC_FILE must be a temporary import */<br>
+      assert(new_impl.type != ANV_SEMAPHORE_TYPE_SYNC_FILE);<br>
+<br>
        anv_semaphore_impl_cleanup(dev<wbr>ice, &semaphore->permanent);<br>
        semaphore->permanent = new_impl;<br>
     }<br>
@@ -719,6 +754,34 @@ VkResult anv_GetSemaphoreFdKHR(<br>
           return result;<br>
        break;<br>
  +   case ANV_SEMAPHORE_TYPE_SYNC_FILE:<br>
+      /* There are two reasons why this could happen:<br>
+       *<br>
+       *  1) The user is trying to export without submitting something that<br>
+       *     signals the semaphore.  If this is the case, it's their bug so<br>
+       *     what we return here doesn't matter.<br>
+       *<br>
+       *  2) The kernel didn't give us a file descriptor.  The most likely<br>
+       *     reason for this is running out of file descriptors.<br>
+       */<br>
+      if (impl->fd < 0)<br>
+         return vk_error(VK_ERROR_TOO_MANY_OBJ<wbr>ECTS);<br>
+<br>
+      *pFd = impl->fd;<br>
+<br>
+      /* From the Vulkan 1.0.53 spec:<br>
+       *<br>
+       *    "...exporting a semaphore payload to a handle with copy<br>
+       *    transference has the same side effects on the source<br>
+       *    semaphore’s payload as executing a semaphore wait operation."<br>
+       *<br>
+       * In other words, it may still be a SYNC_FD semaphore, but it's now<br>
+       * considered to have been waited on and no longer has a sync file<br>
+       * attached.<br>
+       */<br>
+      impl->fd = -1;<br>
+      return VK_SUCCESS;<br>
+<br>
     default:<br>
        return vk_error(VK_ERROR_INVALID_EXTE<wbr>RNAL_HANDLE_KHR);<br>
     }<br>
</blockquote>
<br>
<br>
</div></div></blockquote></div><br></div></div>