 
            First step to implement VK_KHR_external_memory_win32 and shared resources.
 
            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/win32u/tests/d3dkmt.c | 25 ++++---------- dlls/win32u/vulkan.c | 58 +++++++++++++++++--------------- dlls/winevulkan/vulkan.c | 32 ++++++++++++++---- dlls/winevulkan/vulkan_private.h | 1 + dlls/winewayland.drv/vulkan.c | 1 + dlls/winex11.drv/vulkan.c | 1 + 6 files changed, 65 insertions(+), 53 deletions(-)
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..40bb9eb2175 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 */ 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/win32u/vulkan.c | 16 ++++++++++++++++ dlls/winevulkan/make_vulkan | 2 ++ dlls/winevulkan/vulkan_thunks.c | 8 ++++---- include/wine/vulkan_driver.h | 2 ++ 4 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 58872f70cde..0972c64625c 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -478,6 +478,13 @@ static VkResult win32u_vkCreateBuffer( VkDevice client_device, const VkBufferCre return device->p_vkCreateBuffer( device->host.device, create_info, NULL, buffer ); }
+static void win32u_vkDestroyBuffer( VkDevice client_device, VkBuffer buffer, const VkAllocationCallbacks *allocator ) +{ + struct vulkan_device *device = vulkan_device_from_handle( client_device ); + + device->p_vkDestroyBuffer( device->host.device, buffer, NULL ); +} + static void win32u_vkGetDeviceBufferMemoryRequirements( VkDevice client_device, const VkDeviceBufferMemoryRequirements *buffer_requirements, VkMemoryRequirements2 *memory_requirements ) { @@ -571,6 +578,13 @@ static VkResult win32u_vkCreateImage( VkDevice client_device, const VkImageCreat return device->p_vkCreateImage( device->host.device, create_info, NULL, image ); }
+static void win32u_vkDestroyImage( VkDevice client_device, VkImage image, const VkAllocationCallbacks *allocator ) +{ + struct vulkan_device *device = vulkan_device_from_handle( client_device ); + + device->p_vkDestroyImage( device->host.device, image, NULL ); +} + static void win32u_vkGetDeviceImageMemoryRequirements( VkDevice client_device, const VkDeviceImageMemoryRequirements *image_requirements, VkMemoryRequirements2 *memory_requirements ) { @@ -1393,6 +1407,8 @@ static struct vulkan_funcs vulkan_funcs = .p_vkCreateSemaphore = win32u_vkCreateSemaphore, .p_vkCreateSwapchainKHR = win32u_vkCreateSwapchainKHR, .p_vkCreateWin32SurfaceKHR = win32u_vkCreateWin32SurfaceKHR, + .p_vkDestroyBuffer = win32u_vkDestroyBuffer, + .p_vkDestroyImage = win32u_vkDestroyImage, .p_vkDestroyFence = win32u_vkDestroyFence, .p_vkDestroySemaphore = win32u_vkDestroySemaphore, .p_vkDestroySurfaceKHR = win32u_vkDestroySurfaceKHR, diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index d94ba9eadf4..c2a5b62ec2e 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -204,6 +204,8 @@ USER_DRIVER_FUNCS = { "vkCreateSemaphore", "vkCreateSwapchainKHR", "vkCreateWin32SurfaceKHR", + "vkDestroyBuffer", + "vkDestroyImage", "vkDestroyFence", "vkDestroySemaphore", "vkDestroySurfaceKHR", diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 7fa3491fedb..de2ac6b4b1d 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -51185,7 +51185,7 @@ static NTSTATUS thunk64_vkDestroyBuffer(void *args)
TRACE("%p, 0x%s, %p\n", params->device, wine_dbgstr_longlong(params->buffer), params->pAllocator);
- vulkan_device_from_handle(params->device)->p_vkDestroyBuffer(vulkan_device_from_handle(params->device)->host.device, params->buffer, NULL); + vk_funcs->p_vkDestroyBuffer(params->device, params->buffer, params->pAllocator); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -51201,7 +51201,7 @@ static NTSTATUS thunk32_vkDestroyBuffer(void *args)
TRACE("%#x, 0x%s, %#x\n", params->device, wine_dbgstr_longlong(params->buffer), params->pAllocator);
- vulkan_device_from_handle((VkDevice)UlongToPtr(params->device))->p_vkDestroyBuffer(vulkan_device_from_handle((VkDevice)UlongToPtr(params->device))->host.device, params->buffer, NULL); + vk_funcs->p_vkDestroyBuffer((VkDevice)UlongToPtr(params->device), params->buffer, (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator)); return STATUS_SUCCESS; }
@@ -51649,7 +51649,7 @@ static NTSTATUS thunk64_vkDestroyImage(void *args)
TRACE("%p, 0x%s, %p\n", params->device, wine_dbgstr_longlong(params->image), params->pAllocator);
- vulkan_device_from_handle(params->device)->p_vkDestroyImage(vulkan_device_from_handle(params->device)->host.device, params->image, NULL); + vk_funcs->p_vkDestroyImage(params->device, params->image, params->pAllocator); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -51665,7 +51665,7 @@ static NTSTATUS thunk32_vkDestroyImage(void *args)
TRACE("%#x, 0x%s, %#x\n", params->device, wine_dbgstr_longlong(params->image), params->pAllocator);
- vulkan_device_from_handle((VkDevice)UlongToPtr(params->device))->p_vkDestroyImage(vulkan_device_from_handle((VkDevice)UlongToPtr(params->device))->host.device, params->image, NULL); + vk_funcs->p_vkDestroyImage((VkDevice)UlongToPtr(params->device), params->image, (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator)); return STATUS_SUCCESS; }
diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h index be2f5296082..92d5386e4df 100644 --- a/include/wine/vulkan_driver.h +++ b/include/wine/vulkan_driver.h @@ -217,6 +217,8 @@ struct vulkan_funcs PFN_vkCreateSemaphore p_vkCreateSemaphore; PFN_vkCreateSwapchainKHR p_vkCreateSwapchainKHR; PFN_vkCreateWin32SurfaceKHR p_vkCreateWin32SurfaceKHR; + PFN_vkDestroyBuffer p_vkDestroyBuffer; + PFN_vkDestroyImage p_vkDestroyImage; PFN_vkDestroyFence p_vkDestroyFence; PFN_vkDestroySemaphore p_vkDestroySemaphore; PFN_vkDestroySurfaceKHR p_vkDestroySurfaceKHR;
 
            From: Rémi Bernon rbernon@codeweavers.com
DATADIR is used in objidl and will cause compilation errors when d3d headers are included on the unix side. --- dlls/ntdll/Makefile.in | 2 +- dlls/ntdll/unix/loader.c | 2 +- server/Makefile.in | 2 +- server/unicode.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index f7558bb5d86..975c50d0050 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -77,5 +77,5 @@ EXTRA_OBJS = unix/version.o unix_loader_EXTRADEFS = \ -DBINDIR="${bindir}" \ -DLIBDIR="${libdir}" \ - -DDATADIR="${datadir}" \ + -DSHAREDIR="${datadir}" \ -DSYSTEMDLLPATH="${system_dllpath}" diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 3208499a59b..bad01406bd0 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -462,7 +462,7 @@ static void init_paths(void) { if (!(dll_dir = remove_tail( ntdll_dir, get_so_dir(current_machine) ))) dll_dir = ntdll_dir; bin_dir = build_relative_path( dll_dir, LIBDIR "/wine", BINDIR ); - data_dir = build_relative_path( dll_dir, LIBDIR "/wine", DATADIR "/wine" ); + data_dir = build_relative_path( dll_dir, LIBDIR "/wine", SHAREDIR "/wine" ); wineloader = build_path( ntdll_dir, "wine" ); }
diff --git a/server/Makefile.in b/server/Makefile.in index d3d50b9aa5a..55548e6cd58 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -52,4 +52,4 @@ SOURCES = \ UNIX_CFLAGS = $(INOTIFY_CFLAGS) UNIX_LIBS = $(LDEXECFLAGS) $(RT_LIBS) $(INOTIFY_LIBS) $(PROCSTAT_LIBS)
-unicode_EXTRADEFS = -DBINDIR=""${bindir}"" -DDATADIR=""${datadir}"" +unicode_EXTRADEFS = -DBINDIR=""${bindir}"" -DSHAREDIR=""${datadir}"" diff --git a/server/unicode.c b/server/unicode.c index bb39b55e50c..e759e284135 100644 --- a/server/unicode.c +++ b/server/unicode.c @@ -319,7 +319,7 @@ static char *get_nls_dir(void) strcpy( p - 8, "/nls" ); return dir; } - ret = build_relative_path( dir, BINDIR, DATADIR "/wine/nls" ); + ret = build_relative_path( dir, BINDIR, SHAREDIR "/wine/nls" ); free( dir ); return ret; } @@ -327,7 +327,7 @@ static char *get_nls_dir(void) /* load the case mapping table */ struct fd *load_intl_file(void) { - static const char *nls_dirs[] = { NULL, DATADIR "/wine/nls", "/usr/local/share/wine/nls", "/usr/share/wine/nls" }; + static const char *nls_dirs[] = { NULL, SHAREDIR "/wine/nls", "/usr/local/share/wine/nls", "/usr/share/wine/nls" }; static const WCHAR nt_pathW[] = {'C',':','\','w','i','n','d','o','w','s','\', 's','y','s','t','e','m','3','2','\','l','_','i','n','t','l','.','n','l','s',0}; static const struct unicode_str nt_name = { nt_pathW, sizeof(nt_pathW) };
 
            From: Rémi Bernon rbernon@codeweavers.com
This will be part of the public ABI for third-party D3D implementations wanting to support D3D shared resources on Wine. --- dlls/win32u/font.c | 1 + dlls/winewayland.drv/waylanddrv.h | 4 ++ include/ntuser.h | 112 ++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+)
diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index ed2ef5200b2..208959efbe9 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -40,6 +40,7 @@ #include "winternl.h" #include "winreg.h" #include "ntgdi_private.h" +#undef small
#include "wine/unixlib.h" #include "wine/rbtree.h" diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index cb331df789d..0b286c8fedf 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -42,6 +42,10 @@ #include "windef.h" #include "winbase.h" #include "ntgdi.h" +#include "ntuser.h" +#undef interface +#undef small + #include "wine/gdi_driver.h" #include "wine/list.h" #include "wine/rbtree.h" diff --git a/include/ntuser.h b/include/ntuser.h index 0cf257d4d07..f85a9daa972 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -25,6 +25,13 @@ #include <immdev.h> #include <shellapi.h> #include <winternl.h> +#include <d3dukmdt.h> + +#include <d3d9types.h> +#include <dxgi.h> +#include <d3d10.h> +#include <d3d11.h> +#include <d3d12.h>
#ifndef W32KAPI # if defined(_WIN32U_) || defined(WINE_UNIX_LIB) @@ -370,6 +377,111 @@ struct drag_drop_post_params
C_ASSERT( sizeof(struct drag_drop_post_params) == offsetof(struct drag_drop_post_params, files[0]) );
+ +/* D3DKMT runtime descriptors */ + +struct d3dkmt_dxgi_desc +{ + UINT size; + UINT version; + UINT width; + UINT height; + DXGI_FORMAT format; + UINT unknown_0; + UINT unknown_1; + UINT keyed_mutex; + D3DKMT_HANDLE mutex_handle; + D3DKMT_HANDLE sync_handle; + UINT nt_shared; + UINT unknown_2; + UINT unknown_3; + UINT unknown_4; +}; + +struct d3dkmt_d3d9_desc +{ + struct d3dkmt_dxgi_desc dxgi; + D3DFORMAT format; + D3DRESOURCETYPE type; + UINT usage; + union + { + struct + { + UINT unknown_0; + UINT width; + UINT height; + UINT levels; + UINT depth; + } texture; + struct + { + UINT unknown_0; + UINT unknown_1; + UINT unknown_2; + UINT width; + UINT height; + } surface; + struct + { + UINT unknown_0; + UINT width; + UINT format; + UINT unknown_1; + UINT unknown_2; + } buffer; + }; +}; + +C_ASSERT( sizeof(struct d3dkmt_d3d9_desc) == 0x58 ); + +struct d3dkmt_d3d11_desc +{ + struct d3dkmt_dxgi_desc dxgi; + D3D11_RESOURCE_DIMENSION dimension; + union + { + D3D10_BUFFER_DESC d3d10_buf; + D3D10_TEXTURE1D_DESC d3d10_1d; + D3D10_TEXTURE2D_DESC d3d10_2d; + D3D10_TEXTURE3D_DESC d3d10_3d; + D3D11_BUFFER_DESC d3d11_buf; + D3D11_TEXTURE1D_DESC d3d11_1d; + D3D11_TEXTURE2D_DESC d3d11_2d; + D3D11_TEXTURE3D_DESC d3d11_3d; + }; +}; + +C_ASSERT( sizeof(struct d3dkmt_d3d11_desc) == 0x68 ); + +struct d3dkmt_d3d12_desc +{ + struct d3dkmt_d3d11_desc d3d11; + UINT unknown_5[4]; + UINT resource_size; + UINT unknown_6[7]; + UINT resource_align; + UINT unknown_7[9]; + union + { + D3D12_RESOURCE_DESC desc; + D3D12_RESOURCE_DESC1 desc1; + }; + UINT64 unknown_8[1]; +}; + +C_ASSERT( sizeof(struct d3dkmt_d3d12_desc) == 0x108 ); +C_ASSERT( offsetof(struct d3dkmt_d3d12_desc, unknown_5) == sizeof(struct d3dkmt_d3d11_desc) ); + +union d3dkmt_desc +{ + struct d3dkmt_dxgi_desc dxgi; + struct d3dkmt_d3d9_desc d3d9; + struct d3dkmt_d3d11_desc d3d11; + struct d3dkmt_d3d12_desc d3d12; +}; + + /* DPI awareness contexts */ #define MAKE_NTUSER_DPI_CONTEXT( awareness, version, dpi, flags ) ((awareness) | ((version) << 4) | ((dpi) << 8) | (flags)) #define NTUSER_DPI_CONTEXT_GET_AWARENESS( ctx ) ((ctx) & 0x0f)
 
            From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/vulkan.c | 287 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 282 insertions(+), 5 deletions(-)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 0972c64625c..fab083132d2 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -46,12 +46,265 @@ WINE_DECLARE_DEBUG_CHANNEL(fps);
static const struct vulkan_driver_funcs *driver_funcs;
-static const UINT EXTERNAL_MEMORY_WIN32_BITS = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT | - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT | +static const UINT EXTERNAL_SHARED_WIN32_BITS = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT | - VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT; +static const UINT EXTERNAL_MEMORY_WIN32_BITS = EXTERNAL_SHARED_WIN32_BITS | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT; + +struct desc_entry +{ + UINT64 handle; /* VkImage or VkBuffer handle */ + union d3dkmt_desc desc; /* D3D runtime desc of the resource */ + struct rb_entry entry; +}; + +static int desc_entry_compare( const void *ptr, const struct rb_entry *entry ) +{ + const struct desc_entry *info = RB_ENTRY_VALUE( entry, struct desc_entry, entry ); + UINT64 handle = *(UINT64 *)ptr; + + if (handle < info->handle) return -1; + if (handle > info->handle) return 1; + return 0; +} + +static pthread_mutex_t desc_entries_lock = PTHREAD_MUTEX_INITIALIZER; +static struct rb_tree buffer_descs = {.compare = desc_entry_compare}; +static struct rb_tree image_descs = {.compare = desc_entry_compare}; + +static void desc_entries_put( struct rb_tree *descs, UINT64 handle, const union d3dkmt_desc *desc ) +{ + struct desc_entry *entry, *previous = NULL; + struct rb_entry *ptr; + + if (!(entry = malloc( sizeof(*entry) ))) return; + entry->handle = handle; + entry->desc = *desc; + + pthread_mutex_lock( &desc_entries_lock ); + + if (!(ptr = rb_get( descs, &entry->handle ))) + rb_put( descs, &entry->handle, &entry->entry ); + else + { + previous = RB_ENTRY_VALUE( ptr, struct desc_entry, entry ); + rb_replace( descs, &previous->entry, &entry->entry ); + } + + pthread_mutex_unlock( &desc_entries_lock ); + free( previous ); +} + +static void desc_entries_remove( struct rb_tree *descs, UINT64 handle ) +{ + struct desc_entry *entry; + struct rb_entry *ptr; + + pthread_mutex_lock( &desc_entries_lock ); + if (!(ptr = rb_get( descs, &handle ))) entry = NULL; + else + { + entry = RB_ENTRY_VALUE( ptr, struct desc_entry, entry ); + rb_remove( descs, ptr ); + } + pthread_mutex_unlock( &desc_entries_lock ); + + free( entry ); +} + +static void init_buffer_d3dkmt_desc( union d3dkmt_desc *desc, const VkMemoryRequirements *requirements, const VkBufferCreateInfo *create_info, + const VkExternalMemoryBufferCreateInfo *external_info ) +{ + BOOL shared = !!(external_info->handleTypes & EXTERNAL_SHARED_WIN32_BITS); + + desc->d3d12.d3d11.dxgi.size = sizeof(desc->d3d12.d3d11); + desc->d3d12.d3d11.dxgi.version = 4; + desc->d3d12.d3d11.dxgi.width = create_info->size; + desc->d3d12.d3d11.dxgi.height = 1; + desc->d3d12.d3d11.dxgi.format = DXGI_FORMAT_UNKNOWN; + desc->d3d12.d3d11.dxgi.keyed_mutex = 0; + desc->d3d12.d3d11.dxgi.mutex_handle = 0; + desc->d3d12.d3d11.dxgi.sync_handle = 0; + desc->d3d12.d3d11.dxgi.nt_shared = shared; + desc->d3d12.d3d11.dimension = D3D11_RESOURCE_DIMENSION_BUFFER; + desc->d3d12.d3d11.d3d11_buf.ByteWidth = create_info->size; + desc->d3d12.d3d11.d3d11_buf.Usage = D3D11_USAGE_DEFAULT; + desc->d3d12.d3d11.d3d11_buf.BindFlags = 0; + desc->d3d12.d3d11.d3d11_buf.CPUAccessFlags = 0; + desc->d3d12.d3d11.d3d11_buf.MiscFlags = D3D11_RESOURCE_MISC_SHARED | (shared ? D3D11_RESOURCE_MISC_SHARED_NTHANDLE : 0); + desc->d3d12.d3d11.d3d11_buf.StructureByteStride = 0; + desc->d3d12.resource_size = requirements->size; + desc->d3d12.resource_align = requirements->alignment; + desc->d3d12.desc1.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc->d3d12.desc1.Alignment = requirements->alignment; + desc->d3d12.desc1.Width = create_info->size; + desc->d3d12.desc1.Height = 1; + desc->d3d12.desc1.DepthOrArraySize = 1; + desc->d3d12.desc1.MipLevels = 1; + desc->d3d12.desc1.Format = DXGI_FORMAT_UNKNOWN; + desc->d3d12.desc1.SampleDesc.Count = 1; + desc->d3d12.desc1.SampleDesc.Quality = 0; + desc->d3d12.desc1.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc->d3d12.desc1.Flags = D3D12_RESOURCE_FLAG_NONE; + desc->d3d12.desc1.SamplerFeedbackMipRegion.Width = 0; + desc->d3d12.desc1.SamplerFeedbackMipRegion.Height = 0; + desc->d3d12.desc1.SamplerFeedbackMipRegion.Depth = 0; +} + +static DXGI_FORMAT dxgi_format_from_vk_format( VkFormat format ) +{ + switch (format) + { + case VK_FORMAT_UNDEFINED: return DXGI_FORMAT_UNKNOWN; + case VK_FORMAT_R32G32B32A32_SFLOAT: return DXGI_FORMAT_R32G32B32A32_FLOAT; + case VK_FORMAT_R32G32B32A32_UINT: return DXGI_FORMAT_R32G32B32A32_UINT; + case VK_FORMAT_R32G32B32A32_SINT: return DXGI_FORMAT_R32G32B32A32_SINT; + case VK_FORMAT_R32G32B32_SFLOAT: return DXGI_FORMAT_R32G32B32_FLOAT; + case VK_FORMAT_R32G32B32_UINT: return DXGI_FORMAT_R32G32B32_UINT; + case VK_FORMAT_R32G32B32_SINT: return DXGI_FORMAT_R32G32B32_SINT; + case VK_FORMAT_R16G16B16A16_SFLOAT: return DXGI_FORMAT_R16G16B16A16_FLOAT; + case VK_FORMAT_R16G16B16A16_UNORM: return DXGI_FORMAT_R16G16B16A16_UNORM; + case VK_FORMAT_R16G16B16A16_UINT: return DXGI_FORMAT_R16G16B16A16_UINT; + case VK_FORMAT_R16G16B16A16_SNORM: return DXGI_FORMAT_R16G16B16A16_SNORM; + case VK_FORMAT_R16G16B16A16_SINT: return DXGI_FORMAT_R16G16B16A16_SINT; + case VK_FORMAT_R32G32_SFLOAT: return DXGI_FORMAT_R32G32_FLOAT; + case VK_FORMAT_R32G32_UINT: return DXGI_FORMAT_R32G32_UINT; + case VK_FORMAT_R32G32_SINT: return DXGI_FORMAT_R32G32_SINT; + case VK_FORMAT_A2B10G10R10_UNORM_PACK32: return DXGI_FORMAT_R10G10B10A2_UNORM; + case VK_FORMAT_A2B10G10R10_UINT_PACK32: return DXGI_FORMAT_R10G10B10A2_UINT; + case VK_FORMAT_B10G11R11_UFLOAT_PACK32: return DXGI_FORMAT_R11G11B10_FLOAT; + case VK_FORMAT_R8G8_UNORM: return DXGI_FORMAT_R8G8_UNORM; + case VK_FORMAT_R8G8_UINT: return DXGI_FORMAT_R8G8_UINT; + case VK_FORMAT_R8G8_SNORM: return DXGI_FORMAT_R8G8_SNORM; + case VK_FORMAT_R8G8_SINT: return DXGI_FORMAT_R8G8_SINT; + case VK_FORMAT_R8G8B8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM; + case VK_FORMAT_R8G8B8A8_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + case VK_FORMAT_R8G8B8A8_UINT: return DXGI_FORMAT_R8G8B8A8_UINT; + case VK_FORMAT_R8G8B8A8_SNORM: return DXGI_FORMAT_R8G8B8A8_SNORM; + case VK_FORMAT_R8G8B8A8_SINT: return DXGI_FORMAT_R8G8B8A8_SINT; + case VK_FORMAT_R16G16_SFLOAT: return DXGI_FORMAT_R16G16_FLOAT; + case VK_FORMAT_R16G16_UNORM: return DXGI_FORMAT_R16G16_UNORM; + case VK_FORMAT_R16G16_UINT: return DXGI_FORMAT_R16G16_UINT; + case VK_FORMAT_R16G16_SNORM: return DXGI_FORMAT_R16G16_SNORM; + case VK_FORMAT_R16G16_SINT: return DXGI_FORMAT_R16G16_SINT; + case VK_FORMAT_D32_SFLOAT: return DXGI_FORMAT_D32_FLOAT; + case VK_FORMAT_R32_SFLOAT: return DXGI_FORMAT_R32_FLOAT; + case VK_FORMAT_R32_UINT: return DXGI_FORMAT_R32_UINT; + case VK_FORMAT_R32_SINT: return DXGI_FORMAT_R32_SINT; + case VK_FORMAT_R16_SFLOAT: return DXGI_FORMAT_R16_FLOAT; + case VK_FORMAT_D16_UNORM: return DXGI_FORMAT_D16_UNORM; + case VK_FORMAT_R16_UNORM: return DXGI_FORMAT_R16_UNORM; + case VK_FORMAT_R16_UINT: return DXGI_FORMAT_R16_UINT; + case VK_FORMAT_R16_SNORM: return DXGI_FORMAT_R16_SNORM; + case VK_FORMAT_R16_SINT: return DXGI_FORMAT_R16_SINT; + case VK_FORMAT_R8_UNORM: return DXGI_FORMAT_R8_UNORM; + case VK_FORMAT_R8_UINT: return DXGI_FORMAT_R8_UINT; + case VK_FORMAT_R8_SNORM: return DXGI_FORMAT_R8_SNORM; + case VK_FORMAT_R8_SINT: return DXGI_FORMAT_R8_SINT; + case VK_FORMAT_R5G6B5_UNORM_PACK16: return DXGI_FORMAT_B5G6R5_UNORM; + case VK_FORMAT_A1R5G5B5_UNORM_PACK16: return DXGI_FORMAT_B5G5R5A1_UNORM; + case VK_FORMAT_B8G8R8A8_UNORM: return DXGI_FORMAT_B8G8R8A8_UNORM; + case VK_FORMAT_B8G8R8A8_SRGB: return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return DXGI_FORMAT_BC1_UNORM; + case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: return DXGI_FORMAT_BC1_UNORM_SRGB; + case VK_FORMAT_BC2_UNORM_BLOCK: return DXGI_FORMAT_BC2_UNORM; + case VK_FORMAT_BC2_SRGB_BLOCK: return DXGI_FORMAT_BC2_UNORM_SRGB; + case VK_FORMAT_BC3_UNORM_BLOCK: return DXGI_FORMAT_BC3_UNORM; + case VK_FORMAT_BC3_SRGB_BLOCK: return DXGI_FORMAT_BC3_UNORM_SRGB; + case VK_FORMAT_BC4_UNORM_BLOCK: return DXGI_FORMAT_BC4_UNORM; + case VK_FORMAT_BC4_SNORM_BLOCK: return DXGI_FORMAT_BC4_SNORM; + case VK_FORMAT_BC5_UNORM_BLOCK: return DXGI_FORMAT_BC5_UNORM; + case VK_FORMAT_BC5_SNORM_BLOCK: return DXGI_FORMAT_BC5_SNORM; + case VK_FORMAT_BC6H_UFLOAT_BLOCK: return DXGI_FORMAT_BC6H_UF16; + case VK_FORMAT_BC6H_SFLOAT_BLOCK: return DXGI_FORMAT_BC6H_SF16; + case VK_FORMAT_BC7_UNORM_BLOCK: return DXGI_FORMAT_BC7_UNORM; + case VK_FORMAT_BC7_SRGB_BLOCK: return DXGI_FORMAT_BC7_UNORM_SRGB; + default: FIXME( "Unsupported format %#x\n", format ); return DXGI_FORMAT_UNKNOWN; + } +} + +static void init_image_d3dkmt_desc( union d3dkmt_desc *desc, const VkMemoryRequirements *requirements, const VkImageCreateInfo *create_info, + const VkExternalMemoryImageCreateInfo *external_info ) +{ + BOOL shared = !!(external_info->handleTypes & EXTERNAL_SHARED_WIN32_BITS); + DXGI_FORMAT format = dxgi_format_from_vk_format( create_info->format ); + + desc->d3d12.d3d11.dxgi.size = sizeof(desc->d3d12.d3d11); + desc->d3d12.d3d11.dxgi.version = 4; + desc->d3d12.d3d11.dxgi.width = create_info->extent.width; + desc->d3d12.d3d11.dxgi.height = create_info->extent.height; + desc->d3d12.d3d11.dxgi.format = format; + desc->d3d12.d3d11.dxgi.keyed_mutex = 0; + desc->d3d12.d3d11.dxgi.mutex_handle = 0; + desc->d3d12.d3d11.dxgi.sync_handle = 0; + desc->d3d12.d3d11.dxgi.nt_shared = shared; + + switch (create_info->imageType) + { + case VK_IMAGE_TYPE_1D: + desc->d3d12.d3d11.dimension = D3D11_RESOURCE_DIMENSION_TEXTURE1D; + desc->d3d12.d3d11.d3d11_1d.Width = create_info->extent.width; + desc->d3d12.d3d11.d3d11_1d.MipLevels = create_info->mipLevels; + desc->d3d12.d3d11.d3d11_1d.ArraySize = create_info->arrayLayers; + desc->d3d12.d3d11.d3d11_1d.Format = format; + desc->d3d12.d3d11.d3d11_1d.Usage = D3D11_USAGE_DEFAULT; + desc->d3d12.d3d11.d3d11_1d.BindFlags = 0; + desc->d3d12.d3d11.d3d11_1d.CPUAccessFlags = 0; + desc->d3d12.d3d11.d3d11_1d.MiscFlags = D3D11_RESOURCE_MISC_SHARED | (shared ? D3D11_RESOURCE_MISC_SHARED_NTHANDLE : 0); + desc->d3d12.desc1.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE1D; + desc->d3d12.desc1.DepthOrArraySize = create_info->arrayLayers; + break; + case VK_IMAGE_TYPE_2D: + desc->d3d12.d3d11.dimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D; + desc->d3d12.d3d11.d3d11_2d.Width = create_info->extent.width; + desc->d3d12.d3d11.d3d11_2d.Height = create_info->extent.height; + desc->d3d12.d3d11.d3d11_2d.MipLevels = create_info->mipLevels; + desc->d3d12.d3d11.d3d11_2d.ArraySize = create_info->arrayLayers; + desc->d3d12.d3d11.d3d11_2d.Format = format; + desc->d3d12.d3d11.d3d11_2d.SampleDesc.Count = 1; + desc->d3d12.d3d11.d3d11_2d.SampleDesc.Quality = 0; + desc->d3d12.d3d11.d3d11_2d.Usage = D3D11_USAGE_DEFAULT; + desc->d3d12.d3d11.d3d11_2d.BindFlags = 0; + desc->d3d12.d3d11.d3d11_2d.CPUAccessFlags = 0; + desc->d3d12.d3d11.d3d11_2d.MiscFlags = D3D11_RESOURCE_MISC_SHARED | (shared ? D3D11_RESOURCE_MISC_SHARED_NTHANDLE : 0); + desc->d3d12.desc1.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + desc->d3d12.desc1.DepthOrArraySize = create_info->arrayLayers; + break; + case VK_IMAGE_TYPE_3D: + desc->d3d12.d3d11.dimension = D3D11_RESOURCE_DIMENSION_TEXTURE3D; + desc->d3d12.d3d11.d3d11_3d.Width = create_info->extent.width; + desc->d3d12.d3d11.d3d11_3d.Height = create_info->extent.height; + desc->d3d12.d3d11.d3d11_3d.Depth = create_info->extent.depth; + desc->d3d12.d3d11.d3d11_3d.MipLevels = create_info->mipLevels; + desc->d3d12.d3d11.d3d11_3d.Format = format; + desc->d3d12.d3d11.d3d11_3d.Usage = D3D11_USAGE_DEFAULT; + desc->d3d12.d3d11.d3d11_3d.BindFlags = 0; + desc->d3d12.d3d11.d3d11_3d.CPUAccessFlags = 0; + desc->d3d12.d3d11.d3d11_3d.MiscFlags = D3D11_RESOURCE_MISC_SHARED | (shared ? D3D11_RESOURCE_MISC_SHARED_NTHANDLE : 0); + desc->d3d12.desc1.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D; + desc->d3d12.desc1.DepthOrArraySize = create_info->extent.depth; + break; + default: FIXME( "Unsupported image type %#x\n", create_info->imageType ); break; + } + + desc->d3d12.resource_size = requirements->size; + desc->d3d12.resource_align = requirements->alignment; + desc->d3d12.desc1.Alignment = requirements->alignment; + desc->d3d12.desc1.Width = create_info->extent.width; + desc->d3d12.desc1.Height = create_info->extent.height; + desc->d3d12.desc1.MipLevels = create_info->mipLevels; + desc->d3d12.desc1.Format = format; + desc->d3d12.desc1.SampleDesc.Count = 1; + desc->d3d12.desc1.SampleDesc.Quality = 0; + desc->d3d12.desc1.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + desc->d3d12.desc1.Flags = D3D12_RESOURCE_FLAG_NONE; + desc->d3d12.desc1.SamplerFeedbackMipRegion.Width = 0; + desc->d3d12.desc1.SamplerFeedbackMipRegion.Height = 0; + desc->d3d12.desc1.SamplerFeedbackMipRegion.Depth = 0; +}
struct device_memory { @@ -445,6 +698,8 @@ static VkResult win32u_vkCreateBuffer( VkDevice client_device, const VkBufferCre struct vulkan_device *device = vulkan_device_from_handle( client_device ); struct vulkan_physical_device *physical_device = device->physical_device; VkExternalMemoryBufferCreateInfo host_external_info, *external_info = NULL; + union d3dkmt_desc desc; + VkResult result;
for (next = &prev->pNext; *next; prev = *next, next = &(*next)->pNext) { @@ -475,7 +730,16 @@ static VkResult win32u_vkCreateBuffer( VkDevice client_device, const VkBufferCre ((VkBufferCreateInfo *)create_info)->pNext = &host_external_info; /* cast away const, it has been copied in the thunks */ }
- return device->p_vkCreateBuffer( device->host.device, create_info, NULL, buffer ); + result = device->p_vkCreateBuffer( device->host.device, create_info, NULL, buffer ); + if (!result && external_info) + { + VkMemoryRequirements requirements; + device->p_vkGetBufferMemoryRequirements( device->host.device, *buffer, &requirements ); + init_buffer_d3dkmt_desc( &desc, &requirements, create_info, external_info ); + desc_entries_put( &buffer_descs, *buffer, &desc ); + } + + return result; }
static void win32u_vkDestroyBuffer( VkDevice client_device, VkBuffer buffer, const VkAllocationCallbacks *allocator ) @@ -483,6 +747,7 @@ static void win32u_vkDestroyBuffer( VkDevice client_device, VkBuffer buffer, con struct vulkan_device *device = vulkan_device_from_handle( client_device );
device->p_vkDestroyBuffer( device->host.device, buffer, NULL ); + desc_entries_remove( &buffer_descs, buffer ); }
static void win32u_vkGetDeviceBufferMemoryRequirements( VkDevice client_device, const VkDeviceBufferMemoryRequirements *buffer_requirements, @@ -542,6 +807,8 @@ static VkResult win32u_vkCreateImage( VkDevice client_device, const VkImageCreat struct vulkan_device *device = vulkan_device_from_handle( client_device ); struct vulkan_physical_device *physical_device = device->physical_device; VkExternalMemoryImageCreateInfo host_external_info, *external_info = NULL; + union d3dkmt_desc desc; + VkResult result;
for (next = &prev->pNext; *next; prev = *next, next = &(*next)->pNext) { @@ -575,7 +842,16 @@ static VkResult win32u_vkCreateImage( VkDevice client_device, const VkImageCreat ((VkImageCreateInfo *)create_info)->pNext = &host_external_info; /* cast away const, it has been copied in the thunks */ }
- return device->p_vkCreateImage( device->host.device, create_info, NULL, image ); + result = device->p_vkCreateImage( device->host.device, create_info, NULL, image ); + if (!result && external_info) + { + VkMemoryRequirements requirements; + device->p_vkGetImageMemoryRequirements( device->host.device, *image, &requirements ); + init_image_d3dkmt_desc( &desc, &requirements, create_info, external_info ); + desc_entries_put( &image_descs, *image, &desc ); + } + + return result; }
static void win32u_vkDestroyImage( VkDevice client_device, VkImage image, const VkAllocationCallbacks *allocator ) @@ -583,6 +859,7 @@ static void win32u_vkDestroyImage( VkDevice client_device, VkImage image, const struct vulkan_device *device = vulkan_device_from_handle( client_device );
device->p_vkDestroyImage( device->host.device, image, NULL ); + desc_entries_remove( &image_descs, image ); }
static void win32u_vkGetDeviceImageMemoryRequirements( VkDevice client_device, const VkDeviceImageMemoryRequirements *image_requirements,
 
            This merge request was closed by Rémi Bernon.

