From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winevulkan/vulkan.c | 57 ++++++++++++++++++++++++++------ dlls/winevulkan/vulkan_private.h | 27 +++++++-------- 2 files changed, 60 insertions(+), 24 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index df109e5c84a..99a70d97862 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -187,7 +187,7 @@ static VkBool32 debug_report_callback_conversion(VkDebugReportFlagsEXT flags, Vk
object = user_data;
- if (!object->instance->instance) + if (!object->instance) { /* instance wasn't yet created, this is a message from the native loader */ return VK_FALSE; @@ -488,7 +488,7 @@ static VkResult wine_vk_instance_convert_create_info(struct conversion_context * const VkInstanceCreateInfo *src, VkInstanceCreateInfo *dst, struct wine_instance *object) { VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger; - VkDebugReportCallbackCreateInfoEXT *debug_report_callback; + VkDebugReportCallbackCreateInfoEXT *callback_info; VkBaseInStructure *header; unsigned int i;
@@ -512,17 +512,19 @@ static VkResult wine_vk_instance_convert_create_info(struct conversion_context * debug_utils_messenger->pUserData = &object->utils_messengers[i]; }
- debug_report_callback = find_next_struct(header->pNext, - VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT); - if (debug_report_callback) + callback_info = (VkDebugReportCallbackCreateInfoEXT *)dst; + while ((callback_info = find_next_struct(callback_info->pNext, VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT))) { - object->default_callback.instance = object; - object->default_callback.debug_callback = VK_NULL_HANDLE; - object->default_callback.user_callback = debug_report_callback->pfnCallback; - object->default_callback.user_data = debug_report_callback->pUserData; + struct wine_debug_report_callback *callback; + + if (!(callback = calloc(1, sizeof(*callback)))) return VK_ERROR_OUT_OF_HOST_MEMORY; + callback->debug_callback = VK_NULL_HANDLE; + callback->user_callback = callback_info->pfnCallback; + callback->user_data = callback_info->pUserData;
- debug_report_callback->pfnCallback = (void *) &debug_report_callback_conversion; - debug_report_callback->pUserData = &object->default_callback; + /* convert_VkInstanceCreateInfo_* already copied the chain, so we can modify it in-place. */ + callback_info->pfnCallback = debug_report_callback_conversion; + callback_info->pUserData = callback; }
/* ICDs don't support any layers, so nothing to copy. Modern versions of the loader @@ -569,6 +571,28 @@ static VkResult wine_vk_instance_convert_create_info(struct conversion_context * return VK_SUCCESS; }
+static void cleanup_instance_create_info(VkInstanceCreateInfo *info, struct wine_instance *object) +{ + VkDebugReportCallbackCreateInfoEXT *callback_info = (VkDebugReportCallbackCreateInfoEXT *)info; + + while ((callback_info = find_next_struct(callback_info->pNext, VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT))) + { + struct wine_debug_report_callback *callback = (struct wine_debug_report_callback *)callback_info->pUserData; + + if (callback_info->pfnCallback != debug_report_callback_conversion) break; + /* restore previous create info values, if VkCreateInstance needs to be called again */ + callback_info->pfnCallback = callback->user_callback; + callback_info->pUserData = callback->user_data; + + if (!object) free(callback); + else + { + callback->instance = object; + list_add_tail(&object->debug_report_callbacks, &callback->entry); + } + } +} + /* Helper function which stores wrapped physical devices in the instance object. */ static VkResult wine_vk_instance_load_physical_devices(struct wine_instance *instance) { @@ -652,6 +676,9 @@ static struct wine_phys_dev *wine_vk_instance_wrap_physical_device(struct wine_i */ static void wine_vk_instance_free(struct wine_instance *instance) { + struct wine_debug_report_callback *callback; + void *next; + if (!instance) return;
@@ -675,6 +702,12 @@ static void wine_vk_instance_free(struct wine_instance *instance) pthread_rwlock_destroy(&instance->wrapper_lock); free(instance->utils_messengers);
+ LIST_FOR_EACH_ENTRY_SAFE(callback, next, &instance->debug_report_callbacks, struct wine_debug_report_callback, entry) + { + list_remove(&callback->entry); + free(callback); + } + free(instance); }
@@ -846,6 +879,7 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, return VK_ERROR_OUT_OF_HOST_MEMORY; } list_init(&object->wrappers); + list_init(&object->debug_report_callbacks); pthread_rwlock_init(&object->wrapper_lock, NULL);
init_conversion_context(&ctx); @@ -853,6 +887,7 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, if (res == VK_SUCCESS) res = vk_funcs->p_vkCreateInstance(&create_info_host, NULL /* allocator */, &object->instance); free_conversion_context(&ctx); + cleanup_instance_create_info(&create_info_host, res == VK_SUCCESS ? object : NULL); if (res != VK_SUCCESS) { ERR("Failed to create instance, res=%d\n", res); diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index c8e234e4c8d..d2280f0e734 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -74,18 +74,6 @@ static inline struct wine_device *wine_device_from_handle(VkDevice handle)
struct wine_debug_utils_messenger;
-struct wine_debug_report_callback -{ - struct wine_instance *instance; /* parent */ - VkDebugReportCallbackEXT debug_callback; /* native callback object */ - - /* application callback + data */ - PFN_vkDebugReportCallbackEXT user_callback; - void *user_data; - - struct wine_vk_mapping mapping; -}; - struct wine_instance { struct vulkan_instance_funcs funcs; @@ -106,7 +94,7 @@ struct wine_instance struct wine_debug_utils_messenger *utils_messengers; uint32_t utils_messenger_count;
- struct wine_debug_report_callback default_callback; + struct list debug_report_callbacks;
unsigned int quirks;
@@ -207,6 +195,19 @@ static inline VkDebugUtilsMessengerEXT wine_debug_utils_messenger_to_handle( return (VkDebugUtilsMessengerEXT)(uintptr_t)debug_messenger; }
+struct wine_debug_report_callback +{ + struct wine_instance *instance; /* parent */ + VkDebugReportCallbackEXT debug_callback; /* native callback object */ + + /* application callback + data */ + PFN_vkDebugReportCallbackEXT user_callback; + void *user_data; + + struct wine_vk_mapping mapping; + struct list entry; /* entry in wine_instance debug_report_callbacks */ +}; + static inline struct wine_debug_report_callback *wine_debug_report_callback_from_handle( VkDebugReportCallbackEXT handle) {