 
            Instead of https://gitlab.winehq.org/wine/wine/-/merge_requests/9108, creating D3D runtime descriptors from the Vulkan info doesn't seem possible for some cases as some information have been lost (multiple stencil formats end up with the same Vulkan format, D3D bind flags transformation is not bijective).
A separate, Wine-specific, D3DKMTEscape code will be exposed instead, to let D3D runtime implementations update the resource descriptors with the data they expect to find (ideally, the same descriptors as native, so importing can be compatible), after having been created and exported.
(This, currently doesn't actually implements resource sharing, it only creates the D3DKMT object and exports / imports their handles. We still lack the logic to share the underlying host object fds, which will come later)
-- v3: win32u: Implement Vulkan memory D3DKMT handle import from name. win32u: Implement Vulkan memory D3DKMT global / shared handle import. win32u: Implement Vulkan memory D3DKMT NT shared handle export. win32u: Create D3DKMT global resources for exported Vulkan memory. win32u: Swap VK_KHR_external_memory_win32 with the matching host extension. win32u: Pass the name of the extension to replace to get_host_extension. winevulkan: Treat LPCWSTR and HANDLE as pointer sized types.
 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winevulkan/make_vulkan | 2 +- dlls/winevulkan/vulkan_thunks.c | 57 +++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 25 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index d94ba9eadf4..2ccbc3a4b17 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -1225,7 +1225,7 @@ class VkVariable(object): return self.pointer and self.pointer.count('*') > 1
def is_pointer_size(self): - if self.type in ["size_t", "HWND", "HINSTANCE"] or self.type.startswith("PFN"): + if self.type in ["size_t", "HWND", "HINSTANCE", "HANDLE", "LPCWSTR"] or self.type.startswith("PFN"): return True if self.is_handle() and self.handle.is_dispatchable(): return True diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 7fa3491fedb..de26841399d 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -3110,7 +3110,7 @@ typedef struct VkExportFenceWin32HandleInfoKHR32 PTR32 pNext; PTR32 pAttributes; DWORD dwAccess; - LPCWSTR name; + PTR32 name; } VkExportFenceWin32HandleInfoKHR32;
typedef struct VkExportMemoryAllocateInfo32 @@ -3127,7 +3127,7 @@ typedef struct VkExportMemoryWin32HandleInfoKHR32 PTR32 pNext; PTR32 pAttributes; DWORD dwAccess; - LPCWSTR name; + PTR32 name; } VkExportMemoryWin32HandleInfoKHR32;
typedef struct VkExportSemaphoreCreateInfo32 @@ -3144,7 +3144,7 @@ typedef struct VkExportSemaphoreWin32HandleInfoKHR32 PTR32 pNext; PTR32 pAttributes; DWORD dwAccess; - LPCWSTR name; + PTR32 name; } VkExportSemaphoreWin32HandleInfoKHR32;
typedef struct VkExternalBufferProperties32 @@ -3667,8 +3667,8 @@ typedef struct VkImportFenceWin32HandleInfoKHR32 VkFence DECLSPEC_ALIGN(8) fence; VkFenceImportFlags flags; VkExternalFenceHandleTypeFlagBits handleType; - HANDLE handle; - LPCWSTR name; + PTR32 handle; + PTR32 name; } VkImportFenceWin32HandleInfoKHR32;
typedef struct VkImportMemoryHostPointerInfoEXT32 @@ -3684,8 +3684,8 @@ typedef struct VkImportMemoryWin32HandleInfoKHR32 VkStructureType sType; PTR32 pNext; VkExternalMemoryHandleTypeFlagBits handleType; - HANDLE handle; - LPCWSTR name; + PTR32 handle; + PTR32 name; } VkImportMemoryWin32HandleInfoKHR32;
typedef struct VkImportSemaphoreWin32HandleInfoKHR32 @@ -3695,8 +3695,8 @@ typedef struct VkImportSemaphoreWin32HandleInfoKHR32 VkSemaphore DECLSPEC_ALIGN(8) semaphore; VkSemaphoreImportFlags flags; VkExternalSemaphoreHandleTypeFlagBits handleType; - HANDLE handle; - LPCWSTR name; + PTR32 handle; + PTR32 name; } VkImportSemaphoreWin32HandleInfoKHR32;
typedef struct VkIndirectCommandsLayoutCreateInfoEXT32 @@ -9924,7 +9924,7 @@ static void convert_VkMemoryAllocateInfo_win32_to_host(struct conversion_context out_ext->pNext = NULL; out_ext->pAttributes = UlongToPtr(in_ext->pAttributes); out_ext->dwAccess = in_ext->dwAccess; - out_ext->name = in_ext->name; + out_ext->name = (LPCWSTR)UlongToPtr(in_ext->name); out_header->pNext = (void *)out_ext; out_header = (void *)out_ext; break; @@ -9948,8 +9948,8 @@ static void convert_VkMemoryAllocateInfo_win32_to_host(struct conversion_context out_ext->sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR; out_ext->pNext = NULL; out_ext->handleType = in_ext->handleType; - out_ext->handle = in_ext->handle; - out_ext->name = in_ext->name; + out_ext->handle = (HANDLE)UlongToPtr(in_ext->handle); + out_ext->name = (LPCWSTR)UlongToPtr(in_ext->name); out_header->pNext = (void *)out_ext; out_header = (void *)out_ext; break; @@ -22285,7 +22285,7 @@ static void convert_VkFenceCreateInfo_win32_to_host(struct conversion_context *c out_ext->pNext = NULL; out_ext->pAttributes = UlongToPtr(in_ext->pAttributes); out_ext->dwAccess = in_ext->dwAccess; - out_ext->name = in_ext->name; + out_ext->name = (LPCWSTR)UlongToPtr(in_ext->name); out_header->pNext = (void *)out_ext; out_header = (void *)out_ext; break; @@ -26176,7 +26176,7 @@ static void convert_VkSemaphoreCreateInfo_win32_to_host(struct conversion_contex out_ext->pNext = NULL; out_ext->pAttributes = UlongToPtr(in_ext->pAttributes); out_ext->dwAccess = in_ext->dwAccess; - out_ext->name = in_ext->name; + out_ext->name = (LPCWSTR)UlongToPtr(in_ext->name); out_header->pNext = (void *)out_ext; out_header = (void *)out_ext; break; @@ -39074,8 +39074,8 @@ static void convert_VkImportFenceWin32HandleInfoKHR_win32_to_unwrapped_host(cons out->fence = in->fence; out->flags = in->flags; out->handleType = in->handleType; - out->handle = in->handle; - out->name = in->name; + out->handle = (HANDLE)UlongToPtr(in->handle); + out->name = (LPCWSTR)UlongToPtr(in->name); if (in->pNext) FIXME("Unexpected pNext\n"); } @@ -39089,8 +39089,8 @@ static void convert_VkImportSemaphoreWin32HandleInfoKHR_win32_to_unwrapped_host( out->semaphore = in->semaphore; out->flags = in->flags; out->handleType = in->handleType; - out->handle = in->handle; - out->name = in->name; + out->handle = (HANDLE)UlongToPtr(in->handle); + out->name = (LPCWSTR)UlongToPtr(in->name); if (in->pNext) FIXME("Unexpected pNext\n"); } @@ -54753,11 +54753,14 @@ static NTSTATUS thunk32_vkGetFenceWin32HandleKHR(void *args) VkResult result; } *params = args; VkFenceGetWin32HandleInfoKHR pGetWin32HandleInfo_host; + HANDLE pHandle_host;
TRACE("%#x, %#x, %#x\n", params->device, params->pGetWin32HandleInfo, params->pHandle);
convert_VkFenceGetWin32HandleInfoKHR_win32_to_unwrapped_host((const VkFenceGetWin32HandleInfoKHR32 *)UlongToPtr(params->pGetWin32HandleInfo), &pGetWin32HandleInfo_host); - params->result = vk_funcs->p_vkGetFenceWin32HandleKHR((VkDevice)UlongToPtr(params->device), &pGetWin32HandleInfo_host, (HANDLE *)UlongToPtr(params->pHandle)); + pHandle_host = UlongToPtr(*(PTR32 *)UlongToPtr(params->pHandle)); + params->result = vk_funcs->p_vkGetFenceWin32HandleKHR((VkDevice)UlongToPtr(params->device), &pGetWin32HandleInfo_host, &pHandle_host); + *(PTR32 *)UlongToPtr(params->pHandle) = PtrToUlong(pHandle_host); return STATUS_SUCCESS; }
@@ -55458,11 +55461,14 @@ static NTSTATUS thunk32_vkGetMemoryWin32HandleKHR(void *args) VkResult result; } *params = args; VkMemoryGetWin32HandleInfoKHR pGetWin32HandleInfo_host; + HANDLE pHandle_host;
TRACE("%#x, %#x, %#x\n", params->device, params->pGetWin32HandleInfo, params->pHandle);
convert_VkMemoryGetWin32HandleInfoKHR_win32_to_unwrapped_host((const VkMemoryGetWin32HandleInfoKHR32 *)UlongToPtr(params->pGetWin32HandleInfo), &pGetWin32HandleInfo_host); - params->result = vk_funcs->p_vkGetMemoryWin32HandleKHR((VkDevice)UlongToPtr(params->device), &pGetWin32HandleInfo_host, (HANDLE *)UlongToPtr(params->pHandle)); + pHandle_host = UlongToPtr(*(PTR32 *)UlongToPtr(params->pHandle)); + params->result = vk_funcs->p_vkGetMemoryWin32HandleKHR((VkDevice)UlongToPtr(params->device), &pGetWin32HandleInfo_host, &pHandle_host); + *(PTR32 *)UlongToPtr(params->pHandle) = PtrToUlong(pHandle_host); return STATUS_SUCCESS; }
@@ -55484,16 +55490,16 @@ static NTSTATUS thunk32_vkGetMemoryWin32HandlePropertiesKHR(void *args) { PTR32 device; VkExternalMemoryHandleTypeFlagBits handleType; - HANDLE handle; + PTR32 handle; PTR32 pMemoryWin32HandleProperties; VkResult result; } *params = args; VkMemoryWin32HandlePropertiesKHR pMemoryWin32HandleProperties_host;
- TRACE("%#x, %#x, %p, %#x\n", params->device, params->handleType, params->handle, params->pMemoryWin32HandleProperties); + TRACE("%#x, %#x, %#x, %#x\n", params->device, params->handleType, params->handle, params->pMemoryWin32HandleProperties);
convert_VkMemoryWin32HandlePropertiesKHR_win32_to_host((VkMemoryWin32HandlePropertiesKHR32 *)UlongToPtr(params->pMemoryWin32HandleProperties), &pMemoryWin32HandleProperties_host); - params->result = vk_funcs->p_vkGetMemoryWin32HandlePropertiesKHR((VkDevice)UlongToPtr(params->device), params->handleType, params->handle, &pMemoryWin32HandleProperties_host); + params->result = vk_funcs->p_vkGetMemoryWin32HandlePropertiesKHR((VkDevice)UlongToPtr(params->device), params->handleType, (HANDLE)UlongToPtr(params->handle), &pMemoryWin32HandleProperties_host); convert_VkMemoryWin32HandlePropertiesKHR_host_to_win32(&pMemoryWin32HandleProperties_host, (VkMemoryWin32HandlePropertiesKHR32 *)UlongToPtr(params->pMemoryWin32HandleProperties)); return STATUS_SUCCESS; } @@ -58214,11 +58220,14 @@ static NTSTATUS thunk32_vkGetSemaphoreWin32HandleKHR(void *args) VkResult result; } *params = args; VkSemaphoreGetWin32HandleInfoKHR pGetWin32HandleInfo_host; + HANDLE pHandle_host;
TRACE("%#x, %#x, %#x\n", params->device, params->pGetWin32HandleInfo, params->pHandle);
convert_VkSemaphoreGetWin32HandleInfoKHR_win32_to_unwrapped_host((const VkSemaphoreGetWin32HandleInfoKHR32 *)UlongToPtr(params->pGetWin32HandleInfo), &pGetWin32HandleInfo_host); - params->result = vk_funcs->p_vkGetSemaphoreWin32HandleKHR((VkDevice)UlongToPtr(params->device), &pGetWin32HandleInfo_host, (HANDLE *)UlongToPtr(params->pHandle)); + pHandle_host = UlongToPtr(*(PTR32 *)UlongToPtr(params->pHandle)); + params->result = vk_funcs->p_vkGetSemaphoreWin32HandleKHR((VkDevice)UlongToPtr(params->device), &pGetWin32HandleInfo_host, &pHandle_host); + *(PTR32 *)UlongToPtr(params->pHandle) = PtrToUlong(pHandle_host); return STATUS_SUCCESS; }
 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/vulkan.c | 21 +++++++++++---------- dlls/winemac.drv/vulkan.c | 7 ++++--- dlls/winevulkan/vulkan.c | 2 +- dlls/winewayland.drv/vulkan.c | 7 ++++--- dlls/winex11.drv/vulkan.c | 7 ++++--- include/wine/vulkan_driver.h | 6 +++--- 6 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index f54a3a4bddc..361802d04c6 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -1374,9 +1374,9 @@ static void win32u_vkGetPhysicalDeviceExternalFenceProperties( VkPhysicalDevice instance->p_vkGetPhysicalDeviceExternalFenceProperties( physical_device->host.physical_device, fence_info, fence_properties ); }
-static const char *win32u_get_host_surface_extension(void) +static const char *win32u_get_host_extension( const char *name ) { - return driver_funcs->p_get_host_surface_extension(); + return driver_funcs->p_get_host_extension( name ); }
static struct vulkan_funcs vulkan_funcs = @@ -1426,7 +1426,7 @@ static struct vulkan_funcs vulkan_funcs = .p_vkQueueSubmit2KHR = win32u_vkQueueSubmit2, .p_vkUnmapMemory = win32u_vkUnmapMemory, .p_vkUnmapMemory2KHR = win32u_vkUnmapMemory2KHR, - .p_get_host_surface_extension = win32u_get_host_surface_extension, + .p_get_host_extension = win32u_get_host_extension, };
static VkResult nulldrv_vulkan_surface_create( HWND hwnd, const struct vulkan_instance *instance, VkSurfaceKHR *surface, @@ -1450,16 +1450,17 @@ static VkBool32 nulldrv_get_physical_device_presentation_support( struct vulkan_ return VK_TRUE; }
-static const char *nulldrv_get_host_surface_extension(void) +static const char *nulldrv_get_host_extension( const char *name ) { - return "VK_EXT_headless_surface"; + if (!strcmp( name, "VK_KHR_win32_surface" )) return "VK_EXT_headless_surface"; + return name; }
static const struct vulkan_driver_funcs nulldrv_funcs = { .p_vulkan_surface_create = nulldrv_vulkan_surface_create, .p_get_physical_device_presentation_support = nulldrv_get_physical_device_presentation_support, - .p_get_host_surface_extension = nulldrv_get_host_surface_extension, + .p_get_host_extension = nulldrv_get_host_extension, };
static void vulkan_driver_init(void) @@ -1474,7 +1475,7 @@ static void vulkan_driver_init(void) }
if (status == STATUS_NOT_IMPLEMENTED) driver_funcs = &nulldrv_funcs; - else vulkan_funcs.p_get_host_surface_extension = driver_funcs->p_get_host_surface_extension; + else vulkan_funcs.p_get_host_extension = driver_funcs->p_get_host_extension; }
static void vulkan_driver_load(void) @@ -1496,17 +1497,17 @@ static VkBool32 lazydrv_get_physical_device_presentation_support( struct vulkan_ return driver_funcs->p_get_physical_device_presentation_support( physical_device, queue ); }
-static const char *lazydrv_get_host_surface_extension(void) +static const char *lazydrv_get_host_extension( const char *name ) { vulkan_driver_load(); - return driver_funcs->p_get_host_surface_extension(); + return driver_funcs->p_get_host_extension( name ); }
static const struct vulkan_driver_funcs lazydrv_funcs = { .p_vulkan_surface_create = lazydrv_vulkan_surface_create, .p_get_physical_device_presentation_support = lazydrv_get_physical_device_presentation_support, - .p_get_host_surface_extension = lazydrv_get_host_surface_extension, + .p_get_host_extension = lazydrv_get_host_extension, };
static void vulkan_init_once(void) diff --git a/dlls/winemac.drv/vulkan.c b/dlls/winemac.drv/vulkan.c index 9f9e47bbb49..51d951139b9 100644 --- a/dlls/winemac.drv/vulkan.c +++ b/dlls/winemac.drv/vulkan.c @@ -99,16 +99,17 @@ static VkBool32 macdrv_get_physical_device_presentation_support(struct vulkan_ph }
static const char *host_surface_extension = "VK_MVK_macos_surface"; -static const char *macdrv_get_host_surface_extension(void) +static const char *macdrv_get_host_extension(const char *name) { - return host_surface_extension; + if (!strcmp( name, "VK_KHR_win32_surface" )) return host_surface_extension; + return name; }
static const struct vulkan_driver_funcs macdrv_vulkan_driver_funcs = { .p_vulkan_surface_create = macdrv_vulkan_surface_create, .p_get_physical_device_presentation_support = macdrv_get_physical_device_presentation_support, - .p_get_host_surface_extension = macdrv_get_host_surface_extension, + .p_get_host_extension = macdrv_get_host_extension, };
UINT macdrv_VulkanInit(UINT version, void *vulkan_handle, const struct vulkan_driver_funcs **driver_funcs) diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 19d2ba7ef42..05dc8e44cd7 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -715,7 +715,7 @@ static VkResult wine_vk_instance_convert_create_info(struct conversion_context * } if (!strcmp(*extension, "VK_KHR_win32_surface")) { - *extension = vk_funcs->p_get_host_surface_extension(); + *extension = vk_funcs->p_get_host_extension("VK_KHR_win32_surface"); instance->enable_win32_surface = VK_TRUE; } } diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index 1715f479076..f342112aeba 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -81,16 +81,17 @@ static VkBool32 wayland_get_physical_device_presentation_support(struct vulkan_p process_wayland.wl_display); }
-static const char *wayland_get_host_surface_extension(void) +static const char *wayland_get_host_extension(const char *name) { - return "VK_KHR_wayland_surface"; + if (!strcmp( name, "VK_KHR_win32_surface" )) return "VK_KHR_wayland_surface"; + return name; }
static const struct vulkan_driver_funcs wayland_vulkan_driver_funcs = { .p_vulkan_surface_create = wayland_vulkan_surface_create, .p_get_physical_device_presentation_support = wayland_get_physical_device_presentation_support, - .p_get_host_surface_extension = wayland_get_host_surface_extension, + .p_get_host_extension = wayland_get_host_extension, };
/********************************************************************** diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index 61e4327e379..4ef37fe1db5 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -78,16 +78,17 @@ static VkBool32 X11DRV_get_physical_device_presentation_support( struct vulkan_p default_visual.visual->visualid ); }
-static const char *X11DRV_get_host_surface_extension(void) +static const char *X11DRV_get_host_extension( const char *name ) { - return "VK_KHR_xlib_surface"; + if (!strcmp( name, "VK_KHR_win32_surface" )) return "VK_KHR_xlib_surface"; + return name; }
static const struct vulkan_driver_funcs x11drv_vulkan_driver_funcs = { .p_vulkan_surface_create = X11DRV_vulkan_surface_create, .p_get_physical_device_presentation_support = X11DRV_get_physical_device_presentation_support, - .p_get_host_surface_extension = X11DRV_get_host_surface_extension, + .p_get_host_extension = X11DRV_get_host_extension, };
UINT X11DRV_VulkanInit( UINT version, void *vulkan_handle, const struct vulkan_driver_funcs **driver_funcs ) diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h index 6a31bc75b5b..be2f5296082 100644 --- a/include/wine/vulkan_driver.h +++ b/include/wine/vulkan_driver.h @@ -47,7 +47,7 @@ struct vulkan_client_object #include "wine/rbtree.h"
/* Wine internal vulkan driver version, needs to be bumped upon vulkan_funcs changes. */ -#define WINE_VULKAN_DRIVER_VERSION 46 +#define WINE_VULKAN_DRIVER_VERSION 47
struct vulkan_object { @@ -257,7 +257,7 @@ struct vulkan_funcs PFN_vkUnmapMemory2KHR p_vkUnmapMemory2KHR;
/* winevulkan specific functions */ - const char *(*p_get_host_surface_extension)(void); + const char *(*p_get_host_extension)( const char *name ); };
/* interface between win32u and the user drivers */ @@ -266,7 +266,7 @@ struct vulkan_driver_funcs { VkResult (*p_vulkan_surface_create)(HWND, const struct vulkan_instance *, VkSurfaceKHR *, struct client_surface **); VkBool32 (*p_get_physical_device_presentation_support)(struct vulkan_physical_device *, uint32_t); - const char *(*p_get_host_surface_extension)(void); + const char *(*p_get_host_extension)( const char *name ); };
#endif /* WINE_UNIX_LIB */
 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/vulkan-1/tests/vulkan.c | 4 +-- dlls/win32u/tests/d3dkmt.c | 25 ++++---------- dlls/win32u/vulkan.c | 58 +++++++++++++++++--------------- dlls/winevulkan/vulkan.c | 50 ++++++++++++++++++++------- dlls/winevulkan/vulkan_private.h | 1 + dlls/winewayland.drv/vulkan.c | 1 + dlls/winex11.drv/vulkan.c | 1 + 7 files changed, 80 insertions(+), 60 deletions(-)
diff --git a/dlls/vulkan-1/tests/vulkan.c b/dlls/vulkan-1/tests/vulkan.c index 71ad2c4cf34..c4ad755595f 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); - ok(vr == VK_SUCCESS, "vkGetMemoryWin32HandleKHR failed, VkResult %d.\n", vr); + todo_wine 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); @@ -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); - ok(vr == VK_SUCCESS, "vkGetMemoryWin32HandleKHR failed, VkResult %d.\n", vr); + todo_wine 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/tests/d3dkmt.c b/dlls/win32u/tests/d3dkmt.c index a65ca1a4c02..4edb1195293 100644 --- a/dlls/win32u/tests/d3dkmt.c +++ b/dlls/win32u/tests/d3dkmt.c @@ -3363,12 +3363,12 @@ static struct vulkan_device *create_vulkan_device( LUID *luid )
winetest_push_context( "export" ); types = get_vulkan_external_image_types( dev->instance, physical_devices[i], VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR ); - todo_wine ok( !(~types & expect_export_types), "got types %#x\n", types ); + ok( !(~types & expect_export_types), "got types %#x\n", types ); winetest_pop_context();
winetest_push_context( "import" ); types = get_vulkan_external_image_types( dev->instance, physical_devices[i], VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR ); - todo_wine ok( !(~types & expect_import_types), "got types %#x\n", types ); + ok( !(~types & expect_import_types), "got types %#x\n", types ); winetest_pop_context(); }
@@ -3397,15 +3397,8 @@ static struct vulkan_device *create_vulkan_device( LUID *luid )
p_vkCreateDevice = (void *)p_vkGetInstanceProcAddr( dev->instance, "vkCreateDevice" ); vr = p_vkCreateDevice( dev->physical_device, &create_info, NULL, &dev->device ); - todo_wine ok_vk( VK_SUCCESS, vr ); - todo_wine ok_ptr( dev->device, !=, VK_NULL_HANDLE ); - if (dev->device == VK_NULL_HANDLE) - { - PFN_vkDestroyInstance p_vkDestroyInstance = (void *)p_vkGetInstanceProcAddr( dev->instance, "vkDestroyInstance" ); - p_vkDestroyInstance( dev->instance, NULL ); - free( dev ); - return NULL; - } + ok_vk( VK_SUCCESS, vr ); + ok_ptr( dev->device, !=, VK_NULL_HANDLE );
return dev; } @@ -3496,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 ); - ok_vk( VK_SUCCESS, vr ); + todo_wine ok_vk( VK_SUCCESS, vr );
return buf; } @@ -3638,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 ); - ok_vk( VK_SUCCESS, vr ); + todo_wine ok_vk( VK_SUCCESS, vr );
return img; } @@ -4646,42 +4639,36 @@ static void test_shared_resources(void)
case MAKETEST(4, 0, 0): { - if (!vulkan_exp) break; buf = export_vulkan_buffer( vulkan_exp, resource_size, NULL, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, &handle ); get_d3dkmt_resource_desc( luid, handle, FALSE, 0, runtime_desc ); break; } case MAKETEST(4, 0, 1): { - if (!vulkan_exp) break; buf = export_vulkan_buffer( vulkan_exp, resource_size, NULL, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, &handle ); get_d3dkmt_resource_desc( luid, handle, TRUE, 0, runtime_desc ); break; } case MAKETEST(4, 1, 0): { - if (!vulkan_exp) break; img = export_vulkan_image( vulkan_exp, width_1d, 1, array_1d, NULL, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, &handle ); get_d3dkmt_resource_desc( luid, handle, FALSE, 0, runtime_desc ); break; } case MAKETEST(4, 2, 0): { - if (!vulkan_exp) break; img = export_vulkan_image( vulkan_exp, width_2d, height_2d, 1, NULL, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, &handle ); get_d3dkmt_resource_desc( luid, handle, FALSE, 0, runtime_desc ); break; } case MAKETEST(4, 2, 1): { - if (!vulkan_exp) break; img = export_vulkan_image( vulkan_exp, width_2d, height_2d, 1, NULL, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, &handle ); get_d3dkmt_resource_desc( luid, handle, TRUE, 0, runtime_desc ); break; } case MAKETEST(4, 3, 0): { - if (!vulkan_exp) break; img = export_vulkan_image( vulkan_exp, width_3d, height_3d, depth_3d, NULL, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, &handle ); get_d3dkmt_resource_desc( luid, handle, FALSE, 0, runtime_desc ); break; diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 361802d04c6..58872f70cde 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -177,6 +177,14 @@ static VkResult allocate_external_host_memory( struct vulkan_device *device, VkM return VK_SUCCESS; }
+static VkExternalMemoryHandleTypeFlagBits get_host_external_memory_type(void) +{ + const char *host_extension = driver_funcs->p_get_host_extension( "VK_KHR_external_memory_win32" ); + if (!strcmp( host_extension, "VK_KHR_external_memory_fd" )) return VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; + if (!strcmp( host_extension, "VK_EXT_external_memory_dma_buf" )) return VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + return 0; +} + static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryAllocateInfo *client_alloc_info, const VkAllocationCallbacks *allocator, VkDeviceMemory *ret ) { @@ -202,8 +210,8 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA export_info = (VkExportMemoryAllocateInfo *)*next; if (!(export_info->handleTypes & EXTERNAL_MEMORY_WIN32_BITS)) FIXME( "Unsupported handle types %#x\n", export_info->handleTypes ); - FIXME( "VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO not implemented!\n" ); - *next = (*next)->pNext; next = &prev; + else + 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" ); @@ -450,8 +458,8 @@ static VkResult win32u_vkCreateBuffer( VkDevice client_device, const VkBufferCre external_info = (VkExternalMemoryBufferCreateInfo *)*next; if (!(external_info->handleTypes & EXTERNAL_MEMORY_WIN32_BITS)) FIXME( "Unsupported handle types %#x\n", external_info->handleTypes ); - FIXME( "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO not implemented!\n" ); - *next = (*next)->pNext; next = &prev; + else + external_info->handleTypes = get_host_external_memory_type(); break; case VK_STRUCTURE_TYPE_OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT: break; case VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR: break; @@ -491,8 +499,8 @@ static void win32u_vkGetDeviceBufferMemoryRequirements( VkDevice client_device, external_info = (VkExternalMemoryBufferCreateInfo *)*next; if (!(external_info->handleTypes & EXTERNAL_MEMORY_WIN32_BITS)) FIXME( "Unsupported handle types %#x\n", external_info->handleTypes ); - FIXME( "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO not implemented!\n" ); - *next = (*next)->pNext; next = &prev; + else + external_info->handleTypes = get_host_external_memory_type(); break; case VK_STRUCTURE_TYPE_OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT: break; case VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR: break; @@ -509,18 +517,15 @@ static void win32u_vkGetPhysicalDeviceExternalBufferProperties( VkPhysicalDevice VkPhysicalDeviceExternalBufferInfo *buffer_info = (VkPhysicalDeviceExternalBufferInfo *)client_buffer_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; + VkExternalMemoryHandleTypeFlagBits handle_type = 0;
TRACE( "physical_device %p, buffer_info %p, buffer_properties %p\n", physical_device, buffer_info, buffer_properties );
- if (!(buffer_info->handleType & EXTERNAL_MEMORY_WIN32_BITS)) - FIXME( "Unsupported handle type %#x\n", buffer_info->handleType ); - FIXME( "VkPhysicalDeviceExternalBufferInfo Win32 handleType not implemented!\n" ); - buffer_info->handleType = 0; + handle_type = buffer_info->handleType; + if (handle_type & EXTERNAL_MEMORY_WIN32_BITS) buffer_info->handleType = get_host_external_memory_type();
instance->p_vkGetPhysicalDeviceExternalBufferProperties( physical_device->host.physical_device, buffer_info, buffer_properties ); - buffer_properties->externalMemoryProperties.externalMemoryFeatures = 0; - buffer_properties->externalMemoryProperties.exportFromImportedHandleTypes = 0; - buffer_properties->externalMemoryProperties.compatibleHandleTypes = 0; + buffer_properties->externalMemoryProperties.compatibleHandleTypes = handle_type; }
static VkResult win32u_vkCreateImage( VkDevice client_device, const VkImageCreateInfo *create_info, @@ -540,8 +545,8 @@ static VkResult win32u_vkCreateImage( VkDevice client_device, const VkImageCreat external_info = (VkExternalMemoryImageCreateInfo *)*next; if (!(external_info->handleTypes & EXTERNAL_MEMORY_WIN32_BITS)) FIXME( "Unsupported handle types %#x\n", external_info->handleTypes ); - FIXME( "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO not implemented!\n" ); - *next = (*next)->pNext; next = &prev; + else + external_info->handleTypes = get_host_external_memory_type(); break; case VK_STRUCTURE_TYPE_IMAGE_ALIGNMENT_CONTROL_CREATE_INFO_MESA: break; case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT: break; @@ -584,8 +589,8 @@ static void win32u_vkGetDeviceImageMemoryRequirements( VkDevice client_device, c external_info = (VkExternalMemoryImageCreateInfo *)*next; if (!(external_info->handleTypes & EXTERNAL_MEMORY_WIN32_BITS)) FIXME( "Unsupported handle types %#x\n", external_info->handleTypes ); - FIXME( "VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO not implemented!\n" ); - *next = (*next)->pNext; next = &prev; + else + external_info->handleTypes = get_host_external_memory_type(); break; case VK_STRUCTURE_TYPE_IMAGE_ALIGNMENT_CONTROL_CREATE_INFO_MESA: break; case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT: break; @@ -608,7 +613,7 @@ static VkResult win32u_vkGetPhysicalDeviceImageFormatProperties2( VkPhysicalDevi VkBaseOutStructure **next, *prev = (VkBaseOutStructure *)format_info; /* cast away const, chain 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; - VkPhysicalDeviceExternalImageFormatInfo *external_info; + VkExternalMemoryHandleTypeFlagBits handle_type = 0; VkResult res;
TRACE( "physical_device %p, format_info %p, format_properties %p\n", physical_device, format_info, format_properties ); @@ -622,12 +627,12 @@ static VkResult win32u_vkGetPhysicalDeviceImageFormatProperties2( VkPhysicalDevi case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO: break; case VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_INFO_NV: break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: - external_info = (VkPhysicalDeviceExternalImageFormatInfo *)*next; - if (!(external_info->handleType & EXTERNAL_MEMORY_WIN32_BITS)) - FIXME( "Unsupported handle type %#x\n", external_info->handleType ); - FIXME( "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO not implemented!\n" ); - *next = (*next)->pNext; next = &prev; + { + VkPhysicalDeviceExternalImageFormatInfo *external_info = (VkPhysicalDeviceExternalImageFormatInfo *)*next; + handle_type = external_info->handleType; + if (handle_type & EXTERNAL_MEMORY_WIN32_BITS) external_info->handleType = get_host_external_memory_type(); break; + } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT: break; case VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR: break; default: FIXME( "Unhandled sType %u.\n", (*next)->sType ); break; @@ -635,16 +640,14 @@ static VkResult win32u_vkGetPhysicalDeviceImageFormatProperties2( VkPhysicalDevi }
res = instance->p_vkGetPhysicalDeviceImageFormatProperties2( physical_device->host.physical_device, format_info, format_properties ); - if (!res) for (prev = (VkBaseOutStructure *)format_properties, next = &prev->pNext; *next; prev = *next, next = &(*next)->pNext) + for (prev = (VkBaseOutStructure *)format_properties, next = &prev->pNext; *next; prev = *next, next = &(*next)->pNext) { switch ((*next)->sType) { case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES: { VkExternalImageFormatProperties *props = (VkExternalImageFormatProperties *)*next; - props->externalMemoryProperties.externalMemoryFeatures = 0; - props->externalMemoryProperties.exportFromImportedHandleTypes = 0; - props->externalMemoryProperties.compatibleHandleTypes = 0; + props->externalMemoryProperties.compatibleHandleTypes = handle_type; break; } case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT: break; @@ -1453,6 +1456,7 @@ static VkBool32 nulldrv_get_physical_device_presentation_support( struct vulkan_ 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"; return name; }
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 05dc8e44cd7..c8869e82f71 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -366,7 +366,8 @@ static VkResult vulkan_physical_device_init(struct vulkan_physical_device *physi */ for (i = 0; i < num_host_properties; i++) { - if (wine_vk_device_extension_supported(host_properties[i].extensionName)) + if (!strcmp(host_properties[i].extensionName, vk_funcs->p_get_host_extension("VK_KHR_external_memory_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); num_properties++; @@ -397,7 +398,12 @@ static VkResult vulkan_physical_device_init(struct vulkan_physical_device *physi
for (i = 0, j = 0; i < num_host_properties; i++) { - if (wine_vk_device_extension_supported(host_properties[i].extensionName)) + if (!strcmp(host_properties[i].extensionName, vk_funcs->p_get_host_extension("VK_KHR_external_memory_win32"))) + { + 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 (wine_vk_device_extension_supported(host_properties[i].extensionName)) { physical_device->extensions[j] = host_properties[i]; j++; @@ -532,8 +538,8 @@ static void wine_vk_device_init_queues(struct wine_device *object, const VkDevic object->queue_count += info->queueCount; }
-static VkResult wine_vk_device_convert_create_info(struct vulkan_physical_device *physical_device, - struct conversion_context *ctx, const VkDeviceCreateInfo *src, VkDeviceCreateInfo *dst) +static VkResult wine_vk_device_convert_create_info(struct vulkan_physical_device *physical_device, struct conversion_context *ctx, + const VkDeviceCreateInfo *src, VkDeviceCreateInfo *dst, struct wine_device *device) { bool has_swapchain_maintenance1 = false; bool has_external_memory_host = false; @@ -570,6 +576,12 @@ static VkResult wine_vk_device_convert_create_info(struct vulkan_physical_device if (!strcmp(*extension, "VK_EXT_swapchain_maintenance1")) has_swapchain_maintenance1 = true; if (!strcmp(*extension, "VK_EXT_surface_maintenance1")) has_surface_maintenance1 = true; if (!strcmp(*extension, "VK_KHR_swapchain")) has_swapchain = true; + if (!strcmp(*extension, "VK_KHR_external_memory_win32")) + { + device->has_external_memory_win32 = true; + *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 (physical_device->map_placed_align) @@ -894,7 +906,7 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice client_physical_device, const VkDe return VK_ERROR_OUT_OF_HOST_MEMORY;
init_conversion_context(&ctx); - res = wine_vk_device_convert_create_info(physical_device, &ctx, create_info, &create_info_host); + res = wine_vk_device_convert_create_info(physical_device, &ctx, create_info, &create_info_host, device); if (res == VK_SUCCESS) res = instance->p_vkCreateDevice(physical_device->host.physical_device, &create_info_host, NULL /* allocator */, &host_device); @@ -1767,8 +1779,14 @@ NTSTATUS vk_is_available_instance_function(void *arg) NTSTATUS vk_is_available_device_function(void *arg) { struct is_available_device_function_params *params = arg; - struct vulkan_device *device = vulkan_device_from_handle(params->device); - return !!vk_funcs->p_vkGetDeviceProcAddr(device->host.device, params->name); + struct wine_device *device = wine_device_from_handle(params->device); + + if (!strcmp(params->name, "vkGetMemoryWin32HandleKHR")) + return device->has_external_memory_win32; + if (!strcmp(params->name, "vkGetMemoryWin32HandlePropertiesKHR")) + return device->has_external_memory_win32; + + return !!vk_funcs->p_vkGetDeviceProcAddr(device->obj.host.device, params->name); }
#endif /* _WIN64 */ @@ -1781,13 +1799,14 @@ NTSTATUS vk_is_available_instance_function32(void *arg) UINT32 name; } *params = arg; struct wine_instance *instance = wine_instance_from_handle(UlongToPtr(params->instance)); + const char *name = UlongToPtr(params->name);
- if (!strcmp(UlongToPtr(params->name), "vkCreateWin32SurfaceKHR")) + if (!strcmp(name, "vkCreateWin32SurfaceKHR")) return instance->enable_win32_surface; - if (!strcmp(UlongToPtr(params->name), "vkGetPhysicalDeviceWin32PresentationSupportKHR")) + if (!strcmp(name, "vkGetPhysicalDeviceWin32PresentationSupportKHR")) return instance->enable_win32_surface;
- return !!vk_funcs->p_vkGetInstanceProcAddr(instance->obj.host.instance, UlongToPtr(params->name)); + return !!vk_funcs->p_vkGetInstanceProcAddr(instance->obj.host.instance, name); }
NTSTATUS vk_is_available_device_function32(void *arg) @@ -1797,6 +1816,13 @@ NTSTATUS vk_is_available_device_function32(void *arg) UINT32 device; UINT32 name; } *params = arg; - struct vulkan_device *device = vulkan_device_from_handle(UlongToPtr(params->device)); - return !!vk_funcs->p_vkGetDeviceProcAddr(device->host.device, UlongToPtr(params->name)); + struct wine_device *device = wine_device_from_handle(UlongToPtr(params->device)); + const char *name = UlongToPtr(params->name); + + if (!strcmp(name, "vkGetMemoryWin32HandleKHR")) + return device->has_external_memory_win32; + if (!strcmp(name, "vkGetMemoryWin32HandlePropertiesKHR")) + return device->has_external_memory_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 51fd39c4813..d3ef04ada20 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -41,6 +41,7 @@ struct wine_queue struct wine_device { struct vulkan_device obj; + bool has_external_memory_win32; uint64_t queue_count; struct wine_queue queues[]; }; diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index f342112aeba..cd5c5295cb1 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -84,6 +84,7 @@ static VkBool32 wayland_get_physical_device_presentation_support(struct vulkan_p 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"; return name; }
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index 4ef37fe1db5..f49f382b3a6 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -81,6 +81,7 @@ static VkBool32 X11DRV_get_physical_device_presentation_support( struct vulkan_p 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"; return name; }
 
            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 ++ dlls/winevulkan/vulkan.c | 58 ++++++++++++++++-------------------- 6 files changed, 109 insertions(+), 43 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 diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index c8869e82f71..af14a493ec0 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -1761,32 +1761,42 @@ void wine_vkDestroyDeferredOperationKHR(VkDevice device_handle, free(object); }
-#ifdef _WIN64 - -NTSTATUS vk_is_available_instance_function(void *arg) +static NTSTATUS is_available_instance_function(VkInstance handle, const char *name) { - struct is_available_instance_function_params *params = arg; - struct wine_instance *instance = wine_instance_from_handle(params->instance); + struct wine_instance *instance = wine_instance_from_handle(handle);
- if (!strcmp(params->name, "vkCreateWin32SurfaceKHR")) + if (!strcmp(name, "vkCreateWin32SurfaceKHR")) return instance->enable_win32_surface; - if (!strcmp(params->name, "vkGetPhysicalDeviceWin32PresentationSupportKHR")) + if (!strcmp(name, "vkGetPhysicalDeviceWin32PresentationSupportKHR")) return instance->enable_win32_surface;
- return !!vk_funcs->p_vkGetInstanceProcAddr(instance->obj.host.instance, params->name); + return !!vk_funcs->p_vkGetInstanceProcAddr(instance->obj.host.instance, name); }
-NTSTATUS vk_is_available_device_function(void *arg) +static NTSTATUS is_available_device_function(VkDevice handle, const char *name) { - struct is_available_device_function_params *params = arg; - struct wine_device *device = wine_device_from_handle(params->device); + struct wine_device *device = wine_device_from_handle(handle);
- if (!strcmp(params->name, "vkGetMemoryWin32HandleKHR")) + if (!strcmp(name, "vkGetMemoryWin32HandleKHR")) return device->has_external_memory_win32; - if (!strcmp(params->name, "vkGetMemoryWin32HandlePropertiesKHR")) + if (!strcmp(name, "vkGetMemoryWin32HandlePropertiesKHR")) return device->has_external_memory_win32;
- return !!vk_funcs->p_vkGetDeviceProcAddr(device->obj.host.device, params->name); + return !!vk_funcs->p_vkGetDeviceProcAddr(device->obj.host.device, name); +} + +#ifdef _WIN64 + +NTSTATUS vk_is_available_instance_function(void *arg) +{ + struct is_available_instance_function_params *params = arg; + return is_available_instance_function(params->instance, params->name); +} + +NTSTATUS vk_is_available_device_function(void *arg) +{ + struct is_available_device_function_params *params = arg; + return is_available_device_function(params->device, params->name); }
#endif /* _WIN64 */ @@ -1798,15 +1808,7 @@ NTSTATUS vk_is_available_instance_function32(void *arg) UINT32 instance; UINT32 name; } *params = arg; - struct wine_instance *instance = wine_instance_from_handle(UlongToPtr(params->instance)); - const char *name = UlongToPtr(params->name); - - if (!strcmp(name, "vkCreateWin32SurfaceKHR")) - return instance->enable_win32_surface; - if (!strcmp(name, "vkGetPhysicalDeviceWin32PresentationSupportKHR")) - return instance->enable_win32_surface; - - return !!vk_funcs->p_vkGetInstanceProcAddr(instance->obj.host.instance, name); + return is_available_instance_function(UlongToPtr(params->instance), UlongToPtr(params->name)); }
NTSTATUS vk_is_available_device_function32(void *arg) @@ -1816,13 +1818,5 @@ NTSTATUS vk_is_available_device_function32(void *arg) UINT32 device; UINT32 name; } *params = arg; - struct wine_device *device = wine_device_from_handle(UlongToPtr(params->device)); - const char *name = UlongToPtr(params->name); - - if (!strcmp(name, "vkGetMemoryWin32HandleKHR")) - return device->has_external_memory_win32; - if (!strcmp(name, "vkGetMemoryWin32HandlePropertiesKHR")) - return device->has_external_memory_win32; - - return !!vk_funcs->p_vkGetDeviceProcAddr(device->obj.host.device, name); + return is_available_device_function(UlongToPtr(params->device), UlongToPtr(params->name)); }
 
            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;
 
            From: Rémi Bernon rbernon@codeweavers.com
Only try to open the shared handle for now, then close the object. --- dlls/vulkan-1/tests/vulkan.c | 4 +-- dlls/win32u/d3dkmt.c | 26 +++++++++++++++++ dlls/win32u/vulkan.c | 55 ++++++++++++++++++++++++++++++------ dlls/win32u/win32u_private.h | 1 + 4 files changed, 75 insertions(+), 11 deletions(-)
diff --git a/dlls/vulkan-1/tests/vulkan.c b/dlls/vulkan-1/tests/vulkan.c index 71ad2c4cf34..138f914d713 100644 --- a/dlls/vulkan-1/tests/vulkan.c +++ b/dlls/vulkan-1/tests/vulkan.c @@ -1154,8 +1154,8 @@ static void import_memory(VkDevice vk_device, VkMemoryAllocateInfo alloc_info, V import_handle_info.name = L"wine_test_buffer_export_name";
vr = vkAllocateMemory(vk_device, &alloc_info, NULL, &memory); - ok(vr == VK_SUCCESS, "vkAllocateMemory failed, VkResult %d.\n", vr); - vkFreeMemory(vk_device, memory, NULL); + todo_wine ok(vr == VK_SUCCESS, "vkAllocateMemory failed, VkResult %d.\n", vr); + if (vr == VK_SUCCESS) vkFreeMemory(vk_device, memory, NULL); } }
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 4c130f2f6fd..e96cea74c49 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -231,6 +231,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; @@ -263,7 +264,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: - FIXME( "VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR not implemented!\n" ); + import_win32 = (VkImportMemoryWin32HandleInfoKHR *)*next; *next = (*next)->pNext; next = &prev; break; case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO: break; @@ -282,22 +283,48 @@ 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; + } + + FIXME( "Importing memory handle not yet implemented!\n" ); + } + 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) { FIXME( "Exporting memory handle not yet implemented!\n" );
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 ); @@ -310,6 +337,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; } @@ -378,14 +406,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 */
 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/vulkan-1/tests/vulkan.c | 4 ++-- dlls/win32u/vulkan.c | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/dlls/vulkan-1/tests/vulkan.c b/dlls/vulkan-1/tests/vulkan.c index 138f914d713..71ad2c4cf34 100644 --- a/dlls/vulkan-1/tests/vulkan.c +++ b/dlls/vulkan-1/tests/vulkan.c @@ -1154,8 +1154,8 @@ static void import_memory(VkDevice vk_device, VkMemoryAllocateInfo alloc_info, V import_handle_info.name = L"wine_test_buffer_export_name";
vr = vkAllocateMemory(vk_device, &alloc_info, NULL, &memory); - todo_wine ok(vr == VK_SUCCESS, "vkAllocateMemory failed, VkResult %d.\n", vr); - if (vr == VK_SUCCESS) vkFreeMemory(vk_device, memory, NULL); + ok(vr == VK_SUCCESS, "vkAllocateMemory failed, VkResult %d.\n", vr); + vkFreeMemory(vk_device, memory, NULL); } }
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index e96cea74c49..b7b5127b9c6 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -221,6 +221,24 @@ static HANDLE create_shared_handle( D3DKMT_HANDLE local, const VkExportMemoryWin return NULL; }
+static HANDLE open_shared_handle_from_name( const WCHAR *name ) +{ + D3DKMT_OPENNTHANDLEFROMNAME 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 = NtGdiDdDDIOpenNtHandleFromName( &open_name ); + if (status) WARN( "Failed to open %s, status %#x\n", debugstr_w( name ), status ); + return open_name.hNtHandle; +} + static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryAllocateInfo *client_alloc_info, const VkAllocationCallbacks *allocator, VkDeviceMemory *ret ) { @@ -296,8 +314,13 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA 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 ); + { + HANDLE shared = import_win32->handle; + if (import_win32->name && !(shared = open_shared_handle_from_name( import_win32->name ))) break; + memory->local = d3dkmt_open_resource( 0, shared ); + if (shared && shared != import_win32->handle) NtClose( shared ); break; + } default: FIXME( "Unsupported handle type %#x\n", import_win32->handleType ); break;
 
            v3: Fix some issues with WOW64, although the tests will still fail because we're unable to create a vulkan instance on Gitlab CI. The reason for that is that we haven't any vulkan driver installed.
I've opened https://gitlab.winehq.org/wine/wine/-/merge_requests/9119 to fix that issue, this MR should be good otherwise now.

