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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28735>
This commit is contained in:
Lucas Fryzek 2024-03-13 14:53:33 -04:00 committed by Marge Bot
parent d21aa86b54
commit 9ccc3daaf8
2 changed files with 91 additions and 6 deletions

View file

@ -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[] = {

View file

@ -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
};