--- src/intel/vulkan/anv_batch_chain.c | 69 ++++++++++++++++++++++++++++ src/intel/vulkan/anv_device.c | 2 + src/intel/vulkan/anv_private.h | 8 ++++ src/intel/vulkan/anv_queue.c | 93 ++++++++++++++++++++++++++++---------- 4 files changed, 148 insertions(+), 24 deletions(-)
diff --git a/src/intel/vulkan/anv_batch_chain.c b/src/intel/vulkan/anv_batch_chain.c index ec37c81..0f118c8 100644 --- a/src/intel/vulkan/anv_batch_chain.c +++ b/src/intel/vulkan/anv_batch_chain.c @@ -953,6 +953,19 @@ anv_cmd_buffer_add_secondary(struct anv_cmd_buffer *primary, &secondary->surface_relocs, 0); } +struct drm_i915_gem_exec_fence { + /** + * User's handle for a dma-fence to wait on or signal. + */ + __u32 handle; + +#define I915_EXEC_FENCE_WAIT (1<<0) +#define I915_EXEC_FENCE_SIGNAL (1<<1) + __u32 flags; +}; + +#define I915_EXEC_FENCE_ARRAY (1<<19) + struct anv_execbuf { struct drm_i915_gem_execbuffer2 execbuf; @@ -962,6 +975,10 @@ struct anv_execbuf { /* Allocated length of the 'objects' and 'bos' arrays */ uint32_t array_length; + + uint32_t fence_count; + uint32_t fence_array_length; + struct drm_i915_gem_exec_fence * fences; }; static void @@ -976,6 +993,7 @@ anv_execbuf_finish(struct anv_execbuf *exec, { vk_free(alloc, exec->objects); vk_free(alloc, exec->bos); + vk_free(alloc, exec->fences); } static VkResult @@ -1061,6 +1079,35 @@ anv_execbuf_add_bo(struct anv_execbuf *exec, return VK_SUCCESS; } +static VkResult +anv_execbuf_add_syncobj(struct anv_execbuf *exec, + uint32_t handle, + uint32_t flags, + const VkAllocationCallbacks *alloc) +{ + if (exec->fence_count >= exec->fence_array_length) { + uint32_t new_len = MAX2(exec->fence_array_length * 2, 64); + + struct drm_i915_gem_exec_fence *new_fences = + vk_realloc(alloc, exec->fences, new_len * sizeof(*new_fences), + 8, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (new_fences == NULL) + return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + + exec->fences = new_fences; + exec->fence_array_length = new_len; + } + + exec->fences[exec->fence_count] = (struct drm_i915_gem_exec_fence) { + .handle = handle, + .flags = flags, + }; + + exec->fence_count++; + + return VK_SUCCESS; +} + static void anv_cmd_buffer_process_relocs(struct anv_cmd_buffer *cmd_buffer, struct anv_reloc_list *list) @@ -1447,6 +1494,14 @@ anv_cmd_buffer_execbuf(struct anv_device *device, impl->fd = -1; break; + case ANV_SEMAPHORE_TYPE_DRM_SYNCOBJ: + result = anv_execbuf_add_syncobj(&execbuf, impl->syncobj, + I915_EXEC_FENCE_WAIT, + &device->alloc); + if (result != VK_SUCCESS) + return result; + break; + default: break; } @@ -1481,6 +1536,14 @@ anv_cmd_buffer_execbuf(struct anv_device *device, need_out_fence = true; break; + case ANV_SEMAPHORE_TYPE_DRM_SYNCOBJ: + result = anv_execbuf_add_syncobj(&execbuf, impl->syncobj, + I915_EXEC_FENCE_SIGNAL, + &device->alloc); + if (result != VK_SUCCESS) + return result; + break; + default: break; } @@ -1494,6 +1557,12 @@ anv_cmd_buffer_execbuf(struct anv_device *device, setup_empty_execbuf(&execbuf, device); } + if (execbuf.fence_count > 0) { + execbuf.execbuf.flags |= I915_EXEC_FENCE_ARRAY; + execbuf.execbuf.num_cliprects = execbuf.fence_count; + execbuf.execbuf.cliprects_ptr = (uintptr_t) execbuf.fences; + } + if (in_fence != -1) { execbuf.execbuf.flags |= I915_EXEC_FENCE_IN; execbuf.execbuf.rsvd2 |= (uint32_t)in_fence; diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index f853905..13d01d1 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -233,6 +233,8 @@ anv_physical_device_init(struct anv_physical_device *device, 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); + device->has_syncobj = + anv_gem_get_param(fd, 47 /* I915_PARAM_HAS_EXEC_FENCE_ARRAY */); bool swizzled = anv_gem_get_bit6_swizzle(fd, I915_TILING_X); diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index d1406ab..0731e89 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -648,6 +648,7 @@ struct anv_physical_device { int cmd_parser_version; bool has_exec_async; bool has_exec_fence; + bool has_syncobj; uint32_t eu_total; uint32_t subslice_total; @@ -1724,6 +1725,7 @@ enum anv_semaphore_type { ANV_SEMAPHORE_TYPE_DUMMY, ANV_SEMAPHORE_TYPE_BO, ANV_SEMAPHORE_TYPE_SYNC_FILE, + ANV_SEMAPHORE_TYPE_DRM_SYNCOBJ, }; struct anv_semaphore_impl { @@ -1742,6 +1744,12 @@ struct anv_semaphore_impl { * created or because it has been used for a wait, fd will be -1. */ int fd; + + /* Sync object handle when type == AKV_SEMAPHORE_TYPE_DRM_SYNCOBJ. + * Unlike GEM BOs, DRM sync objects aren't deduplicated by the kernel on + * import so we don't need to bother with a userspace cache. + */ + uint32_t syncobj; }; }; diff --git a/src/intel/vulkan/anv_queue.c b/src/intel/vulkan/anv_queue.c index e7c8ef5..c7c527f 100644 --- a/src/intel/vulkan/anv_queue.c +++ b/src/intel/vulkan/anv_queue.c @@ -558,19 +558,28 @@ VkResult anv_CreateSemaphore( semaphore->permanent.type = ANV_SEMAPHORE_TYPE_DUMMY; } else if (handleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX) { assert(handleTypes == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX); + if (device->instance->physicalDevice.has_syncobj) { + semaphore->permanent.type = ANV_SEMAPHORE_TYPE_DRM_SYNCOBJ; + semaphore->permanent.syncobj = anv_gem_syncobj_create(device); + if (!semaphore->permanent.syncobj) { + vk_free2(&device->alloc, pAllocator, semaphore); + return vk_errorf(VK_ERROR_TOO_MANY_OBJECTS, + "drm_syncobj_create failed: %m"); + } + } else { + semaphore->permanent.type = ANV_SEMAPHORE_TYPE_BO; + VkResult result = anv_bo_cache_alloc(device, &device->bo_cache, + 4096, &semaphore->permanent.bo); + if (result != VK_SUCCESS) { + vk_free2(&device->alloc, pAllocator, semaphore); + return result; + } - semaphore->permanent.type = ANV_SEMAPHORE_TYPE_BO; - VkResult result = anv_bo_cache_alloc(device, &device->bo_cache, - 4096, &semaphore->permanent.bo); - if (result != VK_SUCCESS) { - vk_free2(&device->alloc, pAllocator, semaphore); - return result; + /* If we're going to use this as a fence, we need to *not* have the + * EXEC_OBJECT_ASYNC bit set. + */ + semaphore->permanent.bo->flags &= ~EXEC_OBJECT_ASYNC; } - - /* If we're going to use this as a fence, we need to *not* have the - * EXEC_OBJECT_ASYNC bit set. - */ - semaphore->permanent.bo->flags &= ~EXEC_OBJECT_ASYNC; } else if (handleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHX) { assert(handleTypes == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHX); @@ -607,6 +616,10 @@ anv_semaphore_impl_cleanup(struct anv_device *device, close(impl->fd); break; + case ANV_SEMAPHORE_TYPE_DRM_SYNCOBJ: + anv_gem_syncobj_close(device, impl->syncobj); + break; + default: unreachable("Invalid semaphore type"); } @@ -676,22 +689,45 @@ VkResult anv_ImportSemaphoreFdKHX( switch (pImportSemaphoreFdInfo->handleType) { case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX: { - struct anv_bo *bo; - VkResult result = anv_bo_cache_import(device, &device->bo_cache, - pImportSemaphoreFdInfo->fd, 4096, - &bo); - if (result != VK_SUCCESS) - return result; + if (device->instance->physicalDevice.has_syncobj) { + uint32_t handle = + anv_gem_syncobj_fd_to_handle(device, pImportSemaphoreFdInfo->fd); + if (!handle) { + return vk_errorf(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX, + "drm_syncobj_fd_to_handle failed: %m"); + } - /* If we're going to use this as a fence, we need to *not* have the - * EXEC_OBJECT_ASYNC bit set. - */ - bo->flags &= ~EXEC_OBJECT_ASYNC; + /* From the Vulkan spec: + * + * "Importing semaphore state 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(pImportSemaphoreFdInfo->fd); - anv_semaphore_impl_cleanup(device, &semaphore->permanent); + semaphore->permanent.type = ANV_SEMAPHORE_TYPE_DRM_SYNCOBJ; + semaphore->permanent.syncobj = handle; + } else { + struct anv_bo *bo; + VkResult result = anv_bo_cache_import(device, &device->bo_cache, + pImportSemaphoreFdInfo->fd, 4096, + &bo); + if (result != VK_SUCCESS) + return result; - semaphore->permanent.type = ANV_SEMAPHORE_TYPE_BO; - semaphore->permanent.bo = bo; + /* If we're going to use this as a fence, we need to *not* have the + * EXEC_OBJECT_ASYNC bit set. + */ + bo->flags &= ~EXEC_OBJECT_ASYNC; + + anv_semaphore_impl_cleanup(device, &semaphore->permanent); + + semaphore->permanent.type = ANV_SEMAPHORE_TYPE_BO; + semaphore->permanent.bo = bo; + } return VK_SUCCESS; } @@ -717,6 +753,7 @@ VkResult anv_GetSemaphoreFdKHX( { ANV_FROM_HANDLE(anv_device, device, _device); ANV_FROM_HANDLE(anv_semaphore, semaphore, _semaphore); + int fd; switch (semaphore->permanent.type) { case ANV_SEMAPHORE_TYPE_BO: @@ -740,6 +777,14 @@ VkResult anv_GetSemaphoreFdKHX( semaphore->permanent.fd = -1; return VK_SUCCESS; + case ANV_SEMAPHORE_TYPE_DRM_SYNCOBJ: + fd = anv_gem_syncobj_handle_to_fd(device, semaphore->permanent.syncobj); + if (fd < 0) + return vk_errorf(VK_ERROR_TOO_MANY_OBJECTS, + "drm_syncobj_handle_to_fd failed: %m"); + *pFd = fd; + return VK_SUCCESS; + default: return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX); } -- 2.5.0.400.gff86faf _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev