 
            From: Rémi Bernon rbernon@codeweavers.com
Only try to open the shared handle for now, then close the object. --- dlls/win32u/d3dkmt.c | 26 ++++++++++++++++++ dlls/win32u/vulkan.c | 52 ++++++++++++++++++++++++++++++------ dlls/win32u/win32u_private.h | 1 + 3 files changed, 71 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index a2f929079d7..6bdeb4ce2e7 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -1658,6 +1658,32 @@ failed: return 0; }
+/* open a D3DKMT global or shared resource */ +D3DKMT_HANDLE d3dkmt_open_resource( D3DKMT_HANDLE global, HANDLE shared ) +{ + struct d3dkmt_object *allocation = NULL; + struct d3dkmt_resource *resource = NULL; + NTSTATUS status; + UINT dummy = 0; + + TRACE( "global %#x, shared %p\n", global, shared ); + + 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_open( &resource->obj, global, shared, NULL, &dummy ))) goto failed; + + if ((status = alloc_object_handle( allocation ))) goto failed; + resource->allocation = allocation->local; + + return resource->obj.local; + +failed: + WARN( "Failed to open 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 ) { diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 0fbb1740657..4ed9ad0dbf2 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -222,6 +222,7 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA struct vulkan_instance *instance = device->physical_device->instance; VkImportMemoryHostPointerInfoEXT host_pointer_info, *pointer_info = NULL; VkExportMemoryWin32HandleInfoKHR export_win32 = {.dwAccess = GENERIC_ALL}; + VkImportMemoryWin32HandleInfoKHR *import_win32 = NULL; VkExportMemoryAllocateInfo *export_info = NULL; VkDeviceMemory host_device_memory; struct device_memory *memory; @@ -254,6 +255,7 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA pointer_info = (VkImportMemoryHostPointerInfoEXT *)*next; break; case VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR: + import_win32 = (VkImportMemoryWin32HandleInfoKHR *)*next; FIXME( "VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR not implemented!\n" ); *next = (*next)->pNext; next = &prev; break; @@ -273,20 +275,44 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA return res;
if (!(memory = calloc( 1, sizeof(*memory) ))) return VK_ERROR_OUT_OF_HOST_MEMORY; + + if (import_win32) + { + switch (import_win32->handleType) + { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT: + memory->local = d3dkmt_open_resource( PtrToUlong( import_win32->handle ), NULL ); + break; + 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: + memory->local = d3dkmt_open_resource( 0, import_win32->handle ); + break; + default: + FIXME( "Unsupported handle type %#x\n", import_win32->handleType ); + break; + } + + if (!memory->local) + { + free( memory ); + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } + } + if ((res = device->p_vkAllocateMemory( device->host.device, alloc_info, NULL, &host_device_memory ))) { + if (memory->local) d3dkmt_destroy_resource( memory->local ); free( memory ); return res; }
- if (export_info) + if (export_info && !memory->local) { 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; - } + if (nt_shared && !(memory->shared = create_shared_handle( memory->local, &export_win32 ))) goto failed; }
vulkan_object_init( &memory->obj.obj, host_device_memory ); @@ -299,6 +325,7 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA
failed: device->p_vkFreeMemory( device->host.device, host_device_memory, NULL ); + if (memory->local) d3dkmt_destroy_resource( memory->local ); free( memory ); return VK_ERROR_OUT_OF_HOST_MEMORY; } @@ -367,14 +394,23 @@ static VkResult win32u_vkGetMemoryWin32HandleKHR( VkDevice client_device, const } }
+static BOOL is_d3dkmt_global( D3DKMT_HANDLE handle ) +{ + return (handle & 0xc0000000) && (handle & 0x3f) == 2; +} + static VkResult win32u_vkGetMemoryWin32HandlePropertiesKHR( VkDevice client_device, VkExternalMemoryHandleTypeFlagBits handle_type, HANDLE handle, VkMemoryWin32HandlePropertiesKHR *handle_properties ) { + static const UINT d3dkmt_type_bits = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT; struct vulkan_device *device = vulkan_device_from_handle( client_device );
- FIXME( "device %p, handle_type %#x, handle %p, handle_properties %p stub!\n", device, handle_type, handle, handle_properties ); + TRACE( "device %p, handle_type %#x, handle %p, handle_properties %p\n", device, handle_type, handle, handle_properties );
- return VK_ERROR_INCOMPATIBLE_DRIVER; + if (is_d3dkmt_global( HandleToULong( handle ) )) handle_properties->memoryTypeBits = d3dkmt_type_bits; + else handle_properties->memoryTypeBits = EXTERNAL_MEMORY_WIN32_BITS & ~d3dkmt_type_bits; + + return VK_SUCCESS; }
static VkResult win32u_vkMapMemory2KHR( VkDevice client_device, const VkMemoryMapInfoKHR *map_info, void **data ) diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index e135298a520..3c8745afab8 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -206,6 +206,7 @@ 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 D3DKMT_HANDLE d3dkmt_open_resource( D3DKMT_HANDLE global, HANDLE shared ); extern NTSTATUS d3dkmt_destroy_resource( D3DKMT_HANDLE local );
/* winstation.c */