mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-28 13:00:42 +02:00
vulkan: Win32 sync import/export support
Acked-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22879>
This commit is contained in:
parent
952a523abb
commit
c9146794d4
3 changed files with 244 additions and 13 deletions
|
|
@ -25,7 +25,9 @@
|
|||
|
||||
#include "util/os_time.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#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);
|
||||
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
|
||||
* 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;
|
||||
/* 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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue