[Mesa-dev] [PATCH v3 4/8] anv: Implement support for exporting semaphores as FENCE_FD

Jason Ekstrand jason at jlekstrand.net
Mon Aug 14 16:17:38 UTC 2017


On Sun, Aug 13, 2017 at 4:37 AM, Lionel Landwerlin <
lionel.g.landwerlin at intel.com> wrote:

> On 04/08/17 18:24, Jason Ekstrand wrote:
>
>> ---
>>   src/intel/vulkan/anv_batch_chain.c | 57 +++++++++++++++++++++++++++++--
>>   src/intel/vulkan/anv_device.c      |  1 +
>>   src/intel/vulkan/anv_gem.c         | 36 ++++++++++++++++++++
>>   src/intel/vulkan/anv_private.h     | 23 +++++++++----
>>   src/intel/vulkan/anv_queue.c       | 69 ++++++++++++++++++++++++++++++
>> ++++++--
>>   5 files changed, 175 insertions(+), 11 deletions(-)
>>
>> diff --git a/src/intel/vulkan/anv_batch_chain.c
>> b/src/intel/vulkan/anv_batch_chain.c
>> index 65fe366..7a84bbd 100644
>> --- a/src/intel/vulkan/anv_batch_chain.c
>> +++ b/src/intel/vulkan/anv_batch_chain.c
>> @@ -1416,11 +1416,13 @@ anv_cmd_buffer_execbuf(struct anv_device *device,
>>      struct anv_execbuf execbuf;
>>      anv_execbuf_init(&execbuf);
>>   +   int in_fence = -1;
>>      VkResult result = VK_SUCCESS;
>>      for (uint32_t i = 0; i < num_in_semaphores; i++) {
>>         ANV_FROM_HANDLE(anv_semaphore, semaphore, in_semaphores[i]);
>> -      assert(semaphore->temporary.type == ANV_SEMAPHORE_TYPE_NONE);
>> -      struct anv_semaphore_impl *impl = &semaphore->permanent;
>> +      struct anv_semaphore_impl *impl =
>> +         semaphore->temporary.type != ANV_SEMAPHORE_TYPE_NONE ?
>> +         &semaphore->temporary : &semaphore->permanent;
>>
>
> I know you're not enabling this until patch 8, but for consistency,
> shouldn't this be part of patch 1?
>

Yup.  Fixed.


>           switch (impl->type) {
>>         case ANV_SEMAPHORE_TYPE_BO:
>> @@ -1429,11 +1431,29 @@ anv_cmd_buffer_execbuf(struct anv_device *device,
>>            if (result != VK_SUCCESS)
>>               return result;
>>            break;
>> +
>> +      case ANV_SEMAPHORE_TYPE_SYNC_FILE:
>> +         if (in_fence == -1) {
>> +            in_fence = impl->fd;
>> +         } else {
>> +            int merge = anv_gem_sync_file_merge(device, in_fence,
>> impl->fd);
>> +            if (merge == -1)
>> +               return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
>> +
>> +            close(impl->fd);
>> +            close(in_fence);
>> +            in_fence = merge;
>> +         }
>> +
>> +         impl->fd = -1;
>> +         break;
>> +
>>         default:
>>            break;
>>         }
>>      }
>>   +   bool need_out_fence = false;
>>      for (uint32_t i = 0; i < num_out_semaphores; i++) {
>>         ANV_FROM_HANDLE(anv_semaphore, semaphore, out_semaphores[i]);
>>   @@ -1459,6 +1479,11 @@ anv_cmd_buffer_execbuf(struct anv_device *device,
>>            if (result != VK_SUCCESS)
>>               return result;
>>            break;
>> +
>> +      case ANV_SEMAPHORE_TYPE_SYNC_FILE:
>> +         need_out_fence = true;
>> +         break;
>> +
>>         default:
>>            break;
>>         }
>> @@ -1472,9 +1497,19 @@ anv_cmd_buffer_execbuf(struct anv_device *device,
>>         setup_empty_execbuf(&execbuf, device);
>>      }
>>   +   if (in_fence != -1) {
>> +      execbuf.execbuf.flags |= I915_EXEC_FENCE_IN;
>> +      execbuf.execbuf.rsvd2 |= (uint32_t)in_fence;
>> +   }
>> +
>> +   if (need_out_fence)
>> +      execbuf.execbuf.flags |= I915_EXEC_FENCE_OUT;
>>        result = anv_device_execbuf(device, &execbuf.execbuf, execbuf.bos);
>>   +   /* Execbuf does not consume the in_fence.  It's our job to close
>> it. */
>> +   close(in_fence);
>> +
>>      for (uint32_t i = 0; i < num_in_semaphores; i++) {
>>         ANV_FROM_HANDLE(anv_semaphore, semaphore, in_semaphores[i]);
>>         /* From the Vulkan 1.0.53 spec:
>> @@ -1489,6 +1524,24 @@ anv_cmd_buffer_execbuf(struct anv_device *device,
>>         anv_semaphore_reset_temporary(device, semaphore);
>>      }
>>   +   if (result == VK_SUCCESS && need_out_fence) {
>> +      int out_fence = execbuf.execbuf.rsvd2 >> 32;
>> +      for (uint32_t i = 0; i < num_out_semaphores; i++) {
>> +         ANV_FROM_HANDLE(anv_semaphore, semaphore, out_semaphores[i]);
>> +         /* Out fences can't have temporary state because that would
>> imply
>> +          * that we imported a sync file and are trying to signal it.
>> +          */
>> +         assert(semaphore->temporary.type == ANV_SEMAPHORE_TYPE_NONE);
>> +         struct anv_semaphore_impl *impl = &semaphore->permanent;
>> +
>> +         if (impl->type == ANV_SEMAPHORE_TYPE_SYNC_FILE) {
>> +            assert(impl->fd == -1);
>> +            impl->fd = dup(out_fence);
>> +         }
>> +      }
>> +      close(out_fence);
>> +   }
>> +
>>      anv_execbuf_finish(&execbuf, &device->alloc);
>>        return result;
>> diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.
>> c
>> index e82e1e9..3c5f78c 100644
>> --- a/src/intel/vulkan/anv_device.c
>> +++ b/src/intel/vulkan/anv_device.c
>> @@ -337,6 +337,7 @@ anv_physical_device_init(struct anv_physical_device
>> *device,
>>         goto fail;
>>        device->has_exec_async = anv_gem_get_param(fd,
>> I915_PARAM_HAS_EXEC_ASYNC);
>> +   device->has_exec_fence = anv_gem_get_param(fd,
>> I915_PARAM_HAS_EXEC_FENCE);
>>        bool swizzled = anv_gem_get_bit6_swizzle(fd, I915_TILING_X);
>>   diff --git a/src/intel/vulkan/anv_gem.c b/src/intel/vulkan/anv_gem.c
>> index 36692f5..5b68e9b 100644
>> --- a/src/intel/vulkan/anv_gem.c
>> +++ b/src/intel/vulkan/anv_gem.c
>> @@ -22,6 +22,7 @@
>>    */
>>     #include <sys/ioctl.h>
>> +#include <sys/types.h>
>>   #include <sys/mman.h>
>>   #include <string.h>
>>   #include <errno.h>
>> @@ -400,3 +401,38 @@ anv_gem_fd_to_handle(struct anv_device *device, int
>> fd)
>>        return args.handle;
>>   }
>> +
>> +#ifndef SYNC_IOC_MAGIC
>> +/* duplicated from linux/sync_file.h to avoid build-time depnedency
>>
>
> nit: dependency
>

Fixed.


> + * on new (v4.7) kernel headers.  Once distro's are mostly using
>> + * something newer than v4.7 drop this and #include <linux/sync_file.h>
>> + * instead.
>> + */
>> +struct sync_merge_data {
>> +   char  name[32];
>> +   __s32 fd2;
>> +   __s32 fence;
>> +   __u32 flags;
>> +   __u32 pad;
>> +};
>> +
>> +#define SYNC_IOC_MAGIC '>'
>> +#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data)
>> +#endif
>> +
>> +int
>> +anv_gem_sync_file_merge(struct anv_device *device, int fd1, int fd2)
>> +{
>> +   const char name[] = "anv merge fence";
>> +   struct sync_merge_data args = {
>> +      .fd2 = fd2,
>> +      .fence = -1,
>> +   };
>> +   memcpy(args.name, name, sizeof(name));
>> +
>> +   int ret = anv_ioctl(fd1, SYNC_IOC_MERGE, &args);
>> +   if (ret == -1)
>> +      return -1;
>> +
>> +   return args.fence;
>> +}
>> diff --git a/src/intel/vulkan/anv_private.h
>> b/src/intel/vulkan/anv_private.h
>> index bc67bb6..5c7b3b4 100644
>> --- a/src/intel/vulkan/anv_private.h
>> +++ b/src/intel/vulkan/anv_private.h
>> @@ -652,6 +652,7 @@ struct anv_physical_device {
>>       struct isl_device                           isl_dev;
>>       int                                         cmd_parser_version;
>>       bool                                        has_exec_async;
>> +    bool                                        has_exec_fence;
>>         uint32_t                                    eu_total;
>>       uint32_t                                    subslice_total;
>> @@ -810,6 +811,7 @@ uint32_t anv_gem_fd_to_handle(struct anv_device
>> *device, int fd);
>>   int anv_gem_set_caching(struct anv_device *device, uint32_t gem_handle,
>> uint32_t caching);
>>   int anv_gem_set_domain(struct anv_device *device, uint32_t gem_handle,
>>                          uint32_t read_domains, uint32_t write_domain);
>> +int anv_gem_sync_file_merge(struct anv_device *device, int fd1, int fd2);
>>     VkResult anv_bo_init_new(struct anv_bo *bo, struct anv_device
>> *device, uint64_t size);
>>   @@ -1735,17 +1737,26 @@ enum anv_semaphore_type {
>>      ANV_SEMAPHORE_TYPE_NONE = 0,
>>      ANV_SEMAPHORE_TYPE_DUMMY,
>>      ANV_SEMAPHORE_TYPE_BO,
>> +   ANV_SEMAPHORE_TYPE_SYNC_FILE,
>>   };
>>     struct anv_semaphore_impl {
>>      enum anv_semaphore_type type;
>>   -   /* A BO representing this semaphore when type ==
>> ANV_SEMAPHORE_TYPE_BO.
>> -    * This BO will be added to the object list on any execbuf2 calls for
>> -    * which this semaphore is used as a wait or signal fence.  When used
>> as
>> -    * a signal fence, the EXEC_OBJECT_WRITE flag will be set.
>> -    */
>> -   struct anv_bo *bo;
>> +   union {
>> +      /* A BO representing this semaphore when type ==
>> ANV_SEMAPHORE_TYPE_BO.
>> +       * This BO will be added to the object list on any execbuf2 calls
>> for
>> +       * which this semaphore is used as a wait or signal fence.  When
>> used as
>> +       * a signal fence, the EXEC_OBJECT_WRITE flag will be set.
>> +       */
>> +      struct anv_bo *bo;
>> +
>> +      /* The sync file descriptor when type ==
>> AKV_SEMAPHORE_TYPE_SYNC_FILE.
>> +       * If the semaphore is in the unsignaled state due to either just
>> being
>> +       * created or because it has been used for a wait, fd will be -1.
>> +       */
>> +      int fd;
>> +   };
>>   };
>>     struct anv_semaphore {
>> diff --git a/src/intel/vulkan/anv_queue.c b/src/intel/vulkan/anv_queue.c
>> index 039dfd7..1f27028 100644
>> --- a/src/intel/vulkan/anv_queue.c
>> +++ b/src/intel/vulkan/anv_queue.c
>> @@ -571,6 +571,11 @@ VkResult anv_CreateSemaphore(
>>          * EXEC_OBJECT_ASYNC bit set.
>>          */
>>         assert(!(semaphore->permanent.bo->flags & EXEC_OBJECT_ASYNC));
>> +   } else if (handleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR)
>> {
>> +      assert(handleTypes == VK_EXTERNAL_SEMAPHORE_HANDLE_T
>> YPE_SYNC_FD_BIT_KHR);
>> +
>> +      semaphore->permanent.type = ANV_SEMAPHORE_TYPE_SYNC_FILE;
>> +      semaphore->permanent.fd = -1;
>>      } else {
>>         assert(!"Unknown handle type");
>>         vk_free2(&device->alloc, pAllocator, semaphore);
>> @@ -597,6 +602,10 @@ anv_semaphore_impl_cleanup(struct anv_device
>> *device,
>>      case ANV_SEMAPHORE_TYPE_BO:
>>         anv_bo_cache_release(device, &device->bo_cache, impl->bo);
>>         return;
>> +
>> +   case ANV_SEMAPHORE_TYPE_SYNC_FILE:
>> +      close(impl->fd);
>> +      return;
>>      }
>>        unreachable("Invalid semaphore type");
>> @@ -635,6 +644,8 @@ void anv_GetPhysicalDeviceExternalS
>> emaphorePropertiesKHR(
>>       const VkPhysicalDeviceExternalSemaphoreInfoKHR*
>> pExternalSemaphoreInfo,
>>       VkExternalSemaphorePropertiesKHR*
>>  pExternalSemaphoreProperties)
>>   {
>> +   ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
>> +
>>      switch (pExternalSemaphoreInfo->handleType) {
>>      case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
>>         pExternalSemaphoreProperties->exportFromImportedHandleTypes =
>> @@ -644,13 +655,27 @@ void anv_GetPhysicalDeviceExternalS
>> emaphorePropertiesKHR(
>>         pExternalSemaphoreProperties->externalSemaphoreFeatures =
>>            VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR |
>>            VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR;
>> +      return;
>> +
>> +   case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
>> +      if (device->has_exec_fence) {
>> +         pExternalSemaphoreProperties->exportFromImportedHandleTypes =
>> 0;
>> +         pExternalSemaphoreProperties->compatibleHandleTypes =
>> +            VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
>> +         pExternalSemaphoreProperties->externalSemaphoreFeatures =
>> +            VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR |
>> +            VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR;
>> +         return;
>> +      }
>>         break;
>>        default:
>> -      pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
>> -      pExternalSemaphoreProperties->compatibleHandleTypes = 0;
>> -      pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
>> +      break;
>>      }
>> +
>> +   pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
>> +   pExternalSemaphoreProperties->compatibleHandleTypes = 0;
>> +   pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
>>   }
>>     VkResult anv_ImportSemaphoreFdKHR(
>> @@ -682,6 +707,13 @@ VkResult anv_ImportSemaphoreFdKHR(
>>         break;
>>      }
>>   +   case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
>> +      new_impl = (struct anv_semaphore_impl) {
>> +         .type = ANV_SEMAPHORE_TYPE_SYNC_FILE,
>> +         .fd = fd,
>> +      };
>> +      break;
>> +
>>      default:
>>         return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
>>      }
>> @@ -690,6 +722,9 @@ VkResult anv_ImportSemaphoreFdKHR(
>>         anv_semaphore_impl_cleanup(device, &semaphore->temporary);
>>         semaphore->temporary = new_impl;
>>      } else {
>> +      /* SYNC_FILE must be a temporary import */
>> +      assert(new_impl.type != ANV_SEMAPHORE_TYPE_SYNC_FILE);
>> +
>>         anv_semaphore_impl_cleanup(device, &semaphore->permanent);
>>         semaphore->permanent = new_impl;
>>      }
>> @@ -719,6 +754,34 @@ VkResult anv_GetSemaphoreFdKHR(
>>            return result;
>>         break;
>>   +   case ANV_SEMAPHORE_TYPE_SYNC_FILE:
>> +      /* There are two reasons why this could happen:
>> +       *
>> +       *  1) The user is trying to export without submitting something
>> that
>> +       *     signals the semaphore.  If this is the case, it's their bug
>> so
>> +       *     what we return here doesn't matter.
>> +       *
>> +       *  2) The kernel didn't give us a file descriptor.  The most
>> likely
>> +       *     reason for this is running out of file descriptors.
>> +       */
>> +      if (impl->fd < 0)
>> +         return vk_error(VK_ERROR_TOO_MANY_OBJECTS);
>> +
>> +      *pFd = impl->fd;
>> +
>> +      /* From the Vulkan 1.0.53 spec:
>> +       *
>> +       *    "...exporting a semaphore payload to a handle with copy
>> +       *    transference has the same side effects on the source
>> +       *    semaphore’s payload as executing a semaphore wait operation."
>> +       *
>> +       * In other words, it may still be a SYNC_FD semaphore, but it's
>> now
>> +       * considered to have been waited on and no longer has a sync file
>> +       * attached.
>> +       */
>> +      impl->fd = -1;
>> +      return VK_SUCCESS;
>> +
>>      default:
>>         return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
>>      }
>>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170814/8087fc5e/attachment-0001.html>


More information about the mesa-dev mailing list