From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/vulkan.c | 418 +++++++++++++++++++++++++++- dlls/winevulkan/loader.c | 20 +- dlls/winevulkan/loader_thunks.h | 1 - dlls/winevulkan/make_vulkan | 5 +- dlls/winevulkan/vulkan.c | 468 ++------------------------------ dlls/winevulkan/vulkan_thunks.c | 9 +- dlls/winevulkan/vulkan_thunks.h | 3 +- include/wine/vulkan_driver.h | 14 +- 8 files changed, 450 insertions(+), 488 deletions(-)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 80a7eae4855..ede47f6e4b0 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -37,6 +37,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr = NULL; PFN_vkGetInstanceProcAddr p_vkGetInstanceProcAddr = NULL; +static PFN_vkCreateInstance p_vkCreateInstance; +static PFN_vkEnumerateInstanceExtensionProperties p_vkEnumerateInstanceExtensionProperties;
static void *vulkan_handle; static struct vulkan_funcs vulkan_funcs; @@ -61,6 +63,11 @@ static const UINT EXTERNAL_FENCE_WIN32_BITS = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQ
#define ROUND_SIZE(size, mask) ((((SIZE_T)(size) + (mask)) & ~(SIZE_T)(mask)))
+static BOOL use_external_memory(void) +{ + return zero_bits != 0; +} + struct mempool { struct mempool *next; @@ -93,6 +100,24 @@ static void *mem_alloc( struct mempool *pool, size_t size ) return next->mem; }
+struct instance +{ + struct vulkan_instance obj; + BOOL enable_win32_surface; + + struct list utils_messengers; + struct list report_callbacks; + + struct rb_tree objects; + pthread_rwlock_t objects_lock; +}; + +static struct instance *instance_from_handle( VkInstance handle ) +{ + struct vulkan_instance *object = vulkan_instance_from_handle( handle ); + return CONTAINING_RECORD( object, struct instance, obj ); +} + struct device_memory { struct vulkan_device_memory obj; @@ -307,6 +332,338 @@ static HANDLE open_shared_resource_from_name( const WCHAR *name ) return open_name.hNtHandle; }
+static const void *find_next_struct( const VkBaseInStructure *header, VkStructureType type ) +{ + for (; header; header = header->pNext) if (header->sType == type) return header; + return NULL; +} + +static int vulkan_object_compare( const void *key, const struct rb_entry *entry ) +{ + struct vulkan_object *object = RB_ENTRY_VALUE( entry, struct vulkan_object, entry ); + const uint64_t *host_handle = key; + if (*host_handle < object->host_handle) return -1; + if (*host_handle > object->host_handle) return 1; + return 0; +} + +static uint64_t vulkan_instance_client_handle_from_host( struct vulkan_instance *instance, uint64_t host_handle ) +{ + struct instance *impl = CONTAINING_RECORD( instance, struct instance, obj ); + struct rb_entry *entry; + uint64_t result = 0; + + pthread_rwlock_rdlock( &impl->objects_lock ); + if ((entry = rb_get( &impl->objects, &host_handle ))) + { + struct vulkan_object *object = RB_ENTRY_VALUE( entry, struct vulkan_object, entry ); + result = object->client_handle; + } + pthread_rwlock_unlock( &impl->objects_lock ); + return result; +} + +static void vulkan_instance_insert_object( struct vulkan_instance *instance, struct vulkan_object *obj ) +{ + struct instance *impl = CONTAINING_RECORD( instance, struct instance, obj ); + if (impl->objects.compare) + { + pthread_rwlock_wrlock( &impl->objects_lock ); + rb_put( &impl->objects, &obj->host_handle, &obj->entry ); + pthread_rwlock_unlock( &impl->objects_lock ); + } +} + +static void vulkan_instance_remove_object( struct vulkan_instance *instance, struct vulkan_object *obj ) +{ + struct instance *impl = CONTAINING_RECORD( instance, struct instance, obj ); + if (impl->objects.compare) + { + pthread_rwlock_wrlock( &impl->objects_lock ); + rb_remove( &impl->objects, &obj->entry ); + pthread_rwlock_unlock( &impl->objects_lock ); + } +} + +static void free_debug_utils_messengers( struct list *messengers ) +{ + struct vulkan_debug_utils_messenger *messenger, *next; + + LIST_FOR_EACH_ENTRY_SAFE( messenger, next, messengers, struct vulkan_debug_utils_messenger, entry ) + { + list_remove( &messenger->entry ); + free( messenger ); + } +} + +static void free_debug_report_callbacks( struct list *callbacks ) +{ + struct vulkan_debug_report_callback *callback, *next; + + LIST_FOR_EACH_ENTRY_SAFE( callback, next, callbacks, struct vulkan_debug_report_callback, entry ) + { + list_remove( &callback->entry ); + free( callback ); + } +} + +static VkResult convert_instance_create_info( struct mempool *pool, VkInstanceCreateInfo *info, struct instance *instance ) +{ + const VkBaseInStructure *header = (const VkBaseInStructure *)info; + const VkDebugReportCallbackCreateInfoEXT *debug_report_callback; + const char **extensions; + uint32_t count = 0; + + while ((header = find_next_struct( header->pNext, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT ))) + { + const VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger = (const VkDebugUtilsMessengerCreateInfoEXT *)header; + struct vulkan_debug_utils_messenger *messenger = debug_utils_messenger->pUserData; + + list_remove( &messenger->entry ); + list_add_tail( &instance->utils_messengers, &messenger->entry ); + messenger->instance = &instance->obj; + } + + if ((debug_report_callback = find_next_struct( info->pNext, VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT ))) + { + struct vulkan_debug_report_callback *callback = debug_report_callback->pUserData; + + list_remove( &callback->entry ); + list_add_tail( &instance->report_callbacks, &callback->entry ); + callback->instance = &instance->obj; + } + + if (info->enabledLayerCount) + { + FIXME( "Loading explicit layers is not supported!\n" ); + return VK_ERROR_LAYER_NOT_PRESENT; + } + + driver_funcs->p_map_instance_extensions( &instance->obj.extensions ); + instance->obj.extensions.has_VK_KHR_win32_surface = 0; + + if (instance->obj.extensions.has_VK_EXT_debug_utils || instance->obj.extensions.has_VK_EXT_debug_report) + { + rb_init( &instance->objects, vulkan_object_compare ); + pthread_rwlock_init( &instance->objects_lock, NULL ); + } + + if (instance->obj.extensions.has_VK_KHR_win32_surface && vulkan_funcs.host_extensions.has_VK_EXT_surface_maintenance1) + instance->obj.extensions.has_VK_EXT_surface_maintenance1 = 1; + if (use_external_memory()) + { + instance->obj.extensions.has_VK_KHR_get_physical_device_properties2 = 1; + instance->obj.extensions.has_VK_KHR_external_memory_capabilities = 1; + } + + if (!(extensions = mem_alloc( pool, sizeof(instance->obj.extensions) * 8 * sizeof(*extensions) ))) return VK_ERROR_OUT_OF_HOST_MEMORY; +#define USE_VK_EXT(x) if (instance->obj.extensions.has_ ## x) extensions[count++] = #x; + ALL_VK_INSTANCE_EXTS +#undef USE_VK_EXT + + TRACE( "Enabling %u host instance extensions\n", count ); + for (const char **extension = extensions, **end = extension + count; extension < end; extension++) + TRACE( " - %s\n", debugstr_a(*extension) ); + + info->ppEnabledExtensionNames = extensions; + info->enabledExtensionCount = count; + return VK_SUCCESS; +} + +static VkResult init_physical_device( struct vulkan_physical_device *physical_device, VkPhysicalDevice host_physical_device, + VkPhysicalDevice client_physical_device, struct vulkan_instance *instance ) +{ + struct vulkan_device_extensions extensions = {0}; + VkExtensionProperties *properties; + uint32_t count; + VkResult res; + + vulkan_object_init_ptr( &physical_device->obj, (UINT_PTR)host_physical_device, &client_physical_device->obj ); + physical_device->instance = instance; + + instance->p_vkGetPhysicalDeviceMemoryProperties( host_physical_device, &physical_device->memory_properties ); + + if ((res = instance->p_vkEnumerateDeviceExtensionProperties( host_physical_device, NULL, &count, NULL ))) return res; + if (!(properties = calloc( count, sizeof(*properties) ))) return res; + if ((res = instance->p_vkEnumerateDeviceExtensionProperties( host_physical_device, NULL, &count, properties ))) goto done; + + TRACE( "Host physical device extensions:\n" ); + for (uint32_t i = 0; i < count; i++) + { + const char *extension = properties[i].extensionName; +#define USE_VK_EXT(x) \ + if (!strcmp( extension, #x )) \ + { \ + extensions.has_ ## x = 1; \ + TRACE( " - %s\n", extension ); \ + } else + ALL_VK_DEVICE_EXTS +#undef USE_VK_EXT + WARN( "Extension %s is not supported.\n", debugstr_a(extension) ); + } + physical_device->extensions = extensions; + + if (zero_bits && physical_device->extensions.has_VK_EXT_map_memory_placed && physical_device->extensions.has_VK_KHR_map_memory2) + { + VkPhysicalDeviceMapMemoryPlacedFeaturesEXT map_placed_feature = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT}; + VkPhysicalDeviceFeatures2 features = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, .pNext = &map_placed_feature}; + + instance->p_vkGetPhysicalDeviceFeatures2KHR( host_physical_device, &features ); + if (map_placed_feature.memoryMapPlaced && map_placed_feature.memoryUnmapReserve) + { + VkPhysicalDeviceMapMemoryPlacedPropertiesEXT map_placed_props = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT}; + VkPhysicalDeviceProperties2 props = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,.pNext = &map_placed_props}; + + instance->p_vkGetPhysicalDeviceProperties2( host_physical_device, &props ); + physical_device->map_placed_align = map_placed_props.minPlacedMemoryMapAlignment; + TRACE( "Using placed map with alignment %u\n", physical_device->map_placed_align ); + } + } + + if (zero_bits && physical_device->extensions.has_VK_EXT_external_memory_host && !physical_device->map_placed_align) + { + VkPhysicalDeviceExternalMemoryHostPropertiesEXT host_mem_props = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT}; + VkPhysicalDeviceProperties2 props = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, .pNext = &host_mem_props}; + + instance->p_vkGetPhysicalDeviceProperties2KHR( host_physical_device, &props ); + physical_device->external_memory_align = host_mem_props.minImportedHostPointerAlignment; + if (physical_device->external_memory_align) WARN( "Not using VK_EXT_external_memory_host for memory mapping\n" ); + else TRACE( "Using VK_EXT_external_memory_host for memory mapping with alignment: %u\n", physical_device->external_memory_align ); + } + + driver_funcs->p_map_device_extensions( &extensions ); + if (extensions.has_VK_KHR_external_memory_win32 && zero_bits && !physical_device->map_placed_align) + { + WARN( "Cannot export WOW64 memory without VK_EXT_map_memory_placed\n" ); + extensions.has_VK_KHR_external_memory_win32 = 0; + } + extensions.has_VK_KHR_win32_keyed_mutex = extensions.has_VK_KHR_timeline_semaphore; + + /* filter out unsupported client device extensions */ +#define USE_VK_EXT(x) client_physical_device->extensions.has_ ## x = extensions.has_ ## x; + ALL_VK_CLIENT_DEVICE_EXTS +#undef USE_VK_EXT + +done: + free( properties ); + return res; +} + +/* Helper function which stores wrapped physical devices in the instance object. */ +static VkResult init_physical_devices( struct vulkan_instance *instance, struct vulkan_physical_device *physical_devices ) +{ + VkInstance client_instance = instance->client.instance; + VkPhysicalDevice *host_physical_devices; + uint32_t physical_device_count; + unsigned int i; + VkResult res; + + if ((res = instance->p_vkEnumeratePhysicalDevices( instance->host.instance, &physical_device_count, NULL ))) + { + ERR( "Failed to enumerate physical devices, res %d\n", res ); + return res; + } + if (!physical_device_count) return res; + + if (physical_device_count > client_instance->physical_device_count) + { + client_instance->physical_device_count = physical_device_count; + return VK_ERROR_OUT_OF_POOL_MEMORY; + } + client_instance->physical_device_count = physical_device_count; + + if (!(host_physical_devices = calloc( physical_device_count, sizeof(*host_physical_devices) ))) return VK_ERROR_OUT_OF_HOST_MEMORY; + if ((res = instance->p_vkEnumeratePhysicalDevices( instance->host.instance, &physical_device_count, host_physical_devices ))) goto failed; + + /* Wrap each host physical device handle into a dispatchable object for the ICD loader. */ + for (i = 0; i < physical_device_count; i++) + { + VkPhysicalDevice client_physical_device = &client_instance->physical_device[i]; + struct vulkan_physical_device *physical_device = physical_devices + i; + if ((res = init_physical_device( physical_device, host_physical_devices[i], client_physical_device, instance ))) goto failed; + } + instance->physical_device_count = physical_device_count; + instance->physical_devices = physical_devices; + +failed: + free( host_physical_devices ); + return res; +} + +static VkResult win32u_vkCreateInstance( const VkInstanceCreateInfo *client_create_info, const VkAllocationCallbacks *allocator, + VkInstance *client_instance_ptr ) +{ + VkInstanceCreateInfo *create_info = (VkInstanceCreateInfo *)client_create_info; /* cast away const, chain has been copied in the thunks */ + VkInstance host_instance, client_instance = *client_instance_ptr; + struct vulkan_physical_device *physical_devices; + struct mempool pool = {0}; + struct instance *instance; + unsigned int i; + VkResult res; + + if (!(instance = calloc( 1, sizeof(*instance) + sizeof(*physical_devices) * client_instance->physical_device_count) )) return VK_ERROR_OUT_OF_HOST_MEMORY; + physical_devices = (struct vulkan_physical_device *)(instance + 1); + instance->obj.extensions = client_instance->extensions; + list_init( &instance->utils_messengers ); + list_init( &instance->report_callbacks ); + + if ((res = convert_instance_create_info( &pool, create_info, instance ))) goto failed; + if ((res = p_vkCreateInstance( create_info, NULL /* allocator */, &host_instance ))) goto failed; + + vulkan_object_init_ptr( &instance->obj.obj, (UINT_PTR)host_instance, &client_instance->obj ); + instance->obj.p_insert_object = vulkan_instance_insert_object; + instance->obj.p_remove_object = vulkan_instance_remove_object; + instance->obj.p_client_handle_from_host = vulkan_instance_client_handle_from_host; + +#define USE_VK_FUNC( name ) \ + instance->obj.p_##name = (void *)p_vkGetInstanceProcAddr( instance->obj.host.instance, #name ); \ + if (!instance->obj.p_##name) TRACE( "Instance proc %s not found.\n", #name ); + ALL_VK_INSTANCE_FUNCS +#undef USE_VK_FUNC + + /* Cache physical devices for vkEnumeratePhysicalDevices within the instance as each vkPhysicalDevice is a dispatchable + * object, which means we need to wrap the host physical devices and present those to the application. + */ + if ((res = init_physical_devices( &instance->obj, physical_devices ))) goto failed; + + TRACE( "Created instance %p, host_instance %p.\n", instance, instance->obj.host.instance ); + for (i = 0; i < instance->obj.physical_device_count; i++) + { + struct vulkan_physical_device *physical_device = &instance->obj.physical_devices[i]; + vulkan_instance_insert_object( &instance->obj, &physical_device->obj ); + } + vulkan_instance_insert_object( &instance->obj, &instance->obj.obj ); + +failed: + if (res) + { + ERR( "Failed to create vulkan instance, res %d\n", res ); + if (host_instance) instance->obj.p_vkDestroyInstance( host_instance, NULL /* allocator */ ); + free_debug_utils_messengers( &instance->utils_messengers ); + free_debug_report_callbacks( &instance->report_callbacks ); + free( instance ); + } + mem_free( &pool ); + return res; +} + +static void win32u_vkDestroyInstance( VkInstance client_instance, const VkAllocationCallbacks *allocator ) +{ + struct instance *instance = instance_from_handle( client_instance ); + + if (!instance) return; + + instance->obj.p_vkDestroyInstance( instance->obj.host.instance, NULL /* allocator */ ); + for (int i = 0; i < instance->obj.physical_device_count; i++) + vulkan_instance_remove_object( &instance->obj, &instance->obj.physical_devices[i].obj ); + vulkan_instance_remove_object( &instance->obj, &instance->obj.obj ); + + if (instance->objects.compare) pthread_rwlock_destroy( &instance->objects_lock ); + free_debug_utils_messengers( &instance->utils_messengers ); + free_debug_report_callbacks( &instance->report_callbacks ); + free( instance ); +} + static VkResult convert_device_create_info( struct vulkan_physical_device *physical_device, VkDeviceCreateInfo *info, struct mempool *pool, struct vulkan_device *device ) { @@ -2453,16 +2810,6 @@ static void win32u_vkGetPhysicalDeviceExternalFencePropertiesKHR( VkPhysicalDevi get_physical_device_external_fence_properties( physical_device, fence_info, fence_properties, instance->p_vkGetPhysicalDeviceExternalFencePropertiesKHR ); }
-static void win32u_map_instance_extensions( struct vulkan_instance_extensions *extensions ) -{ - return driver_funcs->p_map_instance_extensions( extensions ); -} - -static void win32u_map_device_extensions( struct vulkan_device_extensions *extensions ) -{ - return driver_funcs->p_map_device_extensions( extensions ); -} - static struct vulkan_funcs vulkan_funcs = { .p_vkAcquireNextImage2KHR = win32u_vkAcquireNextImage2KHR, @@ -2472,11 +2819,13 @@ static struct vulkan_funcs vulkan_funcs = .p_vkCreateDevice = win32u_vkCreateDevice, .p_vkCreateFence = win32u_vkCreateFence, .p_vkCreateImage = win32u_vkCreateImage, + .p_vkCreateInstance = win32u_vkCreateInstance, .p_vkCreateSemaphore = win32u_vkCreateSemaphore, .p_vkCreateSwapchainKHR = win32u_vkCreateSwapchainKHR, .p_vkCreateWin32SurfaceKHR = win32u_vkCreateWin32SurfaceKHR, .p_vkDestroyDevice = win32u_vkDestroyDevice, .p_vkDestroyFence = win32u_vkDestroyFence, + .p_vkDestroyInstance = win32u_vkDestroyInstance, .p_vkDestroySemaphore = win32u_vkDestroySemaphore, .p_vkDestroySurfaceKHR = win32u_vkDestroySurfaceKHR, .p_vkDestroySwapchainKHR = win32u_vkDestroySwapchainKHR, @@ -2516,8 +2865,6 @@ static struct vulkan_funcs vulkan_funcs = .p_vkQueueSubmit2KHR = win32u_vkQueueSubmit2KHR, .p_vkUnmapMemory = win32u_vkUnmapMemory, .p_vkUnmapMemory2KHR = win32u_vkUnmapMemory2KHR, - .p_map_instance_extensions = win32u_map_instance_extensions, - .p_map_device_extensions = win32u_map_device_extensions, };
static VkResult nulldrv_vulkan_surface_create( HWND hwnd, const struct vulkan_instance *instance, VkSurfaceKHR *surface, @@ -2620,6 +2967,11 @@ static const struct vulkan_driver_funcs lazydrv_funcs =
static void vulkan_init_once(void) { + struct vulkan_instance_extensions extensions = {0}; + VkExtensionProperties *properties = NULL; + uint32_t count = 0; + VkResult res; + if (!(vulkan_handle = dlopen( SONAME_LIBVULKAN, RTLD_NOW ))) { ERR( "Failed to load %s\n", SONAME_LIBVULKAN ); @@ -2642,6 +2994,48 @@ static void vulkan_init_once(void) driver_funcs = &lazydrv_funcs; vulkan_funcs.p_vkGetInstanceProcAddr = p_vkGetInstanceProcAddr; vulkan_funcs.p_vkGetDeviceProcAddr = p_vkGetDeviceProcAddr; + +#define LOAD_FUNCPTR( f ) p_##f = (PFN_##f)p_vkGetInstanceProcAddr( NULL, #f ); + LOAD_FUNCPTR( vkCreateInstance ); + LOAD_FUNCPTR( vkEnumerateInstanceExtensionProperties ); +#undef LOAD_FUNCPTR + + do + { + free( properties ); + properties = NULL; + if ((res = p_vkEnumerateInstanceExtensionProperties( NULL, &count, NULL ))) goto failed; + if (!count || !(properties = malloc( count * sizeof(*properties) ))) goto failed; + } while ((res = p_vkEnumerateInstanceExtensionProperties( NULL, &count, properties ) == VK_INCOMPLETE)); + if (res) goto failed; + + TRACE( "Host instance extensions:\n" ); + for (uint32_t i = 0; i < count; i++) + { + const char *extension = properties[i].extensionName; +#define USE_VK_EXT(x) \ + if (!strcmp( extension, #x )) \ + { \ + extensions.has_ ## x = 1; \ + TRACE( " - %s\n", extension ); \ + } else + ALL_VK_INSTANCE_EXTS +#undef USE_VK_EXT + WARN( "Extension %s is not supported.\n", debugstr_a(extension) ); + } + vulkan_funcs.host_extensions = extensions; + + /* map host instance extensions for VK_KHR_win32_surface */ + driver_funcs->p_map_instance_extensions( &extensions ); + + /* filter out unsupported client instance extensions */ +#define USE_VK_EXT(x) vulkan_funcs.client_extensions.has_ ## x = extensions.has_ ## x; + ALL_VK_CLIENT_INSTANCE_EXTS +#undef USE_VK_EXT + +failed: + if (res) ERR( "Failed to initialize instance extensions, res %d\n", res ); + free( properties ); }
#else /* SONAME_LIBVULKAN */ diff --git a/dlls/winevulkan/loader.c b/dlls/winevulkan/loader.c index 3e377acd153..d9250c2f831 100644 --- a/dlls/winevulkan/loader.c +++ b/dlls/winevulkan/loader.c @@ -380,7 +380,7 @@ VkResult WINAPI vkCreateInstance(const VkInstanceCreateInfo *create_info, struct vkCreateInstance_params params; const VkApplicationInfo *app_info; struct VkInstance_T *instance; - uint32_t phys_dev_count = 8, i; + uint32_t device_count = 8, i; NTSTATUS status;
TRACE("create_info %p, allocator %p, instance %p\n", create_info, allocator, ret); @@ -409,27 +409,31 @@ VkResult WINAPI vkCreateInstance(const VkInstanceCreateInfo *create_info,
for (;;) { - if (!(instance = vulkan_client_object_create(FIELD_OFFSET(struct VkInstance_T, phys_devs[phys_dev_count])))) + if (!(instance = vulkan_client_object_create(FIELD_OFFSET(struct VkInstance_T, physical_device[device_count])))) return VK_ERROR_OUT_OF_HOST_MEMORY; - instance->phys_dev_count = phys_dev_count; - for (i = 0; i < phys_dev_count; i++) - instance->phys_devs[i].obj.loader_magic = VULKAN_ICD_MAGIC_VALUE; + instance->physical_device_count = device_count; + for (i = 0; i < device_count; i++) + instance->physical_device[i].obj.loader_magic = VULKAN_ICD_MAGIC_VALUE; instance->extensions = extensions; + *ret = instance;
params.pCreateInfo = create_info; params.pAllocator = allocator; params.pInstance = ret; - params.client_ptr = instance; status = UNIX_CALL(vkCreateInstance, ¶ms); assert(!status); - if (instance->phys_dev_count <= phys_dev_count) + if (instance->physical_device_count <= device_count) break; - phys_dev_count = instance->phys_dev_count; + device_count = instance->physical_device_count; free(instance); + *ret = NULL; }
if (params.result) + { free(instance); + *ret = NULL; + } return params.result; }
diff --git a/dlls/winevulkan/loader_thunks.h b/dlls/winevulkan/loader_thunks.h index a249cd70870..e07b48101df 100644 --- a/dlls/winevulkan/loader_thunks.h +++ b/dlls/winevulkan/loader_thunks.h @@ -3294,7 +3294,6 @@ struct vkCreateInstance_params const VkInstanceCreateInfo *pCreateInfo; const VkAllocationCallbacks *pAllocator; VkInstance *pInstance; - void *client_ptr; VkResult result; };
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 906220922d3..ba8e8695fd1 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -176,8 +176,6 @@ PERF_CRITICAL_FUNCTIONS = [ # part of the driver interface. # - dispatch (default: True): set whether we need a function pointer in the device / instance dispatch table. FUNCTION_OVERRIDES = { - # Global functions - "vkCreateInstance" : {"extra_param" : "client_ptr"}, # Device functions "vkCreateCommandPool" : {"extra_param" : "client_ptr"}, "vkGetDeviceProcAddr" : {"dispatch" : False}, @@ -192,11 +190,13 @@ USER_DRIVER_FUNCS = { "vkCreateDevice", "vkCreateFence", "vkCreateImage", + "vkCreateInstance", "vkCreateSemaphore", "vkCreateSwapchainKHR", "vkCreateWin32SurfaceKHR", "vkDestroyDevice", "vkDestroyFence", + "vkDestroyInstance", "vkDestroySemaphore", "vkDestroySurfaceKHR", "vkDestroySwapchainKHR", @@ -252,7 +252,6 @@ MANUAL_UNIX_THUNKS = { "vkDestroyDebugReportCallbackEXT", "vkDestroyDebugUtilsMessengerEXT", "vkDestroyDeferredOperationKHR", - "vkDestroyInstance", "vkEnumerateDeviceLayerProperties", "vkEnumerateInstanceExtensionProperties", "vkEnumerateInstanceLayerProperties", diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index c05ab552961..0f49148ee15 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -35,75 +35,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan); static PFN_vkCreateInstance p_vkCreateInstance; static PFN_vkEnumerateInstanceVersion p_vkEnumerateInstanceVersion; static PFN_vkEnumerateInstanceExtensionProperties p_vkEnumerateInstanceExtensionProperties; -static struct vulkan_instance_extensions instance_extensions; /* supported host instance extensions */ - -static struct wine_instance *wine_instance_from_handle(VkInstance handle) -{ - struct vulkan_instance *object = vulkan_instance_from_handle(handle); - return CONTAINING_RECORD(object, struct wine_instance, obj); -} - -static BOOL is_wow64(void) -{ - return sizeof(void *) == sizeof(UINT64) && NtCurrentTeb()->WowTebOffset; -} - -static BOOL use_external_memory(void) -{ - return is_wow64(); -} - -static ULONG_PTR zero_bits = 0;
const struct vulkan_funcs *vk_funcs;
-static int vulkan_object_compare(const void *key, const struct rb_entry *entry) -{ - struct vulkan_object *object = RB_ENTRY_VALUE(entry, struct vulkan_object, entry); - const uint64_t *host_handle = key; - if (*host_handle < object->host_handle) return -1; - if (*host_handle > object->host_handle) return 1; - return 0; -} - -static void vulkan_instance_insert_object( struct vulkan_instance *instance, struct vulkan_object *obj ) -{ - struct wine_instance *impl = CONTAINING_RECORD(instance, struct wine_instance, obj); - if (impl->objects.compare) - { - pthread_rwlock_wrlock( &impl->objects_lock ); - rb_put( &impl->objects, &obj->host_handle, &obj->entry ); - pthread_rwlock_unlock( &impl->objects_lock ); - } -} - -static void vulkan_instance_remove_object( struct vulkan_instance *instance, struct vulkan_object *obj ) -{ - struct wine_instance *impl = CONTAINING_RECORD(instance, struct wine_instance, obj); - if (impl->objects.compare) - { - pthread_rwlock_wrlock( &impl->objects_lock ); - rb_remove( &impl->objects, &obj->entry ); - pthread_rwlock_unlock( &impl->objects_lock ); - } -} - -static uint64_t client_handle_from_host(struct vulkan_instance *obj, uint64_t host_handle) -{ - struct wine_instance *instance = CONTAINING_RECORD(obj, struct wine_instance, obj); - struct rb_entry *entry; - uint64_t result = 0; - - pthread_rwlock_rdlock(&instance->objects_lock); - if ((entry = rb_get(&instance->objects, &host_handle))) - { - struct vulkan_object *object = RB_ENTRY_VALUE(entry, struct vulkan_object, entry); - result = object->client_handle; - } - pthread_rwlock_unlock(&instance->objects_lock); - return result; -} - static UINT64 call_vulkan_debug_report_callback; static UINT64 call_vulkan_debug_utils_callback;
@@ -213,7 +147,7 @@ static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagB
if (wine_vk_is_type_wrapped(objects[i].object_type)) { - objects[i].object_handle = client_handle_from_host(object->instance, objects[i].object_handle); + objects[i].object_handle = object->instance->p_client_handle_from_host(object->instance, objects[i].object_handle); if (!objects[i].object_handle) { WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data->pObjects[i].objectHandle)); @@ -277,7 +211,7 @@ static VkBool32 debug_report_callback_conversion(VkDebugReportFlagsEXT flags, Vk params->object_type = object_type; params->location = location; params->code = code; - params->object_handle = client_handle_from_host(object->instance, object_handle); + params->object_handle = object->instance->p_client_handle_from_host(object->instance, object_handle); if (!params->object_handle) params->object_type = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
strings_len = 0; @@ -291,107 +225,6 @@ static VkBool32 debug_report_callback_conversion(VkDebugReportFlagsEXT flags, Vk return VK_FALSE; }
-static VkResult vulkan_physical_device_init(struct vulkan_physical_device *physical_device, - VkPhysicalDevice host_physical_device, VkPhysicalDevice client_physical_device, - struct vulkan_instance *instance) -{ - struct vulkan_device_extensions extensions = {0}; - VkExtensionProperties *properties; - uint32_t count; - VkResult res; - - vulkan_object_init_ptr(&physical_device->obj, (UINT_PTR)host_physical_device, &client_physical_device->obj); - physical_device->instance = instance; - - instance->p_vkGetPhysicalDeviceMemoryProperties(host_physical_device, &physical_device->memory_properties); - - if ((res = instance->p_vkEnumerateDeviceExtensionProperties(host_physical_device, NULL, &count, NULL))) return res; - if (!(properties = calloc(count, sizeof(*properties)))) return res; - if ((res = instance->p_vkEnumerateDeviceExtensionProperties(host_physical_device, NULL, &count, properties))) goto done; - - TRACE("Host physical device extensions:\n"); - for (uint32_t i = 0; i < count; i++) - { - const char *extension = properties[i].extensionName; -#define USE_VK_EXT(x) \ - if (!strcmp(extension, #x)) \ - { \ - extensions.has_ ## x = 1; \ - TRACE(" - %s\n", extension); \ - } else - ALL_VK_DEVICE_EXTS -#undef USE_VK_EXT - WARN("Extension %s is not supported.\n", debugstr_a(extension)); - } - physical_device->extensions = extensions; - - if (zero_bits && physical_device->extensions.has_VK_EXT_map_memory_placed && physical_device->extensions.has_VK_KHR_map_memory2) - { - VkPhysicalDeviceMapMemoryPlacedFeaturesEXT map_placed_feature = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT, - }; - VkPhysicalDeviceFeatures2 features = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, - .pNext = &map_placed_feature, - }; - - instance->p_vkGetPhysicalDeviceFeatures2KHR(host_physical_device, &features); - if (map_placed_feature.memoryMapPlaced && map_placed_feature.memoryUnmapReserve) - { - VkPhysicalDeviceMapMemoryPlacedPropertiesEXT map_placed_props = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT, - }; - VkPhysicalDeviceProperties2 props = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, - .pNext = &map_placed_props, - }; - - instance->p_vkGetPhysicalDeviceProperties2(host_physical_device, &props); - physical_device->map_placed_align = map_placed_props.minPlacedMemoryMapAlignment; - TRACE( "Using placed map with alignment %u\n", physical_device->map_placed_align ); - } - } - - if (zero_bits && physical_device->extensions.has_VK_EXT_external_memory_host && !physical_device->map_placed_align) - { - VkPhysicalDeviceExternalMemoryHostPropertiesEXT host_mem_props = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT, - }; - VkPhysicalDeviceProperties2 props = - { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, - .pNext = &host_mem_props, - }; - instance->p_vkGetPhysicalDeviceProperties2KHR(host_physical_device, &props); - physical_device->external_memory_align = host_mem_props.minImportedHostPointerAlignment; - if (physical_device->external_memory_align) - TRACE("Using VK_EXT_external_memory_host for memory mapping with alignment: %u\n", - physical_device->external_memory_align); - } - - vk_funcs->p_map_device_extensions(&extensions); - if (extensions.has_VK_KHR_external_memory_win32 && zero_bits && !physical_device->map_placed_align) - { - WARN("Cannot export WOW64 memory without VK_EXT_map_memory_placed\n"); - extensions.has_VK_KHR_external_memory_win32 = 0; - } - extensions.has_VK_KHR_win32_keyed_mutex = extensions.has_VK_KHR_timeline_semaphore; - - /* filter out unsupported client device extensions */ -#define USE_VK_EXT(x) client_physical_device->extensions.has_ ## x = extensions.has_ ## x; - ALL_VK_CLIENT_DEVICE_EXTS -#undef USE_VK_EXT - -done: - free(properties); - return res; -} - static void wine_vk_free_command_buffers(struct vulkan_device *device, struct wine_cmd_pool *pool, uint32_t count, const VkCommandBuffer *buffers) { @@ -409,7 +242,7 @@ static void wine_vk_free_command_buffers(struct vulkan_device *device,
device->p_vkFreeCommandBuffers(device->host.device, pool->host.command_pool, 1, &buffer->host.command_buffer); - vulkan_instance_remove_object(instance, &buffer->obj); + instance->p_remove_object(instance, &buffer->obj); buffer->client.command_buffer->obj.unix_handle = 0; free(buffer); } @@ -417,11 +250,7 @@ static void wine_vk_free_command_buffers(struct vulkan_device *device,
NTSTATUS init_vulkan(void *arg) { - struct vulkan_instance_extensions extensions = {0}; - VkExtensionProperties *properties = NULL; const struct init_params *params = arg; - uint32_t count = 0; - VkResult res;
vk_funcs = __wine_get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION); if (!vk_funcs) @@ -437,51 +266,8 @@ NTSTATUS init_vulkan(void *arg) p_vkEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion)vk_funcs->p_vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion"); p_vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)vk_funcs->p_vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties");
- if (is_wow64()) - { - SYSTEM_BASIC_INFORMATION info; - - NtQuerySystemInformation(SystemEmulationBasicInformation, &info, sizeof(info), NULL); - zero_bits = (ULONG_PTR)info.HighestUserAddress | 0x7fffffff; - } - - do - { - free(properties); - properties = NULL; - if ((res = p_vkEnumerateInstanceExtensionProperties(NULL, &count, NULL))) goto failed; - if (!count || !(properties = malloc(count * sizeof(*properties)))) return STATUS_UNSUCCESSFUL; - } while ((res = p_vkEnumerateInstanceExtensionProperties(NULL, &count, properties) == VK_INCOMPLETE)); - if (res) goto failed; - - TRACE("Host instance extensions:\n"); - for (uint32_t i = 0; i < count; i++) - { - const char *extension = properties[i].extensionName; -#define USE_VK_EXT(x) \ - if (!strcmp(extension, #x)) \ - { \ - extensions.has_ ## x = 1; \ - TRACE(" - %s\n", extension); \ - } else - ALL_VK_INSTANCE_EXTS -#undef USE_VK_EXT - WARN("Extension %s is not supported.\n", debugstr_a(extension)); - } - instance_extensions = extensions; - - /* map host instance extensions for VK_KHR_win32_surface */ - vk_funcs->p_map_instance_extensions(&extensions); - - /* filter out unsupported client instance extensions */ -#define USE_VK_EXT(x) params->extensions->has_ ## x = extensions.has_ ## x; - ALL_VK_CLIENT_INSTANCE_EXTS -#undef USE_VK_EXT - -failed: - free(properties); - if (res) ERR("Failed to initialize Vulkan, res %d\n", res); - return res ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS; + *params->extensions = vk_funcs->client_extensions; + return STATUS_SUCCESS; }
static void free_debug_utils_messengers(struct list *messengers) @@ -506,134 +292,6 @@ static void free_debug_report_callbacks(struct list *callbacks) } }
-/* Helper function for converting between win32 and host compatible VkInstanceCreateInfo. - * This function takes care of extensions handled at winevulkan layer, a Wine graphics - * driver is responsible for handling e.g. surface extensions. - */ -static VkResult wine_vk_instance_convert_create_info(struct conversion_context *ctx, - const VkInstanceCreateInfo *src, VkInstanceCreateInfo *dst, struct wine_instance *instance) -{ - VkDebugReportCallbackCreateInfoEXT *debug_report_callback; - VkBaseInStructure *header = (VkBaseInStructure *)dst; - const char **extensions; - uint32_t count = 0; - - *dst = *src; - - while ((header = find_next_struct(header->pNext, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT))) - { - VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger = (VkDebugUtilsMessengerCreateInfoEXT *)header; - struct vulkan_debug_utils_messenger *messenger = debug_utils_messenger->pUserData; - - list_remove(&messenger->entry); - list_add_tail(&instance->utils_messengers, &messenger->entry); - messenger->instance = &instance->obj; - } - - if ((debug_report_callback = find_next_struct(dst->pNext, VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT))) - { - struct vulkan_debug_report_callback *callback = debug_report_callback->pUserData; - - list_remove(&callback->entry); - list_add_tail(&instance->report_callbacks, &callback->entry); - callback->instance = &instance->obj; - } - - /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader - * filter this data out as well. - */ - if (dst->enabledLayerCount) - { - FIXME("Loading explicit layers is not supported by winevulkan!\n"); - return VK_ERROR_LAYER_NOT_PRESENT; - } - - vk_funcs->p_map_instance_extensions(&instance->obj.extensions); - instance->obj.extensions.has_VK_KHR_win32_surface = 0; - - if (instance->obj.extensions.has_VK_EXT_debug_utils || instance->obj.extensions.has_VK_EXT_debug_report) - { - rb_init(&instance->objects, vulkan_object_compare); - pthread_rwlock_init(&instance->objects_lock, NULL); - } - - if (instance->obj.extensions.has_VK_KHR_win32_surface && instance_extensions.has_VK_EXT_surface_maintenance1) - instance->obj.extensions.has_VK_EXT_surface_maintenance1 = 1; - if (use_external_memory()) - { - instance->obj.extensions.has_VK_KHR_get_physical_device_properties2 = 1; - instance->obj.extensions.has_VK_KHR_external_memory_capabilities = 1; - } - - extensions = conversion_context_alloc(ctx, sizeof(instance->obj.extensions) * 8 * sizeof(*extensions)); -#define USE_VK_EXT(x) if (instance->obj.extensions.has_ ## x) extensions[count++] = #x; - ALL_VK_INSTANCE_EXTS -#undef USE_VK_EXT - - TRACE("Enabling %u host instance extensions\n", count); - for (const char **extension = extensions, **end = extension + count; extension < end; extension++) - TRACE(" - %s\n", debugstr_a(*extension)); - - dst->ppEnabledExtensionNames = extensions; - dst->enabledExtensionCount = count; - return VK_SUCCESS; -} - -/* Helper function which stores wrapped physical devices in the instance object. */ -static VkResult wine_vk_instance_init_physical_devices(struct vulkan_instance *instance, - struct vulkan_physical_device *physical_devices) -{ - VkInstance client_instance = instance->client.instance; - VkPhysicalDevice *host_physical_devices; - uint32_t phys_dev_count; - unsigned int i; - VkResult res; - - res = instance->p_vkEnumeratePhysicalDevices(instance->host.instance, &phys_dev_count, NULL); - if (res != VK_SUCCESS) - { - ERR("Failed to enumerate physical devices, res=%d\n", res); - return res; - } - if (!phys_dev_count) - return res; - - if (phys_dev_count > client_instance->phys_dev_count) - { - client_instance->phys_dev_count = phys_dev_count; - return VK_ERROR_OUT_OF_POOL_MEMORY; - } - client_instance->phys_dev_count = phys_dev_count; - - if (!(host_physical_devices = calloc(phys_dev_count, sizeof(*host_physical_devices)))) - return VK_ERROR_OUT_OF_HOST_MEMORY; - - res = instance->p_vkEnumeratePhysicalDevices(instance->host.instance, &phys_dev_count, host_physical_devices); - if (res != VK_SUCCESS) - { - free(host_physical_devices); - return res; - } - - /* Wrap each host physical device handle into a dispatchable object for the ICD loader. */ - for (i = 0; i < phys_dev_count; i++) - { - struct vulkan_physical_device *physical_device = physical_devices + i; - res = vulkan_physical_device_init(physical_device, host_physical_devices[i], &client_instance->phys_devs[i], instance); - if (res != VK_SUCCESS) - goto err; - } - instance->physical_device_count = phys_dev_count; - instance->physical_devices = physical_devices; - - free(host_physical_devices); - return VK_SUCCESS; - -err: - free(host_physical_devices); - return res; -} - static struct vulkan_physical_device *vulkan_instance_get_physical_device(struct vulkan_instance *instance, VkPhysicalDevice host_physical_device) { @@ -695,7 +353,7 @@ VkResult wine_vkAllocateCommandBuffers(VkDevice client_device, const VkCommandBu
vulkan_object_init_ptr(&buffer->obj, (UINT_PTR)host_command_buffer, &client_command_buffer->obj); buffer->device = device; - vulkan_instance_insert_object(instance, &buffer->obj); + instance->p_insert_object(instance, &buffer->obj); }
if (res != VK_SUCCESS) @@ -704,21 +362,13 @@ VkResult wine_vkAllocateCommandBuffers(VkDevice client_device, const VkCommandBu return res; }
-VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *client_create_info, - const VkAllocationCallbacks *allocator, VkInstance *ret, - void *client_ptr) +VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *client_create_info, const VkAllocationCallbacks *allocator, + VkInstance *client_instance_ptr) { VkInstanceCreateInfo *create_info = (VkInstanceCreateInfo *)client_create_info; /* cast away const, chain has been copied in the thunks */ struct list utils_messengers = LIST_INIT(utils_messengers), report_callbacks = LIST_INIT(report_callbacks); VkBaseInStructure *header = (VkBaseInStructure *)create_info; VkDebugReportCallbackCreateInfoEXT *debug_report_callback; - VkInstanceCreateInfo create_info_host; - struct conversion_context ctx; - struct wine_instance *instance; - VkInstance host_instance, client_instance = client_ptr; - struct vulkan_physical_device *physical_devices; - unsigned int i; - VkResult res;
while ((header = find_next_struct(header->pNext, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT))) { @@ -749,70 +399,7 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *client_create_info, list_add_tail(&report_callbacks, &report_callback->entry); }
- if (!(instance = calloc(1, sizeof(*instance) + sizeof(*physical_devices) * client_instance->phys_dev_count))) - { - ERR("Failed to allocate memory for instance\n"); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - physical_devices = (struct vulkan_physical_device *)(instance + 1); - instance->obj.extensions = client_instance->extensions; - list_init(&instance->utils_messengers); - list_init(&instance->report_callbacks); - - init_conversion_context(&ctx); - res = wine_vk_instance_convert_create_info(&ctx, create_info, &create_info_host, instance); - if (res == VK_SUCCESS) - res = p_vkCreateInstance(&create_info_host, NULL /* allocator */, &host_instance); - free_conversion_context(&ctx); - if (res != VK_SUCCESS) - { - ERR("Failed to create instance, res=%d\n", res); - free_debug_utils_messengers(&instance->utils_messengers); - free_debug_report_callbacks(&instance->report_callbacks); - free(instance); - return res; - } - - vulkan_object_init_ptr(&instance->obj.obj, (UINT_PTR)host_instance, &client_instance->obj); - instance->obj.p_insert_object = vulkan_instance_insert_object; - instance->obj.p_remove_object = vulkan_instance_remove_object; - - /* Load all instance functions we are aware of. Note the loader takes care - * of any filtering for extensions which were not requested, but which the - * ICD may support. - */ -#define USE_VK_FUNC(name) \ - instance->obj.p_##name = (void *)vk_funcs->p_vkGetInstanceProcAddr(instance->obj.host.instance, #name); - ALL_VK_INSTANCE_FUNCS -#undef USE_VK_FUNC - - /* Cache physical devices for vkEnumeratePhysicalDevices within the instance as - * each vkPhysicalDevice is a dispatchable object, which means we need to wrap - * the host physical devices and present those to the application. - * Cleanup happens as part of wine_vkDestroyInstance. - */ - res = wine_vk_instance_init_physical_devices(&instance->obj, physical_devices); - if (res != VK_SUCCESS) - { - ERR("Failed to load physical devices, res=%d\n", res); - instance->obj.p_vkDestroyInstance(instance->obj.host.instance, NULL /* allocator */); - free_debug_utils_messengers(&instance->utils_messengers); - free_debug_report_callbacks(&instance->report_callbacks); - free(instance); - return res; - } - - TRACE("Created instance %p, host_instance %p.\n", instance, instance->obj.host.instance); - - for (i = 0; i < instance->obj.physical_device_count; i++) - { - struct vulkan_physical_device *physical_device = &instance->obj.physical_devices[i]; - vulkan_instance_insert_object(&instance->obj, &physical_device->obj); - } - vulkan_instance_insert_object(&instance->obj, &instance->obj.obj); - - *ret = client_instance; - return VK_SUCCESS; + return vk_funcs->p_vkCreateInstance(create_info, NULL /* allocator */, client_instance_ptr);
failed: free_debug_utils_messengers(&utils_messengers); @@ -820,27 +407,6 @@ failed: return VK_ERROR_OUT_OF_HOST_MEMORY; }
-void wine_vkDestroyInstance(VkInstance client_instance, const VkAllocationCallbacks *allocator) -{ - struct wine_instance *instance = wine_instance_from_handle(client_instance); - unsigned int i; - - if (allocator) - FIXME("Support allocation allocators\n"); - if (!instance) - return; - - instance->obj.p_vkDestroyInstance(instance->obj.host.instance, NULL /* allocator */); - for (i = 0; i < instance->obj.physical_device_count; i++) - vulkan_instance_remove_object(&instance->obj, &instance->obj.physical_devices[i].obj); - vulkan_instance_remove_object(&instance->obj, &instance->obj.obj); - - if (instance->objects.compare) pthread_rwlock_destroy(&instance->objects_lock); - free_debug_utils_messengers(&instance->utils_messengers); - free_debug_report_callbacks(&instance->report_callbacks); - free(instance); -} - VkResult wine_vkEnumerateInstanceExtensionProperties(const char *name, uint32_t *count, VkExtensionProperties *properties) { @@ -929,7 +495,7 @@ VkResult wine_vkCreateCommandPool(VkDevice client_device, const VkCommandPoolCre }
vulkan_object_init_ptr(&object->obj, host_command_pool, &client_command_pool->obj); - vulkan_instance_insert_object(instance, &object->obj); + instance->p_insert_object(instance, &object->obj);
*command_pool = object->client.command_pool; return VK_SUCCESS; @@ -946,7 +512,7 @@ void wine_vkDestroyCommandPool(VkDevice client_device, VkCommandPool handle, FIXME("Support for allocation callbacks not implemented yet\n");
device->p_vkDestroyCommandPool(device->host.device, pool->host.command_pool, NULL); - vulkan_instance_remove_object(instance, &pool->obj); + instance->p_remove_object(instance, &pool->obj); free(pool); }
@@ -1267,7 +833,7 @@ VkResult wine_vkCreateDebugUtilsMessengerEXT(VkInstance client_instance, object->instance = instance; object->user_callback = (UINT_PTR)create_info->pfnUserCallback; object->user_data = (UINT_PTR)create_info->pUserData; - vulkan_instance_insert_object(instance, &object->obj); + instance->p_insert_object(instance, &object->obj);
*messenger = object->client.debug_messenger; return VK_SUCCESS; @@ -1285,7 +851,7 @@ void wine_vkDestroyDebugUtilsMessengerEXT(VkInstance client_instance, VkDebugUti return;
instance->p_vkDestroyDebugUtilsMessengerEXT(instance->host.instance, object->host.debug_messenger, NULL); - vulkan_instance_remove_object(instance, &object->obj); + instance->p_remove_object(instance, &object->obj);
free(object); } @@ -1323,7 +889,7 @@ VkResult wine_vkCreateDebugReportCallbackEXT(VkInstance client_instance, object->instance = instance; object->user_callback = (UINT_PTR)create_info->pfnCallback; object->user_data = (UINT_PTR)create_info->pUserData; - vulkan_instance_insert_object(instance, &object->obj); + instance->p_insert_object(instance, &object->obj);
*callback = object->client.debug_callback; return VK_SUCCESS; @@ -1341,7 +907,7 @@ void wine_vkDestroyDebugReportCallbackEXT(VkInstance client_instance, VkDebugRep return;
instance->p_vkDestroyDebugReportCallbackEXT(instance->host.instance, object->host.debug_callback, NULL); - vulkan_instance_remove_object(instance, &object->obj); + instance->p_remove_object(instance, &object->obj);
free(object); } @@ -1371,7 +937,7 @@ VkResult wine_vkCreateDeferredOperationKHR(VkDevice device_handle,
vulkan_object_init(&object->obj, host_deferred_operation); init_conversion_context(&object->ctx); - vulkan_instance_insert_object(instance, &object->obj); + instance->p_insert_object(instance, &object->obj);
*operation = object->client.deferred_operation; return VK_SUCCESS; @@ -1391,7 +957,7 @@ void wine_vkDestroyDeferredOperationKHR(VkDevice device_handle, return;
device->p_vkDestroyDeferredOperationKHR(device->host.device, object->host.deferred_operation, NULL); - vulkan_instance_remove_object(instance, &object->obj); + instance->p_remove_object(instance, &object->obj);
free_conversion_context(&object->ctx); free(object); diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 2419c8554bd..0497c19add2 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -51368,7 +51368,7 @@ static NTSTATUS thunk64_vkCreateInstance(void *args)
init_conversion_context(ctx); convert_VkInstanceCreateInfo_win64_to_host(ctx, params->pCreateInfo, &pCreateInfo_host); - params->result = wine_vkCreateInstance(&pCreateInfo_host, params->pAllocator, params->pInstance, params->client_ptr); + params->result = wine_vkCreateInstance(&pCreateInfo_host, params->pAllocator, params->pInstance); free_conversion_context(ctx); return STATUS_SUCCESS; } @@ -51381,7 +51381,6 @@ static NTSTATUS thunk32_vkCreateInstance(void *args) PTR32 pCreateInfo; PTR32 pAllocator; PTR32 pInstance; - PTR32 client_ptr; VkResult result; } *params = args; VkInstanceCreateInfo pCreateInfo_host; @@ -51394,7 +51393,7 @@ static NTSTATUS thunk32_vkCreateInstance(void *args) init_conversion_context(ctx); convert_VkInstanceCreateInfo_win32_to_host(ctx, (const VkInstanceCreateInfo32 *)UlongToPtr(params->pCreateInfo), &pCreateInfo_host); pInstance_host = UlongToPtr(*(PTR32 *)UlongToPtr(params->pInstance)); - params->result = wine_vkCreateInstance(&pCreateInfo_host, (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator), &pInstance_host, UlongToPtr(params->client_ptr)); + params->result = wine_vkCreateInstance(&pCreateInfo_host, (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator), &pInstance_host); *(PTR32 *)UlongToPtr(params->pInstance) = PtrToUlong(pInstance_host); free_conversion_context(ctx); return STATUS_SUCCESS; @@ -53103,7 +53102,7 @@ static NTSTATUS thunk64_vkDestroyInstance(void *args) if (!params->instance) return STATUS_SUCCESS;
- wine_vkDestroyInstance(params->instance, params->pAllocator); + vk_funcs->p_vkDestroyInstance(params->instance, params->pAllocator); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -53121,7 +53120,7 @@ static NTSTATUS thunk32_vkDestroyInstance(void *args) if (!params->instance) return STATUS_SUCCESS;
- wine_vkDestroyInstance((VkInstance)UlongToPtr(params->instance), (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator)); + vk_funcs->p_vkDestroyInstance((VkInstance)UlongToPtr(params->instance), (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator)); return STATUS_SUCCESS; }
diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index fccc2cc3923..52af356d5c6 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -26,12 +26,11 @@ VkResult wine_vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo VkResult wine_vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback); VkResult wine_vkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger); VkResult wine_vkCreateDeferredOperationKHR(VkDevice device, const VkAllocationCallbacks *pAllocator, VkDeferredOperationKHR *pDeferredOperation); -VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance, void *client_ptr); +VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance); void wine_vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator); void wine_vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks *pAllocator); void wine_vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks *pAllocator); void wine_vkDestroyDeferredOperationKHR(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks *pAllocator); -void wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator); VkResult wine_vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkLayerProperties *pProperties); VkResult wine_vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties); VkResult wine_vkEnumerateInstanceVersion(uint32_t *pApiVersion); diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h index 614a450a9ee..d2e2db3e360 100644 --- a/include/wine/vulkan_driver.h +++ b/include/wine/vulkan_driver.h @@ -67,8 +67,8 @@ struct VkInstance_T { struct vulkan_client_object obj; struct vulkan_instance_extensions extensions; - uint32_t phys_dev_count; - struct VkPhysicalDevice_T phys_devs[1]; + UINT physical_device_count; + struct VkPhysicalDevice_T physical_device[1]; };
struct VkQueue_T @@ -159,6 +159,7 @@ struct vulkan_instance #undef USE_VK_FUNC void (*p_insert_object)( struct vulkan_instance *instance, struct vulkan_object *obj ); void (*p_remove_object)( struct vulkan_instance *instance, struct vulkan_object *obj ); + uint64_t (*p_client_handle_from_host)( struct vulkan_instance *instance, uint64_t host_handle );
struct vulkan_physical_device *physical_devices; uint32_t physical_device_count; @@ -288,6 +289,9 @@ static inline struct vulkan_fence *vulkan_fence_from_handle( VkFence handle )
struct vulkan_funcs { + struct vulkan_instance_extensions host_extensions; + struct vulkan_instance_extensions client_extensions; + /* Vulkan global functions. These are the only calls at this point a graphics driver * needs to provide. Other function calls will be provided indirectly by dispatch * tables part of dispatchable Vulkan objects such as VkInstance or vkDevice. @@ -299,11 +303,13 @@ struct vulkan_funcs PFN_vkCreateDevice p_vkCreateDevice; PFN_vkCreateFence p_vkCreateFence; PFN_vkCreateImage p_vkCreateImage; + PFN_vkCreateInstance p_vkCreateInstance; PFN_vkCreateSemaphore p_vkCreateSemaphore; PFN_vkCreateSwapchainKHR p_vkCreateSwapchainKHR; PFN_vkCreateWin32SurfaceKHR p_vkCreateWin32SurfaceKHR; PFN_vkDestroyDevice p_vkDestroyDevice; PFN_vkDestroyFence p_vkDestroyFence; + PFN_vkDestroyInstance p_vkDestroyInstance; PFN_vkDestroySemaphore p_vkDestroySemaphore; PFN_vkDestroySurfaceKHR p_vkDestroySurfaceKHR; PFN_vkDestroySwapchainKHR p_vkDestroySwapchainKHR; @@ -345,10 +351,6 @@ struct vulkan_funcs PFN_vkQueueSubmit2KHR p_vkQueueSubmit2KHR; PFN_vkUnmapMemory p_vkUnmapMemory; PFN_vkUnmapMemory2KHR p_vkUnmapMemory2KHR; - - /* winevulkan specific functions */ - void (*p_map_instance_extensions)( struct vulkan_instance_extensions *extensions ); - void (*p_map_device_extensions)( struct vulkan_device_extensions *extensions ); };
/* interface between win32u and the user drivers */