From: Arkadiusz Hiler ahiler@codeweavers.com
With VK_EXT_device_address_binding_report we can get debug_util callbacks used to track memory bindings. Since it's the host's implementation that starts the callback we have to be sure that we have a way of converting it to the client side's variant before it's added to the handle map - i.e. we don't know the host handle at that time yet. --- dlls/winevulkan/vulkan.c | 32 +++++++++++++++++++++++++++++++- dlls/winevulkan/vulkan_private.h | 2 ++ 2 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 61b3a42d63f..6bed1f32833 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -164,6 +164,23 @@ static void append_debug_utils_object(const VkDebugUtilsObjectNameInfoEXT *objec dst->object_name_len = append_string(object->pObjectName, strings, strings_len); }
+static void set_transient_client_handle(struct wine_instance *instance, uint64_t client_handle) +{ + uint64_t *handle = pthread_getspecific(instance->transient_object_handle); + if (!handle) + { + handle = malloc(sizeof(uint64_t)); + pthread_setspecific(instance->transient_object_handle, handle); + } + *handle = client_handle; +} + +static uint64_t get_transient_handle(struct wine_instance *instance) +{ + uint64_t *handle = pthread_getspecific(instance->transient_object_handle); + return handle && *handle; +} + static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT message_types, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, @@ -174,6 +191,8 @@ static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagB struct wine_debug_utils_messenger *object; struct debug_utils_object dummy_object, *objects; struct debug_utils_label dummy_label, *labels; + VkInstance instance; + struct wine_instance *wine_instance; UINT size, strings_len; char *ptr, *strings; ULONG ret_len; @@ -183,13 +202,16 @@ static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagB TRACE("%i, %u, %p, %p\n", severity, message_types, callback_data, user_data);
object = user_data; + instance = object->instance->host.instance;
- if (!object->instance->host.instance) + if (!instance) { /* instance wasn't yet created, this is a message from the host loader */ return VK_FALSE; }
+ wine_instance = CONTAINING_RECORD(object->instance, struct wine_instance, obj); + if ((address = callback_data->pNext)) { if (address->sType != VK_STRUCTURE_TYPE_DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT) address = NULL; @@ -246,6 +268,8 @@ 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); + if (!objects[i].object_handle) + objects[i].object_handle = get_transient_handle(wine_instance); if (!objects[i].object_handle) { WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data->pObjects[i].objectHandle)); @@ -1004,6 +1028,8 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, instance->quirks |= WINEVULKAN_QUIRK_GET_DEVICE_PROC_ADDR; }
+ pthread_key_create(&instance->transient_object_handle, free); + TRACE("Created instance %p, host_instance %p.\n", instance, instance->obj.host.instance);
for (i = 0; i < instance->phys_dev_count; i++) @@ -1054,6 +1080,8 @@ void wine_vkDestroyInstance(VkInstance client_instance, const VkAllocationCallba } vulkan_instance_remove_object(&instance->obj, &instance->obj.obj);
+ pthread_key_delete(instance->transient_object_handle); + if (instance->objects.compare) pthread_rwlock_destroy(&instance->objects_lock); free(instance->utils_messengers); free(instance); @@ -1645,6 +1673,7 @@ VkResult wine_vkAllocateMemory(VkDevice client_device, const VkMemoryAllocateInf struct vulkan_device *device = vulkan_device_from_handle(client_device); struct wine_phys_dev *physical_device = CONTAINING_RECORD(device->physical_device, struct wine_phys_dev, obj); struct vulkan_instance *instance = device->physical_device->instance; + struct wine_instance *wine_instance = CONTAINING_RECORD(instance, struct wine_instance, obj); struct wine_device_memory *memory; VkMemoryAllocateInfo info = *alloc_info; VkImportMemoryHostPointerInfoEXT host_pointer_info; @@ -1724,6 +1753,7 @@ VkResult wine_vkAllocateMemory(VkDevice client_device, const VkMemoryAllocateInf if (!(memory = malloc(sizeof(*memory)))) return VK_ERROR_OUT_OF_HOST_MEMORY;
+ set_transient_client_handle(wine_instance, (uintptr_t)memory); result = device->p_vkAllocateMemory(device->host.device, &info, NULL, &host_device_memory); if (result != VK_SUCCESS) { diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 59b900930b3..8e0b48af169 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -100,6 +100,8 @@ struct wine_instance struct rb_tree objects; pthread_rwlock_t objects_lock;
+ pthread_key_t transient_object_handle; + /* We cache devices as we need to wrap them as they are dispatchable objects. */ uint32_t phys_dev_count; struct wine_phys_dev phys_devs[];