From: Jesse Natalie Date: Fri, 5 May 2023 04:06:41 +0000 (-0700) Subject: vulkan: Win32 sync import/export support X-Git-Tag: upstream/23.3.3~8644 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c9146794d4acd3600613e6df7c90257fdce8de23;p=platform%2Fupstream%2Fmesa.git vulkan: Win32 sync import/export support Acked-by: Alyssa Rosenzweig Part-of: --- diff --git a/src/vulkan/runtime/vk_semaphore.c b/src/vulkan/runtime/vk_semaphore.c index a008384..abae89c 100644 --- a/src/vulkan/runtime/vk_semaphore.c +++ b/src/vulkan/runtime/vk_semaphore.c @@ -25,7 +25,9 @@ #include "util/os_time.h" -#ifndef _WIN32 +#ifdef _WIN32 +#include +#else #include #endif @@ -47,6 +49,12 @@ vk_sync_semaphore_import_types(const struct vk_sync_type *type, if (type->export_sync_file && semaphore_type == VK_SEMAPHORE_TYPE_BINARY) handle_types |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; + if (type->import_win32_handle) { + handle_types |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT; + if (type->features & VK_SYNC_FEATURE_TIMELINE) + handle_types |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT; + } + return handle_types; } @@ -62,6 +70,12 @@ vk_sync_semaphore_export_types(const struct vk_sync_type *type, if (type->export_sync_file && semaphore_type == VK_SEMAPHORE_TYPE_BINARY) handle_types |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; + if (type->export_win32_handle) { + handle_types |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT; + if (type->features & VK_SYNC_FEATURE_TIMELINE) + handle_types |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT; + } + return handle_types; } @@ -184,6 +198,20 @@ vk_common_CreateSemaphore(VkDevice _device, return result; } +#ifdef _WIN32 + const VkExportSemaphoreWin32HandleInfoKHR *export_win32 = + vk_find_struct_const(pCreateInfo->pNext, EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR); + if (export_win32) { + result = vk_sync_set_win32_export_params(device, &semaphore->permanent, export_win32->pAttributes, + export_win32->dwAccess, export_win32->name); + if (result != VK_SUCCESS) { + vk_sync_finish(device, &semaphore->permanent); + vk_object_free(device, pAllocator, semaphore); + return result; + } + } +#endif + *pSemaphore = vk_semaphore_to_handle(semaphore); return VK_SUCCESS; @@ -247,18 +275,23 @@ vk_common_GetPhysicalDeviceExternalSemaphoreProperties( VkExternalSemaphoreHandleTypeFlagBits export = vk_sync_semaphore_export_types(sync_type, semaphore_type); - if (handle_type != VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) { - const struct vk_sync_type *opaque_sync_type = - get_semaphore_sync_type(pdevice, semaphore_type, - VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT); - - /* If we're a different vk_sync_type than the one selected when only - * OPAQUE_FD is set, then we can't import/export OPAQUE_FD. Put - * differently, there can only be one OPAQUE_FD sync type. - */ - if (sync_type != opaque_sync_type) { - import &= ~VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; - export &= ~VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; + VkExternalSemaphoreHandleTypeFlagBits opaque_types[] = { + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT, + }; + for (uint32_t i = 0; i < ARRAY_SIZE(opaque_types); ++i) { + if (handle_type != opaque_types[i]) { + const struct vk_sync_type *opaque_sync_type = + get_semaphore_sync_type(pdevice, semaphore_type, opaque_types[i]); + + /* If we're a different vk_sync_type than the one selected when only + * an opaque type is set, then we can't import/export that opaque type. Put + * differently, there can only be one OPAQUE_FD/WIN32_HANDLE sync type. + */ + if (sync_type != opaque_sync_type) { + import &= ~opaque_types[i]; + export &= ~opaque_types[i]; + } } } @@ -380,7 +413,123 @@ vk_common_SignalSemaphore(VkDevice _device, return VK_SUCCESS; } -#ifndef _WIN32 +#ifdef _WIN32 + +VKAPI_ATTR VkResult VKAPI_CALL +vk_common_ImportSemaphoreWin32HandleKHR(VkDevice _device, + const VkImportSemaphoreWin32HandleInfoKHR *pImportSemaphoreWin32HandleInfo) +{ + VK_FROM_HANDLE(vk_device, device, _device); + VK_FROM_HANDLE(vk_semaphore, semaphore, pImportSemaphoreWin32HandleInfo->semaphore); + + assert(pImportSemaphoreWin32HandleInfo->sType == + VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR); + + const HANDLE handle = pImportSemaphoreWin32HandleInfo->handle; + const wchar_t *name = pImportSemaphoreWin32HandleInfo->name; + const VkExternalSemaphoreHandleTypeFlagBits handle_type = + pImportSemaphoreWin32HandleInfo->handleType; + + struct vk_sync *temporary = NULL, *sync; + if (pImportSemaphoreWin32HandleInfo->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT) { + /* From the Vulkan 1.2.194 spec: + * + * VUID-VkImportSemaphoreWin32HandleInfoKHR-flags-03322 + * + * "If flags contains VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, the + * VkSemaphoreTypeCreateInfo::semaphoreType field of the semaphore + * from which handle or name was exported must not be + * VK_SEMAPHORE_TYPE_TIMELINE" + */ + if (unlikely(semaphore->type == VK_SEMAPHORE_TYPE_TIMELINE)) { + return vk_errorf(device, VK_ERROR_UNKNOWN, + "Cannot temporarily import into a timeline " + "semaphore"); + } + + const struct vk_sync_type *sync_type = + get_semaphore_sync_type(device->physical, semaphore->type, handle_type); + + VkResult result = vk_sync_create(device, sync_type, 0 /* flags */, + 0 /* initial_value */, &temporary); + if (result != VK_SUCCESS) + return result; + + sync = temporary; + } else { + sync = &semaphore->permanent; + } + assert(handle_type & + vk_sync_semaphore_handle_types(sync->type, semaphore->type)); + + VkResult result; + switch (pImportSemaphoreWin32HandleInfo->handleType) { + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT: + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT: + result = vk_sync_import_win32_handle(device, sync, handle, name); + break; + + default: + result = vk_error(semaphore, VK_ERROR_INVALID_EXTERNAL_HANDLE); + } + + if (result != VK_SUCCESS) { + if (temporary != NULL) + vk_sync_destroy(device, temporary); + return result; + } + + /* From a spec correctness point of view, we could probably replace the + * semaphore's temporary payload with the new vk_sync at the top. However, + * we choose to be nice to applications and only replace the semaphore if + * the import succeeded. + */ + if (temporary) { + vk_semaphore_reset_temporary(device, semaphore); + semaphore->temporary = temporary; + } + + return VK_SUCCESS; +} + +VKAPI_ATTR VkResult VKAPI_CALL +vk_common_GetSemaphoreWin32HandleKHR(VkDevice _device, + const VkSemaphoreGetWin32HandleInfoKHR *pGetWin32HandleInfo, + HANDLE *pHandle) +{ + VK_FROM_HANDLE(vk_device, device, _device); + VK_FROM_HANDLE(vk_semaphore, semaphore, pGetWin32HandleInfo->semaphore); + + assert(pGetWin32HandleInfo->sType == VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR); + + struct vk_sync *sync = vk_semaphore_get_active_sync(semaphore); + + VkResult result; + switch (pGetWin32HandleInfo->handleType) { + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT: + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT: + result = vk_sync_export_win32_handle(device, sync, pHandle); + if (result != VK_SUCCESS) + return result; + break; + + default: + unreachable("Invalid semaphore export handle type"); + } + + /* From the Vulkan 1.2.194 spec: + * + * "Export operations have the same transference as the specified + * handle type’s import operations. [...] If the semaphore was using + * a temporarily imported payload, the semaphore’s prior permanent + * payload will be restored." + */ + vk_semaphore_reset_temporary(device, semaphore); + + return VK_SUCCESS; +} + +#else VKAPI_ATTR VkResult VKAPI_CALL vk_common_ImportSemaphoreFdKHR(VkDevice _device, diff --git a/src/vulkan/runtime/vk_sync.c b/src/vulkan/runtime/vk_sync.c index 26a6178..da680ca 100644 --- a/src/vulkan/runtime/vk_sync.c +++ b/src/vulkan/runtime/vk_sync.c @@ -400,3 +400,47 @@ vk_sync_export_sync_file(struct vk_device *device, assert(!(sync->flags & VK_SYNC_IS_TIMELINE)); return sync->type->export_sync_file(device, sync, sync_file); } + +VkResult +vk_sync_import_win32_handle(struct vk_device *device, + struct vk_sync *sync, + void *handle, + const wchar_t *name) +{ + VkResult result = sync->type->import_win32_handle(device, sync, handle, name); + if (unlikely(result != VK_SUCCESS)) + return result; + + sync->flags |= VK_SYNC_IS_SHAREABLE | + VK_SYNC_IS_SHARED; + + return VK_SUCCESS; +} + +VkResult +vk_sync_export_win32_handle(struct vk_device *device, + struct vk_sync *sync, + void **handle) +{ + assert(sync->flags & VK_SYNC_IS_SHAREABLE); + + VkResult result = sync->type->export_win32_handle(device, sync, handle); + if (unlikely(result != VK_SUCCESS)) + return result; + + sync->flags |= VK_SYNC_IS_SHARED; + + return VK_SUCCESS; +} + +VkResult +vk_sync_set_win32_export_params(struct vk_device *device, + struct vk_sync *sync, + const void *security_attributes, + uint32_t access, + const wchar_t *name) +{ + assert(sync->flags & VK_SYNC_IS_SHARED); + + return sync->type->set_win32_export_params(device, sync, security_attributes, access, name); +} diff --git a/src/vulkan/runtime/vk_sync.h b/src/vulkan/runtime/vk_sync.h index bb5b204..15d85dc 100644 --- a/src/vulkan/runtime/vk_sync.h +++ b/src/vulkan/runtime/vk_sync.h @@ -272,6 +272,29 @@ struct vk_sync_type { VkResult (*export_sync_file)(struct vk_device *device, struct vk_sync *sync, int *sync_file); + + /** Permanently imports the given handle or name into this vk_sync + * + * This replaces the guts of the given vk_sync with whatever is in the object. + * In a sense, this vk_sync now aliases whatever vk_sync the handle was + * exported from. + */ + VkResult (*import_win32_handle)(struct vk_device *device, + struct vk_sync *sync, + void *handle, + const wchar_t *name); + + /** Export the guts of this vk_sync to a handle and/or name */ + VkResult (*export_win32_handle)(struct vk_device *device, + struct vk_sync *sync, + void **handle); + + /** Vulkan puts these as creation params instead of export params */ + VkResult (*set_win32_export_params)(struct vk_device *device, + struct vk_sync *sync, + const void *security_attributes, + uint32_t access, + const wchar_t *name); }; enum vk_sync_flags { @@ -361,6 +384,21 @@ VkResult MUST_CHECK vk_sync_export_sync_file(struct vk_device *device, struct vk_sync *sync, int *sync_file); +VkResult MUST_CHECK vk_sync_import_win32_handle(struct vk_device *device, + struct vk_sync *sync, + void *handle, + const wchar_t *name); + +VkResult MUST_CHECK vk_sync_export_win32_handle(struct vk_device *device, + struct vk_sync *sync, + void **handle); + +VkResult MUST_CHECK vk_sync_set_win32_export_params(struct vk_device *device, + struct vk_sync *sync, + const void *security_attributes, + uint32_t access, + const wchar_t *name); + VkResult MUST_CHECK vk_sync_move(struct vk_device *device, struct vk_sync *dst, struct vk_sync *src);