 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/vulkan.c | 1 + dlls/winevulkan/vulkan.c | 16 ++++++++++++++++ dlls/winevulkan/vulkan_private.h | 1 + dlls/winewayland.drv/vulkan.c | 1 + dlls/winex11.drv/vulkan.c | 1 + 5 files changed, 20 insertions(+)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 3e0300184c0..6e54d0dc654 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -1601,6 +1601,7 @@ static const char *nulldrv_get_host_extension( const char *name ) { if (!strcmp( name, "VK_KHR_win32_surface" )) return "VK_EXT_headless_surface"; if (!strcmp( name, "VK_KHR_external_memory_win32" )) return "VK_KHR_external_memory_fd"; + if (!strcmp( name, "VK_KHR_external_semaphore_win32" )) return "VK_KHR_external_semaphore_fd"; return name; }
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index af14a493ec0..71785d97ca5 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -367,6 +367,7 @@ static VkResult vulkan_physical_device_init(struct vulkan_physical_device *physi for (i = 0; i < num_host_properties; i++) { if (!strcmp(host_properties[i].extensionName, vk_funcs->p_get_host_extension("VK_KHR_external_memory_win32")) + || !strcmp(host_properties[i].extensionName, vk_funcs->p_get_host_extension("VK_KHR_external_semaphore_win32")) || wine_vk_device_extension_supported(host_properties[i].extensionName)) { TRACE("Enabling extension '%s' for physical device %p\n", host_properties[i].extensionName, physical_device); @@ -403,6 +404,11 @@ static VkResult vulkan_physical_device_init(struct vulkan_physical_device *physi strcpy(physical_device->extensions[j].extensionName, "VK_KHR_external_memory_win32"); physical_device->extensions[j++].specVersion = VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION; } + else if (!strcmp(host_properties[i].extensionName, vk_funcs->p_get_host_extension("VK_KHR_external_semaphore_win32"))) + { + strcpy(physical_device->extensions[j].extensionName, "VK_KHR_external_semaphore_win32"); + physical_device->extensions[j++].specVersion = VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION; + } else if (wine_vk_device_extension_supported(host_properties[i].extensionName)) { physical_device->extensions[j] = host_properties[i]; @@ -582,6 +588,11 @@ static VkResult wine_vk_device_convert_create_info(struct vulkan_physical_device *extension = vk_funcs->p_get_host_extension("VK_KHR_external_memory_win32"); if (!strcmp(*extension, "VK_EXT_external_memory_dma_buf")) extensions[count++] = "VK_KHR_external_memory_fd"; } + if (!strcmp(*extension, "VK_KHR_external_semaphore_win32")) + { + device->has_external_semaphore_win32 = true; + *extension = vk_funcs->p_get_host_extension("VK_KHR_external_semaphore_win32"); + } }
if (physical_device->map_placed_align) @@ -1782,6 +1793,11 @@ static NTSTATUS is_available_device_function(VkDevice handle, const char *name) if (!strcmp(name, "vkGetMemoryWin32HandlePropertiesKHR")) return device->has_external_memory_win32;
+ if (!strcmp(name, "vkGetSemaphoreWin32HandleKHR")) + return device->has_external_semaphore_win32; + if (!strcmp(name, "vkImportSemaphoreWin32HandleKHR")) + return device->has_external_semaphore_win32; + return !!vk_funcs->p_vkGetDeviceProcAddr(device->obj.host.device, name); }
diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index d3ef04ada20..37aae0ca004 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -42,6 +42,7 @@ struct wine_device { struct vulkan_device obj; bool has_external_memory_win32; + bool has_external_semaphore_win32; uint64_t queue_count; struct wine_queue queues[]; }; diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index cd5c5295cb1..b70d2636df3 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -85,6 +85,7 @@ static const char *wayland_get_host_extension(const char *name) { if (!strcmp( name, "VK_KHR_win32_surface" )) return "VK_KHR_wayland_surface"; if (!strcmp( name, "VK_KHR_external_memory_win32" )) return "VK_KHR_external_memory_fd"; + if (!strcmp( name, "VK_KHR_external_semaphore_win32" )) return "VK_KHR_external_semaphore_fd"; return name; }
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index f49f382b3a6..a3277bb999b 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -82,6 +82,7 @@ static const char *X11DRV_get_host_extension( const char *name ) { if (!strcmp( name, "VK_KHR_win32_surface" )) return "VK_KHR_xlib_surface"; if (!strcmp( name, "VK_KHR_external_memory_win32" )) return "VK_KHR_external_memory_fd"; + if (!strcmp( name, "VK_KHR_external_semaphore_win32" )) return "VK_KHR_external_semaphore_fd"; return name; }
 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/vulkan.c | 20 +++++++++++++++++++- dlls/win32u/win32u_private.h | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 6e54d0dc654..21bc707d073 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -52,6 +52,9 @@ static const UINT EXTERNAL_MEMORY_WIN32_BITS = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OP VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT; +static const UINT EXTERNAL_SEMAPHORE_WIN32_BITS = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT | + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT | + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT;
struct device_memory { @@ -189,6 +192,14 @@ static VkExternalMemoryHandleTypeFlagBits get_host_external_memory_type(void) return 0; }
+static VkExternalSemaphoreHandleTypeFlagBits get_host_external_semaphore_type(void) +{ + const char *host_extension = driver_funcs->p_get_host_extension( "VK_KHR_external_semaphore_win32" ); + if (!strcmp( host_extension, "VK_KHR_external_semaphore_fd" )) return VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; + if (!strcmp( host_extension, "VK_KHR_external_semaphore_capabilities" )) return VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; + return 0; +} + static void init_shared_resource_path( const WCHAR *name, UNICODE_STRING *str ) { UINT len = wcslen( name ); @@ -1422,15 +1433,22 @@ static VkResult win32u_vkImportSemaphoreWin32HandleKHR( VkDevice client_device, return VK_ERROR_INCOMPATIBLE_DRIVER; }
-static void win32u_vkGetPhysicalDeviceExternalSemaphoreProperties( VkPhysicalDevice client_physical_device, const VkPhysicalDeviceExternalSemaphoreInfo *semaphore_info, +static void win32u_vkGetPhysicalDeviceExternalSemaphoreProperties( VkPhysicalDevice client_physical_device, const VkPhysicalDeviceExternalSemaphoreInfo *client_semaphore_info, VkExternalSemaphoreProperties *semaphore_properties ) { + VkPhysicalDeviceExternalSemaphoreInfo *semaphore_info = (VkPhysicalDeviceExternalSemaphoreInfo *)client_semaphore_info; /* cast away const, it has been copied in the thunks */ struct vulkan_physical_device *physical_device = vulkan_physical_device_from_handle( client_physical_device ); struct vulkan_instance *instance = physical_device->instance; + VkExternalSemaphoreHandleTypeFlagBits handle_type;
TRACE( "physical_device %p, semaphore_info %p, semaphore_properties %p\n", physical_device, semaphore_info, semaphore_properties );
+ handle_type = semaphore_info->handleType; + if (semaphore_info->handleType & EXTERNAL_SEMAPHORE_WIN32_BITS) semaphore_info->handleType = get_host_external_semaphore_type(); + instance->p_vkGetPhysicalDeviceExternalSemaphoreProperties( physical_device->host.physical_device, semaphore_info, semaphore_properties ); + semaphore_properties->compatibleHandleTypes = handle_type; + semaphore_properties->exportFromImportedHandleTypes = handle_type; }
static VkResult win32u_vkCreateFence( VkDevice client_device, const VkFenceCreateInfo *client_create_info, const VkAllocationCallbacks *allocator, VkFence *ret ) diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 3c8745afab8..6fbd0b74c9f 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -209,6 +209,9 @@ extern D3DKMT_HANDLE d3dkmt_create_resource( D3DKMT_HANDLE *global ); extern D3DKMT_HANDLE d3dkmt_open_resource( D3DKMT_HANDLE global, HANDLE shared ); extern NTSTATUS d3dkmt_destroy_resource( D3DKMT_HANDLE local );
+extern D3DKMT_HANDLE d3dkmt_create_sync( D3DKMT_HANDLE *global ); +extern NTSTATUS d3dkmt_destroy_sync( D3DKMT_HANDLE local ); + /* winstation.c */
struct object_lock
 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 32 ++++++++++++++++++++++++++++++++ dlls/win32u/vulkan.c | 38 +++++++++++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 3 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index a048aca740a..878104b009b 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -1698,3 +1698,35 @@ NTSTATUS d3dkmt_destroy_resource( D3DKMT_HANDLE local )
return STATUS_SUCCESS; } + +/* create a D3DKMT global or shared sync */ +D3DKMT_HANDLE d3dkmt_create_sync( D3DKMT_HANDLE *global ) +{ + struct d3dkmt_object *sync = NULL; + NTSTATUS status; + + TRACE( "global %p\n", global ); + + if ((status = d3dkmt_object_alloc( sizeof(*sync), D3DKMT_SYNC, (void **)&sync ))) goto failed; + if ((status = d3dkmt_object_create( sync, !global, NULL, 0 ))) goto failed; + if (global) *global = sync->global; + return sync->local; + +failed: + WARN( "Failed to create sync, status %#x\n", status ); + if (sync) d3dkmt_object_free( sync ); + return 0; +} + +/* destroy a locally opened D3DKMT sync */ +NTSTATUS d3dkmt_destroy_sync( D3DKMT_HANDLE local ) +{ + struct d3dkmt_object *sync; + + TRACE( "local %#x\n", local ); + + if (!(sync = get_d3dkmt_object( local, D3DKMT_SYNC ))) return STATUS_INVALID_PARAMETER; + d3dkmt_object_free( sync ); + + return STATUS_SUCCESS; +} diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 21bc707d073..558569a06b6 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -102,6 +102,8 @@ static struct swapchain *swapchain_from_handle( VkSwapchainKHR handle ) struct semaphore { struct vulkan_semaphore obj; + D3DKMT_HANDLE local; + D3DKMT_HANDLE global; };
static struct semaphore *semaphore_from_handle( VkSemaphore handle ) @@ -1360,6 +1362,7 @@ static VkResult win32u_vkCreateSemaphore( VkDevice client_device, const VkSemaph struct vulkan_device *device = vulkan_device_from_handle( client_device ); VkBaseOutStructure **next, *prev = (VkBaseOutStructure *)create_info; struct vulkan_instance *instance = device->physical_device->instance; + VkExportSemaphoreCreateInfoKHR *export_info = NULL; struct semaphore *semaphore; VkSemaphore host_semaphore; VkResult res; @@ -1371,7 +1374,11 @@ static VkResult win32u_vkCreateSemaphore( VkDevice client_device, const VkSemaph switch ((*next)->sType) { case VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO: - FIXME( "VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO not implemented!\n" ); + export_info = (VkExportSemaphoreCreateInfoKHR *)*next; + if (!(export_info->handleTypes & EXTERNAL_SEMAPHORE_WIN32_BITS)) + FIXME( "Unsupported handle types %#x\n", export_info->handleTypes ); + else + export_info->handleTypes = get_host_external_semaphore_type(); *next = (*next)->pNext; next = &prev; break; case VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR: @@ -1392,11 +1399,24 @@ static VkResult win32u_vkCreateSemaphore( VkDevice client_device, const VkSemaph return res; }
+ if (export_info) + { + FIXME( "Exporting semaphore handle not yet implemented!\n" ); + + if (!(semaphore->local = d3dkmt_create_sync( &semaphore->global ))) goto failed; + } + vulkan_object_init( &semaphore->obj.obj, host_semaphore ); instance->p_insert_object( instance, &semaphore->obj.obj );
*ret = semaphore->obj.client.semaphore; return res; + +failed: + device->p_vkDestroySemaphore( device->host.device, host_semaphore, NULL ); + if (semaphore->local) d3dkmt_destroy_sync( semaphore->local ); + free( semaphore ); + return VK_ERROR_OUT_OF_HOST_MEMORY; }
static void win32u_vkDestroySemaphore( VkDevice client_device, VkSemaphore client_semaphore, const VkAllocationCallbacks *allocator ) @@ -1412,16 +1432,28 @@ static void win32u_vkDestroySemaphore( VkDevice client_device, VkSemaphore clien device->p_vkDestroySemaphore( device->host.device, semaphore->obj.host.semaphore, NULL /* allocator */ ); instance->p_remove_object( instance, &semaphore->obj.obj );
+ if (semaphore->local) d3dkmt_destroy_sync( semaphore->local ); free( semaphore ); }
static VkResult win32u_vkGetSemaphoreWin32HandleKHR( VkDevice client_device, const VkSemaphoreGetWin32HandleInfoKHR *handle_info, HANDLE *handle ) { struct vulkan_device *device = vulkan_device_from_handle( client_device ); + struct semaphore *semaphore = semaphore_from_handle( handle_info->semaphore );
- FIXME( "device %p, handle_info %p, handle %p stub!\n", device, handle_info, handle ); + TRACE( "device %p, handle_info %p, handle %p\n", device, handle_info, handle );
- return VK_ERROR_INCOMPATIBLE_DRIVER; + switch (handle_info->handleType) + { + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + TRACE( "Returning global D3DKMT handle %#x\n", semaphore->global ); + *handle = UlongToPtr( semaphore->global ); + return VK_SUCCESS; + + default: + FIXME( "Unsupported handle type %#x\n", handle_info->handleType ); + return VK_ERROR_INCOMPATIBLE_DRIVER; + } }
static VkResult win32u_vkImportSemaphoreWin32HandleKHR( VkDevice client_device, const VkImportSemaphoreWin32HandleInfoKHR *handle_info )
 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 19 +++++++++++++++++++ dlls/win32u/vulkan.c | 30 ++++++++++++++++++++++++++++-- dlls/win32u/win32u_private.h | 1 + 3 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 878104b009b..7eb3928ba72 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -1718,6 +1718,25 @@ failed: return 0; }
+/* open a D3DKMT global or shared sync */ +D3DKMT_HANDLE d3dkmt_open_sync( D3DKMT_HANDLE global, HANDLE shared ) +{ + struct d3dkmt_object *sync = NULL; + NTSTATUS status; + UINT dummy = 0; + + TRACE( "global %#x, shared %p\n", global, shared ); + + if ((status = d3dkmt_object_alloc( sizeof(*sync), D3DKMT_SYNC, (void **)&sync ))) goto failed; + if ((status = d3dkmt_object_open( sync, global, shared, NULL, &dummy ))) goto failed; + return sync->local; + +failed: + WARN( "Failed to open sync, status %#x\n", status ); + if (sync) d3dkmt_object_free( sync ); + return 0; +} + /* destroy a locally opened D3DKMT sync */ NTSTATUS d3dkmt_destroy_sync( D3DKMT_HANDLE local ) { diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 558569a06b6..81251a6064a 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -1459,10 +1459,36 @@ static VkResult win32u_vkGetSemaphoreWin32HandleKHR( VkDevice client_device, con static VkResult win32u_vkImportSemaphoreWin32HandleKHR( VkDevice client_device, const VkImportSemaphoreWin32HandleInfoKHR *handle_info ) { struct vulkan_device *device = vulkan_device_from_handle( client_device ); + struct semaphore *semaphore = semaphore_from_handle( handle_info->semaphore ); + D3DKMT_HANDLE local, global = 0;
- FIXME( "device %p, handle_info %p stub!\n", device, handle_info ); + TRACE( "device %p, handle_info %p\n", device, handle_info );
- return VK_ERROR_INCOMPATIBLE_DRIVER; + switch (handle_info->handleType) + { + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + global = PtrToUlong( handle_info->handle ); + if (!(local = d3dkmt_open_sync( global, NULL ))) return VK_ERROR_INVALID_EXTERNAL_HANDLE; + break; + default: + FIXME( "Unsupported handle type %#x\n", handle_info->handleType ); + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } + + FIXME( "Importing memory handle not yet implemented!\n" ); + + if (handle_info->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT) + { + /* FIXME: Should we still keep the temporary handles for vkGetSemaphoreWin32HandleKHR? */ + d3dkmt_destroy_sync( local ); + } + else + { + if (semaphore->local) d3dkmt_destroy_sync( semaphore->local ); + semaphore->global = global; + semaphore->local = local; + } + return VK_SUCCESS; }
static void win32u_vkGetPhysicalDeviceExternalSemaphoreProperties( VkPhysicalDevice client_physical_device, const VkPhysicalDeviceExternalSemaphoreInfo *client_semaphore_info, diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 6fbd0b74c9f..6eaa7270b01 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -210,6 +210,7 @@ extern D3DKMT_HANDLE d3dkmt_open_resource( D3DKMT_HANDLE global, HANDLE shared ) extern NTSTATUS d3dkmt_destroy_resource( D3DKMT_HANDLE local );
extern D3DKMT_HANDLE d3dkmt_create_sync( D3DKMT_HANDLE *global ); +extern D3DKMT_HANDLE d3dkmt_open_sync( D3DKMT_HANDLE global, HANDLE shared ); extern NTSTATUS d3dkmt_destroy_sync( D3DKMT_HANDLE local );
/* winstation.c */
 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/vulkan.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 81251a6064a..61fc32d4e96 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -104,6 +104,7 @@ struct semaphore struct vulkan_semaphore obj; D3DKMT_HANDLE local; D3DKMT_HANDLE global; + HANDLE shared; };
static struct semaphore *semaphore_from_handle( VkSemaphore handle ) @@ -217,7 +218,7 @@ static void init_shared_resource_path( const WCHAR *name, UNICODE_STRING *str ) str->Length += len; }
-static HANDLE create_shared_handle( D3DKMT_HANDLE local, const VkExportMemoryWin32HandleInfoKHR *info ) +static HANDLE create_shared_resource_handle( D3DKMT_HANDLE local, const VkExportMemoryWin32HandleInfoKHR *info ) { SECURITY_DESCRIPTOR *security = info->pAttributes ? info->pAttributes->lpSecurityDescriptor : NULL; WCHAR bufferW[MAX_PATH * 2]; @@ -361,7 +362,7 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA FIXME( "Exporting memory handle not yet implemented!\n" );
if (!memory->local && !(memory->local = d3dkmt_create_resource( nt_shared ? NULL : &memory->global ))) goto failed; - if (nt_shared && !(memory->shared = create_shared_handle( memory->local, &export_win32 ))) goto failed; + if (nt_shared && !(memory->shared = create_shared_resource_handle( memory->local, &export_win32 ))) goto failed; }
vulkan_object_init( &memory->obj.obj, host_device_memory ); @@ -1355,16 +1356,35 @@ static VkResult win32u_vkQueueSubmit2( VkQueue client_queue, uint32_t count, con return device->p_vkQueueSubmit2( queue->host.queue, count, submits, fence ? fence->host.fence : 0 ); }
+static HANDLE create_shared_semaphore_handle( D3DKMT_HANDLE local, const VkExportSemaphoreWin32HandleInfoKHR *info ) +{ + SECURITY_DESCRIPTOR *security = info->pAttributes ? info->pAttributes->lpSecurityDescriptor : NULL; + WCHAR bufferW[MAX_PATH * 2]; + UNICODE_STRING name = {.Buffer = bufferW}; + OBJECT_ATTRIBUTES attr; + NTSTATUS status; + HANDLE shared; + + if (info->name) init_shared_resource_path( info->name, &name ); + InitializeObjectAttributes( &attr, info->name ? &name : NULL, OBJ_CASE_INSENSITIVE, security, NULL ); + + if (!(status = NtGdiDdDDIShareObjects( 1, &local, &attr, info->dwAccess, &shared ))) return shared; + WARN( "Failed to share resource %#x, status %#x\n", local, status ); + return NULL; +} + static VkResult win32u_vkCreateSemaphore( VkDevice client_device, const VkSemaphoreCreateInfo *client_create_info, const VkAllocationCallbacks *allocator, VkSemaphore *ret ) { VkSemaphoreCreateInfo *create_info = (VkSemaphoreCreateInfo *)client_create_info; /* cast away const, chain has been copied in the thunks */ + VkExportSemaphoreWin32HandleInfoKHR export_win32 = {.dwAccess = GENERIC_ALL}; struct vulkan_device *device = vulkan_device_from_handle( client_device ); VkBaseOutStructure **next, *prev = (VkBaseOutStructure *)create_info; struct vulkan_instance *instance = device->physical_device->instance; VkExportSemaphoreCreateInfoKHR *export_info = NULL; struct semaphore *semaphore; VkSemaphore host_semaphore; + BOOL nt_shared = FALSE; VkResult res;
TRACE( "device %p, create_info %p, allocator %p, ret %p\n", device, create_info, allocator, ret ); @@ -1378,11 +1398,14 @@ static VkResult win32u_vkCreateSemaphore( VkDevice client_device, const VkSemaph if (!(export_info->handleTypes & EXTERNAL_SEMAPHORE_WIN32_BITS)) FIXME( "Unsupported handle types %#x\n", export_info->handleTypes ); else + { + nt_shared = !(export_info->handleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT); export_info->handleTypes = get_host_external_semaphore_type(); + } *next = (*next)->pNext; next = &prev; break; case VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR: - FIXME( "VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR not implemented!\n" ); + export_win32 = *(VkExportSemaphoreWin32HandleInfoKHR *)*next; *next = (*next)->pNext; next = &prev; break; case VK_STRUCTURE_TYPE_QUERY_LOW_LATENCY_SUPPORT_NV: break; @@ -1403,7 +1426,8 @@ static VkResult win32u_vkCreateSemaphore( VkDevice client_device, const VkSemaph { FIXME( "Exporting semaphore handle not yet implemented!\n" );
- if (!(semaphore->local = d3dkmt_create_sync( &semaphore->global ))) goto failed; + if (!(semaphore->local = d3dkmt_create_sync( nt_shared ? NULL : &semaphore->global ))) goto failed; + if (nt_shared && !(semaphore->shared = create_shared_semaphore_handle( semaphore->local, &export_win32 ))) goto failed; }
vulkan_object_init( &semaphore->obj.obj, host_semaphore ); @@ -1432,6 +1456,7 @@ static void win32u_vkDestroySemaphore( VkDevice client_device, VkSemaphore clien device->p_vkDestroySemaphore( device->host.device, semaphore->obj.host.semaphore, NULL /* allocator */ ); instance->p_remove_object( instance, &semaphore->obj.obj );
+ if (semaphore->shared) NtClose( semaphore->shared ); if (semaphore->local) d3dkmt_destroy_sync( semaphore->local ); free( semaphore ); } @@ -1450,6 +1475,12 @@ static VkResult win32u_vkGetSemaphoreWin32HandleKHR( VkDevice client_device, con *handle = UlongToPtr( semaphore->global ); return VK_SUCCESS;
+ case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT: + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT: + NtDuplicateObject( NtCurrentProcess(), semaphore->shared, NtCurrentProcess(), handle, 0, 0, DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS ); + TRACE( "Returning NT shared handle %p -> %p\n", semaphore->shared, *handle ); + return VK_SUCCESS; + default: FIXME( "Unsupported handle type %#x\n", handle_info->handleType ); return VK_ERROR_INCOMPATIBLE_DRIVER;
 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/vulkan.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 61fc32d4e96..d0c53bdb244 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -1492,6 +1492,7 @@ static VkResult win32u_vkImportSemaphoreWin32HandleKHR( VkDevice client_device, struct vulkan_device *device = vulkan_device_from_handle( client_device ); struct semaphore *semaphore = semaphore_from_handle( handle_info->semaphore ); D3DKMT_HANDLE local, global = 0; + HANDLE shared = NULL;
TRACE( "device %p, handle_info %p\n", device, handle_info );
@@ -1501,6 +1502,18 @@ static VkResult win32u_vkImportSemaphoreWin32HandleKHR( VkDevice client_device, global = PtrToUlong( handle_info->handle ); if (!(local = d3dkmt_open_sync( global, NULL ))) return VK_ERROR_INVALID_EXTERNAL_HANDLE; break; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT: + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT: + if (!(shared = handle_info->handle) || NtDuplicateObject( NtCurrentProcess(), shared, NtCurrentProcess(), &shared, + 0, 0, DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS )) + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + + if (!(local = d3dkmt_open_sync( 0, shared ))) + { + NtClose( shared ); + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } + break; default: FIXME( "Unsupported handle type %#x\n", handle_info->handleType ); return VK_ERROR_INVALID_EXTERNAL_HANDLE; @@ -1511,11 +1524,14 @@ static VkResult win32u_vkImportSemaphoreWin32HandleKHR( VkDevice client_device, if (handle_info->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT) { /* FIXME: Should we still keep the temporary handles for vkGetSemaphoreWin32HandleKHR? */ + if (shared) NtClose( shared ); d3dkmt_destroy_sync( local ); } else { + if (semaphore->shared) NtClose( semaphore->shared ); if (semaphore->local) d3dkmt_destroy_sync( semaphore->local ); + semaphore->shared = shared; semaphore->global = global; semaphore->local = local; }
 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/vulkan.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index d0c53bdb244..877091cd590 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -235,7 +235,7 @@ static HANDLE create_shared_resource_handle( D3DKMT_HANDLE local, const VkExport return NULL; }
-static HANDLE open_shared_handle_from_name( const WCHAR *name ) +static HANDLE open_shared_resource_from_name( const WCHAR *name ) { D3DKMT_OPENNTHANDLEFROMNAME open_name = {0}; WCHAR bufferW[MAX_PATH * 2]; @@ -331,7 +331,7 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT: { HANDLE shared = import_win32->handle; - if (import_win32->name && !(shared = open_shared_handle_from_name( import_win32->name ))) break; + if (import_win32->name && !(shared = open_shared_resource_from_name( import_win32->name ))) break; memory->local = d3dkmt_open_resource( 0, shared ); if (shared && shared != import_win32->handle) NtClose( shared ); break; @@ -1373,6 +1373,24 @@ static HANDLE create_shared_semaphore_handle( D3DKMT_HANDLE local, const VkExpor return NULL; }
+static HANDLE open_shared_semaphore_from_name( const WCHAR *name ) +{ + D3DKMT_OPENSYNCOBJECTNTHANDLEFROMNAME open_name = {0}; + WCHAR bufferW[MAX_PATH * 2]; + UNICODE_STRING name_str = {.Buffer = bufferW}; + OBJECT_ATTRIBUTES attr; + NTSTATUS status; + + init_shared_resource_path( name, &name_str ); + InitializeObjectAttributes( &attr, &name_str, OBJ_OPENIF, NULL, NULL ); + + open_name.dwDesiredAccess = GENERIC_ALL; + open_name.pObjAttrib = &attr; + status = NtGdiDdDDIOpenSyncObjectNtHandleFromName( &open_name ); + if (status) WARN( "Failed to open %s, status %#x\n", debugstr_w( name ), status ); + return open_name.hNtHandle; +} + static VkResult win32u_vkCreateSemaphore( VkDevice client_device, const VkSemaphoreCreateInfo *client_create_info, const VkAllocationCallbacks *allocator, VkSemaphore *ret ) { @@ -1504,8 +1522,10 @@ static VkResult win32u_vkImportSemaphoreWin32HandleKHR( VkDevice client_device, break; case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT: case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT: - if (!(shared = handle_info->handle) || NtDuplicateObject( NtCurrentProcess(), shared, NtCurrentProcess(), &shared, - 0, 0, DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS )) + if (handle_info->name && !(shared = open_shared_semaphore_from_name( handle_info->name ))) + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + else if (!(shared = handle_info->handle) || NtDuplicateObject( NtCurrentProcess(), shared, NtCurrentProcess(), &shared, + 0, 0, DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS )) return VK_ERROR_INVALID_EXTERNAL_HANDLE;
if (!(local = d3dkmt_open_sync( 0, shared )))

