From 43e8808b82b9ebaecde4a30984fef897c1a1a030 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Tue, 8 Aug 2017 15:17:31 -0700 Subject: [PATCH] anv: Add support for the SYNC_FD handle type for fences Reviewed-by: Lionel Landwerlin --- src/intel/vulkan/anv_gem.c | 28 +++++++++++++++++ src/intel/vulkan/anv_gem_stubs.c | 13 ++++++++ src/intel/vulkan/anv_private.h | 4 +++ src/intel/vulkan/anv_queue.c | 53 +++++++++++++++++++++++++------- 4 files changed, 87 insertions(+), 11 deletions(-) diff --git a/src/intel/vulkan/anv_gem.c b/src/intel/vulkan/anv_gem.c index 8283117cd0e..3994c6b66c2 100644 --- a/src/intel/vulkan/anv_gem.c +++ b/src/intel/vulkan/anv_gem.c @@ -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) { diff --git a/src/intel/vulkan/anv_gem_stubs.c b/src/intel/vulkan/anv_gem_stubs.c index 36700d7434c..02527b5fcd8 100644 --- a/src/intel/vulkan/anv_gem_stubs.c +++ b/src/intel/vulkan/anv_gem_stubs.c @@ -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) { diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index f9537c2b245..b30b71f3367 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -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, diff --git a/src/intel/vulkan/anv_queue.c b/src/intel/vulkan/anv_queue.c index a954f65f1d7..429bac9739e 100644 --- a/src/intel/vulkan/anv_queue.c +++ b/src/intel/vulkan/anv_queue.c @@ -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"); }