diff options
author | Jason Ekstrand <[email protected]> | 2017-02-15 17:25:46 -0800 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2017-05-03 15:09:46 -0700 |
commit | 4201cc2dd3aaa4b6c15c52037b3a6413274082ec (patch) | |
tree | 0038fcf65886bcb383c3e96d25fd42e59f32e3e2 /src/intel/vulkan/anv_queue.c | |
parent | ef2e427d783b5c192e9ec5c25613c8a992bfc79b (diff) |
anv: Implement VK_KHX_external_semaphore_fd
This implementation allocates a 4k BO for each semaphore that can be
exported using OPAQUE_FD and uses the kernel's already-existing
synchronization mechanism on BOs.
Reviewed-by: Chad Versace <[email protected]>
Diffstat (limited to 'src/intel/vulkan/anv_queue.c')
-rw-r--r-- | src/intel/vulkan/anv_queue.c | 141 |
1 files changed, 133 insertions, 8 deletions
diff --git a/src/intel/vulkan/anv_queue.c b/src/intel/vulkan/anv_queue.c index 64c59006ca8..fac979a52c0 100644 --- a/src/intel/vulkan/anv_queue.c +++ b/src/intel/vulkan/anv_queue.c @@ -25,6 +25,10 @@ * This file implements VkQueue, VkFence, and VkSemaphore */ +#include <fcntl.h> +#include <unistd.h> +#include <sys/eventfd.h> + #include "anv_private.h" #include "util/vk_util.h" @@ -161,7 +165,23 @@ VkResult anv_QueueSubmit( assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY); assert(!anv_batch_has_error(&cmd_buffer->batch)); - result = anv_cmd_buffer_execbuf(device, cmd_buffer); + const VkSemaphore *in_semaphores = NULL, *out_semaphores = NULL; + uint32_t num_in_semaphores = 0, num_out_semaphores = 0; + if (j == 0) { + /* Only the first batch gets the in semaphores */ + in_semaphores = pSubmits[i].pWaitSemaphores; + num_in_semaphores = pSubmits[i].waitSemaphoreCount; + } + + if (j == pSubmits[i].commandBufferCount - 1) { + /* Only the last batch gets the out semaphores */ + out_semaphores = pSubmits[i].pSignalSemaphores; + num_out_semaphores = pSubmits[i].signalSemaphoreCount; + } + + result = anv_cmd_buffer_execbuf(device, cmd_buffer, + in_semaphores, num_in_semaphores, + out_semaphores, num_out_semaphores); if (result != VK_SUCCESS) goto out; } @@ -513,14 +533,33 @@ VkResult anv_CreateSemaphore( VkExternalSemaphoreHandleTypeFlagsKHX handleTypes = export ? export->handleTypes : 0; - /* External semaphores are not yet supported */ - assert(handleTypes == 0); + if (handleTypes == 0) { + /* The DRM execbuffer ioctl always execute in-oder so long as you stay + * on the same ring. Since we don't expose the blit engine as a DMA + * queue, a dummy no-op semaphore is a perfectly valid implementation. + */ + 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); + + 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; + } else { + assert(!"Unknown handle type"); + vk_free2(&device->alloc, pAllocator, semaphore); + return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX); + } - /* The DRM execbuffer ioctl always execute in-oder, even between - * different rings. As such, a dummy no-op semaphore is a perfectly - * valid implementation. - */ - semaphore->permanent.type = ANV_SEMAPHORE_TYPE_DUMMY; semaphore->temporary.type = ANV_SEMAPHORE_TYPE_NONE; *pSemaphore = anv_semaphore_to_handle(semaphore); @@ -528,6 +567,24 @@ VkResult anv_CreateSemaphore( return VK_SUCCESS; } +static void +anv_semaphore_impl_cleanup(struct anv_device *device, + struct anv_semaphore_impl *impl) +{ + switch (impl->type) { + case ANV_SEMAPHORE_TYPE_NONE: + case ANV_SEMAPHORE_TYPE_DUMMY: + /* Dummy. Nothing to do */ + return; + + case ANV_SEMAPHORE_TYPE_BO: + anv_bo_cache_release(device, &device->bo_cache, impl->bo); + return; + } + + unreachable("Invalid semaphore type"); +} + void anv_DestroySemaphore( VkDevice _device, VkSemaphore _semaphore, @@ -539,6 +596,9 @@ void anv_DestroySemaphore( if (semaphore == NULL) return; + anv_semaphore_impl_cleanup(device, &semaphore->temporary); + anv_semaphore_impl_cleanup(device, &semaphore->permanent); + vk_free2(&device->alloc, pAllocator, semaphore); } @@ -548,9 +608,74 @@ void anv_GetPhysicalDeviceExternalSemaphorePropertiesKHX( VkExternalSemaphorePropertiesKHX* pExternalSemaphoreProperties) { switch (pExternalSemaphoreInfo->handleType) { + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX: + pExternalSemaphoreProperties->exportFromImportedHandleTypes = + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX; + pExternalSemaphoreProperties->compatibleHandleTypes = + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX; + pExternalSemaphoreProperties->externalSemaphoreFeatures = + VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHX | + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHX; + break; + default: pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; pExternalSemaphoreProperties->compatibleHandleTypes = 0; pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; } } + +VkResult anv_ImportSemaphoreFdKHX( + VkDevice _device, + const VkImportSemaphoreFdInfoKHX* pImportSemaphoreFdInfo) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + ANV_FROM_HANDLE(anv_semaphore, semaphore, pImportSemaphoreFdInfo->semaphore); + + 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 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; + } + + default: + return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX); + } +} + +VkResult anv_GetSemaphoreFdKHX( + VkDevice _device, + VkSemaphore _semaphore, + VkExternalSemaphoreHandleTypeFlagBitsKHX handleType, + int* pFd) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + ANV_FROM_HANDLE(anv_semaphore, semaphore, _semaphore); + + switch (semaphore->permanent.type) { + case ANV_SEMAPHORE_TYPE_BO: + return anv_bo_cache_export(device, &device->bo_cache, + semaphore->permanent.bo, pFd); + + default: + return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX); + } + + return VK_SUCCESS; +} |