[PATCH v6 0/1] MR5658: winevulkan: Make device memory wrapper available in callbacks.
With [`VK_EXT_device_address_binding_report`](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_dev...) we can get [debug_util](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_deb...) 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. This is [used by vkd3d-proton](https://github.com/HansKristian-Work/vkd3d-proton/pull/1962). Requires Mesa with https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28649 (24.3 is modern enough to have it). before (note the missing BIND for VkDevice which actually means `VkDeviceMemory`): ``` vkd3d-proton % WINEDLLOVERRIDES="d3d12=n;d3d12core=n" \ VKD3D_TEST_FILTER=create_placed_resource_size \ VKD3D_CONFIG=fault VKD3D_DEBUG=trace \ ~/build/wine/wine ./tests/d3d12.exe 2>&1 | grep vkd3d_address_binding_callback 6669.627:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: BIND || VkBuffer || VA ffff800101600000 || size 0000000001000000. 6669.627:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: BIND || VkImage || VA ffff800101600000 || size 000000000019a000. 6669.627:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: UNBIND || VkImage || VA ffff800101600000 || size 000000000019a000. 6669.627:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: UNBIND || VkBuffer || VA ffff800101600000 || size 0000000001000000. 6669.627:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: UNBIND || VkDevice || VA ffff800101600000 || size 0000000001000000. 6669.627:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: BIND || VkBuffer || VA ffff800101600000 || size 0000000001000000. 6669.627:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: UNBIND || VkBuffer || VA ffff800101600000 || size 0000000001000000. 6669.627:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: UNBIND || VkDevice || VA ffff800101600000 || size 0000000001000000 ``` after: ``` vkd3d-proton % WINEDLLOVERRIDES="d3d12=n;d3d12core=n" \ VKD3D_TEST_FILTER=create_placed_resource_size \ VKD3D_CONFIG=fault VKD3D_DEBUG=trace \ ~/build/wine/wine ./tests/d3d12.exe 2>&1 | grep vkd3d_address_binding_callback 4015.597:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: BIND || VkDevice || VA ffff800101600000 || size 0000000001000000. 4015.597:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: BIND || VkBuffer || VA ffff800101600000 || size 0000000001000000. 4015.597:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: BIND || VkImage || VA ffff800101600000 || size 000000000019a000. 4015.597:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: UNBIND || VkImage || VA ffff800101600000 || size 000000000019a000. 4015.597:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: UNBIND || VkBuffer || VA ffff800101600000 || size 0000000001000000. 4015.597:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: UNBIND || VkDevice || VA ffff800101600000 || size 0000000001000000. 4015.597:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: BIND || VkDevice || VA ffff800101600000 || size 0000000001000000. 4015.597:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: BIND || VkBuffer || VA ffff800101600000 || size 0000000001000000. 4015.597:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: UNBIND || VkBuffer || VA ffff800101600000 || size 0000000001000000. 4015.597:0020:0024:trace:vkd3d-proton:vkd3d_address_binding_callback: UNBIND || VkDevice || VA ffff800101600000 || size 0000000001000000. ``` [The spec guarantees](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#de...) the following:
An application can receive multiple callbacks if multiple VkDebugUtilsMessengerEXT objects are created. A callback will always be executed in the same thread as the originating Vulkan call.
-- v6: winevulkan: Make device memory wrapper available in callbacks. https://gitlab.winehq.org/wine/wine/-/merge_requests/5658
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/win32u/vulkan.c | 15 +++++++++++++++ dlls/winevulkan/vulkan.c | 8 ++++++++ include/wine/vulkan_driver.h | 3 +++ 3 files changed, 26 insertions(+) diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 2b25e44eace..9a089c63e19 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -611,6 +611,8 @@ static VkResult win32u_vkCreateInstance( const VkInstanceCreateInfo *client_crea list_init( &instance->utils_messengers ); list_init( &instance->report_callbacks ); + pthread_key_create(&instance->obj.transient_object_handle, free); + if ((res = convert_instance_create_info( &pool, create_info, instance ))) goto failed; if ((res = p_vkCreateInstance( create_info, NULL /* allocator */, &host_instance ))) goto failed; @@ -665,6 +667,7 @@ static void win32u_vkDestroyInstance( VkInstance client_instance, const VkAlloca if (instance->objects.compare) pthread_rwlock_destroy( &instance->objects_lock ); free_debug_utils_messengers( &instance->utils_messengers ); free_debug_report_callbacks( &instance->report_callbacks ); + pthread_key_delete(instance->obj.transient_object_handle); free( instance ); } @@ -862,6 +865,17 @@ static void win32u_vkGetDeviceQueue2( VkDevice client_device, const VkDeviceQueu *client_queue = device_find_queue( client_device, &info ); } +static void set_transient_client_handle(struct vulkan_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 VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryAllocateInfo *client_alloc_info, const VkAllocationCallbacks *allocator, VkDeviceMemory *ret ) { @@ -982,6 +996,7 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA alloc_info->pNext = &fd_info; } + set_transient_client_handle(instance, (uintptr_t)&memory->obj.obj); if ((res = device->p_vkAllocateMemory( device->host.device, alloc_info, NULL, &host_device_memory ))) goto failed; if (export_info) diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 0f49148ee15..d9d99270a72 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -66,6 +66,12 @@ static void append_debug_utils_object(const VkDebugUtilsObjectNameInfoEXT *objec dst->object_name_len = append_string(object->pObjectName, strings, strings_len); } +static uint64_t get_transient_handle(struct vulkan_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, @@ -148,6 +154,8 @@ static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagB if (wine_vk_is_type_wrapped(objects[i].object_type)) { objects[i].object_handle = object->instance->p_client_handle_from_host(object->instance, objects[i].object_handle); + if (!objects[i].object_handle) + objects[i].object_handle = get_transient_handle(object->instance); if (!objects[i].object_handle) { WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data->pObjects[i].objectHandle)); diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h index d2e2db3e360..308694e5be6 100644 --- a/include/wine/vulkan_driver.h +++ b/include/wine/vulkan_driver.h @@ -85,6 +85,7 @@ struct VkDevice_T #ifdef WINE_UNIX_LIB +#include <pthread.h> #include "wine/rbtree.h" #include "wine/list.h" @@ -163,6 +164,8 @@ struct vulkan_instance struct vulkan_physical_device *physical_devices; uint32_t physical_device_count; + + pthread_key_t transient_object_handle; }; static inline struct vulkan_instance *vulkan_instance_from_handle( VkInstance handle ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5658
I've switched to pthread TLS already with the previous revision. The 32bit failures look unrelated and other MRs are hitting them too: ``` device.c:5680:17.748 Tests skipped: Following tests require two adapters. device.c:6722:23.710 Test failed: Got unexpected hr 0x1. device.c:6726:23.711 Test failed: Got unexpected hr 0x1. device.c:6727:23.711 Test failed: Got unexpected query result 0xffffffffffffffff. ``` ``` win.c:10624:0.182 Test failed: transparent window didn't get WM_NCHITTEST message win.c:10625:0.182 Test failed: button under static window didn't get WM_LBUTTONUP ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5658#note_127204
participants (2)
-
Arek Hiler (@ivyl) -
Arkadiusz Hiler