 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/vulkan-1/tests/vulkan.c | 2 +- dlls/win32u/tests/d3dkmt.c | 7 ++--- dlls/win32u/vulkan.c | 57 ++++++++++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 7 deletions(-)
diff --git a/dlls/vulkan-1/tests/vulkan.c b/dlls/vulkan-1/tests/vulkan.c index dfb5c449452..71ad2c4cf34 100644 --- a/dlls/vulkan-1/tests/vulkan.c +++ b/dlls/vulkan-1/tests/vulkan.c @@ -1363,7 +1363,7 @@ static void test_external_memory(VkInstance vk_instance, VkPhysicalDevice vk_phy get_handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR;
vr = pfn_vkGetMemoryWin32HandleKHR(vk_device, &get_handle_info, &handle); - todo_wine ok(vr == VK_SUCCESS, "vkGetMemoryWin32HandleKHR failed, VkResult %d.\n", vr); + ok(vr == VK_SUCCESS, "vkGetMemoryWin32HandleKHR failed, VkResult %d.\n", vr);
alloc_info.pNext = &dedicated_alloc_info; import_memory(vk_device, alloc_info, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR, handle); diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 95f72265efc..693276bba7a 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -455,8 +455,7 @@ static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_glob D3DKMT_HANDLE resource; NTSTATUS status;
- todo_wine_if( !expect_global ) ok_ptr( handle, !=, NULL ); - if (!handle) return; + ok_ptr( handle, !=, NULL );
open_adapter.AdapterLuid = luid; status = D3DKMTOpenAdapterFromLuid(&open_adapter); @@ -3489,7 +3488,7 @@ static struct vulkan_buffer *export_vulkan_buffer( struct vulkan_device *dev, UI get_handle_info.memory = buf->memory; get_handle_info.handleType = handle_type; vr = p_vkGetMemoryWin32HandleKHR( dev->device, &get_handle_info, handle ); - todo_wine_if( handle_type != VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT ) ok_vk( VK_SUCCESS, vr ); + ok_vk( VK_SUCCESS, vr );
return buf; } @@ -3631,7 +3630,7 @@ static struct vulkan_image *export_vulkan_image( struct vulkan_device *dev, UINT get_handle_info.memory = img->memory; get_handle_info.handleType = handle_type; vr = p_vkGetMemoryWin32HandleKHR( dev->device, &get_handle_info, handle ); - todo_wine_if( handle_type != VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT ) ok_vk( VK_SUCCESS, vr ); + ok_vk( VK_SUCCESS, vr );
return img; } diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 189637c3f65..4c130f2f6fd 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -61,6 +61,7 @@ struct device_memory
D3DKMT_HANDLE local; D3DKMT_HANDLE global; + HANDLE shared; };
static inline struct device_memory *device_memory_from_handle( VkDeviceMemory handle ) @@ -188,6 +189,38 @@ static VkExternalMemoryHandleTypeFlagBits get_host_external_memory_type(void) return 0; }
+static void init_shared_resource_path( const WCHAR *name, UNICODE_STRING *str ) +{ + UINT len = wcslen( name ); + char buffer[MAX_PATH]; + + snprintf( buffer, ARRAY_SIZE(buffer), "\Sessions\%u\BaseNamedObjects\", + NtCurrentTeb()->Peb->SessionId ); + str->MaximumLength = asciiz_to_unicode( str->Buffer, buffer ); + str->Length = str->MaximumLength - sizeof(WCHAR); + + memcpy( str->Buffer + str->Length / sizeof(WCHAR), name, (len + 1) * sizeof(WCHAR) ); + str->MaximumLength += len; + str->Length += len; +} + +static HANDLE create_shared_handle( D3DKMT_HANDLE local, const VkExportMemoryWin32HandleInfoKHR *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_vkAllocateMemory( VkDevice client_device, const VkMemoryAllocateInfo *client_alloc_info, const VkAllocationCallbacks *allocator, VkDeviceMemory *ret ) { @@ -197,9 +230,11 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA struct vulkan_physical_device *physical_device = device->physical_device; struct vulkan_instance *instance = device->physical_device->instance; VkImportMemoryHostPointerInfoEXT host_pointer_info, *pointer_info = NULL; + VkExportMemoryWin32HandleInfoKHR export_win32 = {.dwAccess = GENERIC_ALL}; VkExportMemoryAllocateInfo *export_info = NULL; VkDeviceMemory host_device_memory; struct device_memory *memory; + BOOL nt_shared = FALSE; uint32_t mem_flags; void *mapping = NULL; VkResult res; @@ -214,10 +249,14 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA if (!(export_info->handleTypes & EXTERNAL_MEMORY_WIN32_BITS)) FIXME( "Unsupported handle types %#x\n", export_info->handleTypes ); else + { + nt_shared = !(export_info->handleTypes & (VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT)); export_info->handleTypes = get_host_external_memory_type(); + } break; case VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR: - FIXME( "VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR not implemented!\n" ); + export_win32 = *(VkExportMemoryWin32HandleInfoKHR *)*next; *next = (*next)->pNext; next = &prev; break; case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT: @@ -253,7 +292,12 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA { FIXME( "Exporting memory handle not yet implemented!\n" );
- if (!(memory->local = d3dkmt_create_resource( &memory->global ))) goto failed; + if (!(memory->local = d3dkmt_create_resource( nt_shared ? NULL : &memory->global ))) goto failed; + if (nt_shared && !(memory->shared = create_shared_handle( memory->local, &export_win32 ))) + { + d3dkmt_destroy_resource( memory->local ); + goto failed; + } }
vulkan_object_init( &memory->obj.obj, host_device_memory ); @@ -300,6 +344,7 @@ static void win32u_vkFreeMemory( VkDevice client_device, VkDeviceMemory client_m NtFreeVirtualMemory( GetCurrentProcess(), &memory->vm_map, &alloc_size, MEM_RELEASE ); }
+ if (memory->shared) NtClose( memory->shared ); if (memory->local) d3dkmt_destroy_resource( memory->local ); free( memory ); } @@ -319,6 +364,14 @@ static VkResult win32u_vkGetMemoryWin32HandleKHR( VkDevice client_device, const *handle = UlongToPtr( memory->global ); return VK_SUCCESS;
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT: + NtDuplicateObject( NtCurrentProcess(), memory->shared, NtCurrentProcess(), handle, 0, 0, DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS ); + TRACE( "Returning NT shared handle %p -> %p\n", memory->shared, *handle ); + return VK_SUCCESS; + default: FIXME( "Unsupported handle type %#x\n", handle_info->handleType ); return VK_ERROR_INCOMPATIBLE_DRIVER;