anv: Add support for the SYNC_FD handle type for fences
authorJason Ekstrand <jason.ekstrand@intel.com>
Tue, 8 Aug 2017 22:17:31 +0000 (15:17 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 29 Aug 2017 02:33:43 +0000 (19:33 -0700)
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
src/intel/vulkan/anv_gem.c
src/intel/vulkan/anv_gem_stubs.c
src/intel/vulkan/anv_private.h
src/intel/vulkan/anv_queue.c

index 8283117cd0e08602dc3dcf6fa08ac686e3953e41..3994c6b66c2d43afc6977e1076e122acd613ad6b 100644 (file)
@@ -489,6 +489,34 @@ anv_gem_syncobj_fd_to_handle(struct anv_device *device, int fd)
    return args.handle;
 }
 
+int
+anv_gem_syncobj_export_sync_file(struct anv_device *device, uint32_t handle)
+{
+   struct drm_syncobj_handle args = {
+      .handle = handle,
+      .flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE,
+   };
+
+   int ret = anv_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args);
+   if (ret)
+      return -1;
+
+   return args.fd;
+}
+
+int
+anv_gem_syncobj_import_sync_file(struct anv_device *device,
+                                 uint32_t handle, int fd)
+{
+   struct drm_syncobj_handle args = {
+      .handle = handle,
+      .fd = fd,
+      .flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE,
+   };
+
+   return anv_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args);
+}
+
 void
 anv_gem_syncobj_reset(struct anv_device *device, uint32_t handle)
 {
index 36700d7434cd69033bc1d576deec83941d420b60..02527b5fcd8d4d87ae29cd07aae6ac7ec1dbabae 100644 (file)
@@ -187,6 +187,19 @@ anv_gem_sync_file_merge(struct anv_device *device, int fd1, int fd2)
    unreachable("Unused");
 }
 
+int
+anv_gem_syncobj_export_sync_file(struct anv_device *device, uint32_t handle)
+{
+   unreachable("Unused");
+}
+
+int
+anv_gem_syncobj_import_sync_file(struct anv_device *device,
+                                 uint32_t handle, int fd)
+{
+   unreachable("Unused");
+}
+
 uint32_t
 anv_gem_syncobj_create(struct anv_device *device, uint32_t flags)
 {
index f9537c2b2450c43cba6d0d4bbe4a79353961aae4..b30b71f3367d5a29b6425749252d2d8736141409 100644 (file)
@@ -810,6 +810,10 @@ uint32_t anv_gem_syncobj_create(struct anv_device *device, uint32_t flags);
 void anv_gem_syncobj_destroy(struct anv_device *device, uint32_t handle);
 int anv_gem_syncobj_handle_to_fd(struct anv_device *device, uint32_t handle);
 uint32_t anv_gem_syncobj_fd_to_handle(struct anv_device *device, int fd);
+int anv_gem_syncobj_export_sync_file(struct anv_device *device,
+                                     uint32_t handle);
+int anv_gem_syncobj_import_sync_file(struct anv_device *device,
+                                     uint32_t handle, int fd);
 void anv_gem_syncobj_reset(struct anv_device *device, uint32_t handle);
 bool anv_gem_supports_syncobj_wait(int fd);
 int anv_gem_syncobj_wait(struct anv_device *device,
index a954f65f1d7a79dd558839fb6492679e91f1a8f4..429bac9739eaeba164cdb8534e01b47d0bb0d047 100644 (file)
@@ -688,11 +688,14 @@ void anv_GetPhysicalDeviceExternalFencePropertiesKHR(
 
    switch (pExternalFenceInfo->handleType) {
    case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
+   case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
       if (device->has_syncobj_wait) {
          pExternalFenceProperties->exportFromImportedHandleTypes =
-            VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+            VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR |
+            VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
          pExternalFenceProperties->compatibleHandleTypes =
-            VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+            VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR |
+            VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
          pExternalFenceProperties->externalFenceFeatures =
             VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR |
             VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR;
@@ -732,22 +735,41 @@ VkResult anv_ImportFenceFdKHR(
       if (!new_impl.syncobj)
          return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
 
-      /* From the Vulkan 1.0.53 spec:
-       *
-       *    "Importing a fence payload 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.
+      break;
+
+   case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
+      /* Sync files are a bit tricky.  Because we want to continue using the
+       * syncobj implementation of WaitForFences, we don't use the sync file
+       * directly but instead import it into a syncobj.
        */
-      close(fd);
+      new_impl.type = ANV_FENCE_TYPE_SYNCOBJ;
+
+      new_impl.syncobj = anv_gem_syncobj_create(device, 0);
+      if (!new_impl.syncobj)
+         return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+      if (anv_gem_syncobj_import_sync_file(device, new_impl.syncobj, fd)) {
+         anv_gem_syncobj_destroy(device, new_impl.syncobj);
+         return vk_errorf(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR,
+                          "syncobj sync file import failed: %m");
+      }
       break;
 
    default:
       return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
    }
 
+   /* From the Vulkan 1.0.53 spec:
+    *
+    *    "Importing a fence payload 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);
+
    if (pImportFenceFdInfo->flags & VK_FENCE_IMPORT_TEMPORARY_BIT_KHR) {
       anv_fence_impl_cleanup(device, &fence->temporary);
       fence->temporary = new_impl;
@@ -784,6 +806,15 @@ VkResult anv_GetFenceFdKHR(
       break;
    }
 
+   case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR: {
+      int fd = anv_gem_syncobj_export_sync_file(device, impl->syncobj);
+      if (fd < 0)
+         return vk_error(VK_ERROR_TOO_MANY_OBJECTS);
+
+      *pFd = fd;
+      break;
+   }
+
    default:
       unreachable("Invalid fence export handle type");
    }