 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/vulkan-1/tests/vulkan.c | 2 +- dlls/win32u/d3dkmt.c | 41 ++++++++++++++++++++++++++++++++++++ dlls/win32u/tests/d3dkmt.c | 14 ++++++------ dlls/win32u/vulkan.c | 34 +++++++++++++++++++++++++++--- dlls/win32u/win32u_private.h | 3 +++ 5 files changed, 83 insertions(+), 11 deletions(-)
diff --git a/dlls/vulkan-1/tests/vulkan.c b/dlls/vulkan-1/tests/vulkan.c index c4ad755595f..dfb5c449452 100644 --- a/dlls/vulkan-1/tests/vulkan.c +++ b/dlls/vulkan-1/tests/vulkan.c @@ -1398,7 +1398,7 @@ static void test_external_memory(VkInstance vk_instance, VkPhysicalDevice vk_phy get_handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_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_KMT_BIT_KHR, handle); diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 3afdcabfcf8..a2f929079d7 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -1631,3 +1631,44 @@ NTSTATUS WINAPI NtGdiDdDDIDestroySynchronizationObject( const D3DKMT_DESTROYSYNC
return STATUS_SUCCESS; } + +/* create a D3DKMT global or shared resource */ +D3DKMT_HANDLE d3dkmt_create_resource( D3DKMT_HANDLE *global ) +{ + struct d3dkmt_resource *resource = NULL; + struct d3dkmt_object *allocation = NULL; + NTSTATUS status; + + TRACE( "global %p\n", global ); + + if ((status = d3dkmt_object_alloc( sizeof(*resource), D3DKMT_RESOURCE, (void **)&resource ))) goto failed; + if ((status = d3dkmt_object_alloc( sizeof(*allocation), D3DKMT_ALLOCATION, (void **)&allocation ))) goto failed; + if ((status = d3dkmt_object_create( &resource->obj, !global, NULL, 0 ))) goto failed; + + if ((status = alloc_object_handle( allocation ))) goto failed; + resource->allocation = allocation->local; + + if (global) *global = resource->obj.global; + return resource->obj.local; + +failed: + WARN( "Failed to create resource, status %#x\n", status ); + if (allocation) d3dkmt_object_free( allocation ); + if (resource) d3dkmt_object_free( &resource->obj ); + return 0; +} + +/* destroy a locally opened D3DKMT resource */ +NTSTATUS d3dkmt_destroy_resource( D3DKMT_HANDLE local ) +{ + struct d3dkmt_resource *resource; + struct d3dkmt_object *allocation; + + TRACE( "local %#x\n", local ); + + if (!(resource = get_d3dkmt_object( local, D3DKMT_RESOURCE ))) return STATUS_INVALID_PARAMETER; + if ((allocation = get_d3dkmt_object( resource->allocation, D3DKMT_RESOURCE ))) d3dkmt_object_free( allocation ); + d3dkmt_object_free( &resource->obj ); + + return STATUS_SUCCESS; +} diff --git a/dlls/win32u/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index 4edb1195293..95f72265efc 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -455,7 +455,7 @@ static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_glob D3DKMT_HANDLE resource; NTSTATUS status;
- todo_wine ok_ptr( handle, !=, NULL ); + todo_wine_if( !expect_global ) ok_ptr( handle, !=, NULL ); if (!handle) return;
open_adapter.AdapterLuid = luid; @@ -480,7 +480,7 @@ static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_glob status = D3DKMTQueryResourceInfo( &query ); ok_nt( STATUS_SUCCESS, status ); if (size) ok_u4( query.PrivateRuntimeDataSize, ==, size ); - else todo_wine ok( query.PrivateRuntimeDataSize == 0 || query.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", query.PrivateRuntimeDataSize ); + else ok( query.PrivateRuntimeDataSize == 0 || query.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", query.PrivateRuntimeDataSize ); ok_u4( query.TotalPrivateDriverDataSize, <, sizeof(driver_data) ); ok_u4( query.ResourcePrivateDriverDataSize, <, sizeof(driver_data) ); ok_u4( query.NumAllocations, ==, 1 ); @@ -501,7 +501,7 @@ static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_glob ok_nt( STATUS_SUCCESS, status ); check_d3dkmt_local( open.hResource, NULL ); if (size) ok_u4( open.PrivateRuntimeDataSize, ==, size ); - else todo_wine ok( open.PrivateRuntimeDataSize == 0 || open.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", open.PrivateRuntimeDataSize ); + else ok( open.PrivateRuntimeDataSize == 0 || open.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", open.PrivateRuntimeDataSize ); ok_u4( open.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); ok_u4( open.ResourcePrivateDriverDataSize, <, sizeof(driver_data) ); ok_u4( open.NumAllocations, ==, 1 ); @@ -519,7 +519,7 @@ static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_glob status = D3DKMTQueryResourceInfoFromNtHandle( &query_nt ); ok_nt( STATUS_SUCCESS, status ); if (size) ok_u4( query_nt.PrivateRuntimeDataSize, ==, size ); - else todo_wine ok( query_nt.PrivateRuntimeDataSize == 0 || query_nt.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", query_nt.PrivateRuntimeDataSize ); + else ok( query_nt.PrivateRuntimeDataSize == 0 || query_nt.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", query_nt.PrivateRuntimeDataSize ); ok_u4( query_nt.TotalPrivateDriverDataSize, <, sizeof(driver_data) ); ok_u4( query_nt.ResourcePrivateDriverDataSize, <, sizeof(driver_data) ); ok_u4( query_nt.NumAllocations, ==, 1 ); @@ -540,7 +540,7 @@ static void get_d3dkmt_resource_desc( LUID luid, HANDLE handle, BOOL expect_glob ok_nt( STATUS_SUCCESS, status ); check_d3dkmt_local( open_nt.hResource, NULL ); if (size) ok_u4( open_nt.PrivateRuntimeDataSize, ==, size ); - else todo_wine ok( open_nt.PrivateRuntimeDataSize == 0 || open_nt.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", open_nt.PrivateRuntimeDataSize ); + else ok( open_nt.PrivateRuntimeDataSize == 0 || open_nt.PrivateRuntimeDataSize == 0x68 /* NVIDIA */, "got %#x\n", open_nt.PrivateRuntimeDataSize ); ok_u4( open_nt.TotalPrivateDriverDataBufferSize, <, sizeof(driver_data) ); ok_u4( open_nt.ResourcePrivateDriverDataSize, <, sizeof(driver_data) ); ok_u4( open_nt.NumAllocations, ==, 1 ); @@ -3489,7 +3489,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 ok_vk( VK_SUCCESS, vr ); + todo_wine_if( handle_type != VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT ) ok_vk( VK_SUCCESS, vr );
return buf; } @@ -3631,7 +3631,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 ok_vk( VK_SUCCESS, vr ); + todo_wine_if( handle_type != VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT ) ok_vk( VK_SUCCESS, vr );
return img; } diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 58872f70cde..189637c3f65 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -58,6 +58,9 @@ struct device_memory struct vulkan_device_memory obj; VkDeviceSize size; void *vm_map; + + D3DKMT_HANDLE local; + D3DKMT_HANDLE global; };
static inline struct device_memory *device_memory_from_handle( VkDeviceMemory handle ) @@ -239,13 +242,20 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA (res = allocate_external_host_memory( device, alloc_info, mem_flags, &host_pointer_info ))) return res;
- if (!(memory = malloc( sizeof(*memory) ))) return VK_ERROR_OUT_OF_HOST_MEMORY; + if (!(memory = calloc( 1, sizeof(*memory) ))) return VK_ERROR_OUT_OF_HOST_MEMORY; if ((res = device->p_vkAllocateMemory( device->host.device, alloc_info, NULL, &host_device_memory ))) { free( memory ); return res; }
+ if (export_info) + { + FIXME( "Exporting memory handle not yet implemented!\n" ); + + if (!(memory->local = d3dkmt_create_resource( &memory->global ))) goto failed; + } + vulkan_object_init( &memory->obj.obj, host_device_memory ); memory->size = alloc_info->allocationSize; memory->vm_map = mapping; @@ -253,6 +263,11 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA
*ret = memory->obj.client.device_memory; return VK_SUCCESS; + +failed: + device->p_vkFreeMemory( device->host.device, host_device_memory, NULL ); + free( memory ); + return VK_ERROR_OUT_OF_HOST_MEMORY; }
static void win32u_vkFreeMemory( VkDevice client_device, VkDeviceMemory client_memory, const VkAllocationCallbacks *allocator ) @@ -285,16 +300,29 @@ static void win32u_vkFreeMemory( VkDevice client_device, VkDeviceMemory client_m NtFreeVirtualMemory( GetCurrentProcess(), &memory->vm_map, &alloc_size, MEM_RELEASE ); }
+ if (memory->local) d3dkmt_destroy_resource( memory->local ); free( memory ); }
static VkResult win32u_vkGetMemoryWin32HandleKHR( VkDevice client_device, const VkMemoryGetWin32HandleInfoKHR *handle_info, HANDLE *handle ) { struct vulkan_device *device = vulkan_device_from_handle( client_device ); + struct device_memory *memory = device_memory_from_handle( handle_info->memory );
- 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_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT: + TRACE( "Returning global D3DKMT handle %#x\n", memory->global ); + *handle = UlongToPtr( memory->global ); + return VK_SUCCESS; + + default: + FIXME( "Unsupported handle type %#x\n", handle_info->handleType ); + return VK_ERROR_INCOMPATIBLE_DRIVER; + } }
static VkResult win32u_vkGetMemoryWin32HandlePropertiesKHR( VkDevice client_device, VkExternalMemoryHandleTypeFlagBits handle_type, HANDLE handle, diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index a9b39de6471..e135298a520 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -205,6 +205,9 @@ extern BOOL get_vulkan_gpus( struct list *gpus ); extern void free_vulkan_gpu( struct vulkan_gpu *gpu ); extern BOOL get_vulkan_uuid_from_luid( const LUID *luid, GUID *uuid );
+extern D3DKMT_HANDLE d3dkmt_create_resource( D3DKMT_HANDLE *global ); +extern NTSTATUS d3dkmt_destroy_resource( D3DKMT_HANDLE local ); + /* winstation.c */
struct object_lock