From 9ccc3daaf80794281049825b564f1be910035d58 Mon Sep 17 00:00:00 2001 From: Lucas Fryzek Date: Wed, 13 Mar 2024 14:53:33 -0400 Subject: [PATCH] lavapipe: Implement VK_KHR_external_*_fd Implement external sync fd extensions by plumbing into llvmpipe's implementation of `lp_create_fence_fd` and `lp_fence_get_fd`. Part-of: --- src/gallium/frontends/lavapipe/lvp_device.c | 50 ++++++++++++++++--- .../frontends/lavapipe/lvp_pipe_sync.c | 47 +++++++++++++++++ 2 files changed, 91 insertions(+), 6 deletions(-) diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index e6792279577..7b9a61bca71 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -1259,6 +1259,10 @@ lvp_physical_device_init(struct lvp_physical_device *device, device->vk.supported_extensions.EXT_external_memory_dma_buf = true; if ((supported_dmabuf_bits & dmabuf_bits) == dmabuf_bits) device->vk.supported_extensions.EXT_image_drm_format_modifier = true; + if (device->pscreen->get_param(device->pscreen, PIPE_CAP_NATIVE_FENCE_FD)) { + device->vk.supported_extensions.KHR_external_semaphore_fd = true; + device->vk.supported_extensions.KHR_external_fence_fd = true; + } #endif /* SNORM blending on llvmpipe fails CTS - disable by default */ @@ -2508,9 +2512,24 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceExternalFenceProperties( const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo, VkExternalFenceProperties *pExternalFenceProperties) { - pExternalFenceProperties->exportFromImportedHandleTypes = 0; - pExternalFenceProperties->compatibleHandleTypes = 0; - pExternalFenceProperties->externalFenceFeatures = 0; + LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice); + const VkExternalFenceHandleTypeFlagBits handle_type = pExternalFenceInfo->handleType; + + if (handle_type == VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT && + physical_device->pscreen->get_param( + physical_device->pscreen, PIPE_CAP_NATIVE_FENCE_FD)) { + pExternalFenceProperties->exportFromImportedHandleTypes = + VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; + pExternalFenceProperties->compatibleHandleTypes = + VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; + pExternalFenceProperties->externalFenceFeatures = + VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT | + VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT; + } else { + pExternalFenceProperties->exportFromImportedHandleTypes = 0; + pExternalFenceProperties->compatibleHandleTypes = 0; + pExternalFenceProperties->externalFenceFeatures = 0; + } } VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceExternalSemaphoreProperties( @@ -2518,9 +2537,28 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceExternalSemaphoreProperties( const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, VkExternalSemaphoreProperties *pExternalSemaphoreProperties) { - pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; - pExternalSemaphoreProperties->compatibleHandleTypes = 0; - pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; + LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice); + const VkSemaphoreTypeCreateInfo *type_info = + vk_find_struct_const(pExternalSemaphoreInfo->pNext, SEMAPHORE_TYPE_CREATE_INFO); + const VkSemaphoreType type = !type_info ? VK_SEMAPHORE_TYPE_BINARY : type_info->semaphoreType; + const VkExternalSemaphoreHandleTypeFlagBits handle_type = pExternalSemaphoreInfo->handleType; + + if (type == VK_SEMAPHORE_TYPE_BINARY && + handle_type == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT && + physical_device->pscreen->get_param( + physical_device->pscreen, PIPE_CAP_NATIVE_FENCE_FD)) { + pExternalSemaphoreProperties->exportFromImportedHandleTypes = + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; + pExternalSemaphoreProperties->compatibleHandleTypes = + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; + pExternalSemaphoreProperties->externalSemaphoreFeatures = + VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT | + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT; + } else { + pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; + pExternalSemaphoreProperties->compatibleHandleTypes = 0; + pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; + } } static const VkTimeDomainEXT lvp_time_domains[] = { diff --git a/src/gallium/frontends/lavapipe/lvp_pipe_sync.c b/src/gallium/frontends/lavapipe/lvp_pipe_sync.c index 20924a61b25..11dbb8a46af 100644 --- a/src/gallium/frontends/lavapipe/lvp_pipe_sync.c +++ b/src/gallium/frontends/lavapipe/lvp_pipe_sync.c @@ -23,6 +23,7 @@ #include "lvp_private.h" #include "util/timespec.h" +#include "vk_common_entrypoints.h" static void lvp_pipe_sync_validate(ASSERTED struct lvp_pipe_sync *sync) @@ -239,6 +240,48 @@ lvp_pipe_sync_wait(struct vk_device *vk_device, return result; } +#ifdef HAVE_LIBDRM +static VkResult +lvp_pipe_import_sync_file(struct vk_device *vk_device, + struct vk_sync *vk_sync, + int sync_file) +{ + struct lvp_device *device = container_of(vk_device, struct lvp_device, vk); + struct lvp_pipe_sync *sync = vk_sync_as_lvp_pipe_sync(vk_sync); + + struct pipe_fence_handle *fence; + device->queue.ctx->create_fence_fd( + device->queue.ctx, &fence, sync_file, PIPE_FD_TYPE_NATIVE_SYNC); + + if (fence == NULL) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + lvp_pipe_sync_signal_with_fence(device, sync, fence); + device->pscreen->fence_reference(device->pscreen, &fence, NULL); + + return VK_SUCCESS; +} + +static VkResult +lvp_pipe_export_sync_file(struct vk_device *vk_device, + struct vk_sync *vk_sync, + int *sync_file) +{ + struct lvp_pipe_sync *sync = vk_sync_as_lvp_pipe_sync(vk_sync); + + /* It's not ideal, but since we cannot properly support sync files + * from userspace, what we will do instead is wait for lavapipe to + * finish rendering, so that we can safely export a sync file that + * has already been signalled. + */ + vk_common_DeviceWaitIdle(vk_device_to_handle(vk_device)); + struct lvp_device *device = container_of(vk_device, struct lvp_device, vk); + *sync_file = device->pscreen->fence_get_fd(device->pscreen, sync->fence); + + return *sync_file != -1 ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY; +} +#endif + const struct vk_sync_type lvp_pipe_sync_type = { .size = sizeof(struct lvp_pipe_sync), .features = VK_SYNC_FEATURE_BINARY | @@ -254,4 +297,8 @@ const struct vk_sync_type lvp_pipe_sync_type = { .reset = lvp_pipe_sync_reset, .move = lvp_pipe_sync_move, .wait = lvp_pipe_sync_wait, +#ifdef HAVE_LIBDRM + .import_sync_file = lvp_pipe_import_sync_file, + .export_sync_file = lvp_pipe_export_sync_file, +#endif };