[PATCH v6 3/3] winevulkan: Implement VK_EXT_debug_utils.

Georg Lehmann dadschoorse at gmail.com
Tue Oct 13 12:28:37 CDT 2020


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49813

Signed-off-by: Georg Lehmann <dadschoorse at gmail.com>
---
 dlls/winevulkan/make_vulkan      |  10 +-
 dlls/winevulkan/vulkan.c         | 207 +++++++++++++++++++++++++++++++
 dlls/winevulkan/vulkan_private.h |  29 +++++
 3 files changed, 245 insertions(+), 1 deletion(-)

diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index 13a4962dd1a..f3f2da7548c 100755
--- a/dlls/winevulkan/make_vulkan
+++ b/dlls/winevulkan/make_vulkan
@@ -92,7 +92,6 @@ UNSUPPORTED_EXTENSIONS = [
     # plumbing down to the native layer, we will get each message twice as we
     # use 2 loaders (win32+native), but we may get output from the driver.
     # In any case callback conversion is required.
-    "VK_EXT_debug_utils",
     "VK_EXT_validation_features",
     "VK_EXT_validation_flags",
     "VK_KHR_display", # Needs WSI work.
@@ -225,6 +224,13 @@ FUNCTION_OVERRIDES = {
     # VK_EXT_calibrated_timestamps
     "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT" : {"dispatch" : True, "driver" : False, "thunk" : False},
     "vkGetCalibratedTimestampsEXT" : {"dispatch" : True, "driver" : False, "thunk" : False},
+
+    # VK_EXT_debug_utils
+    "vkCreateDebugUtilsMessengerEXT" : {"dispatch": True, "driver" : False, "thunk" : False},
+    "vkDestroyDebugUtilsMessengerEXT" : {"dispatch": True, "driver" : False, "thunk" : False},
+    "vkSubmitDebugUtilsMessageEXT" : {"dispatch": True, "driver" : False, "thunk" : True, "private_thunk" : True},
+    "vkSetDebugUtilsObjectTagEXT" : {"dispatch": True, "driver" : False, "thunk" : True, "private_thunk" : True},
+    "vkSetDebugUtilsObjectNameEXT" : {"dispatch": True, "driver" : False, "thunk" : True, "private_thunk" : True},
 }
 
 STRUCT_CHAIN_CONVERSIONS = [
@@ -944,6 +950,8 @@ class VkHandle(object):
 
         if self.name == "VkCommandPool":
             return "wine_cmd_pool_from_handle({0})->command_pool".format(name)
+        if self.name == "VkDebugUtilsMessengerEXT":
+            return "wine_debug_utils_messenger_from_handle({0})->debug_messenger".format(name)
 
         native_handle_name = None
 
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c
index c140ff3a0e8..92c26be1fc0 100644
--- a/dlls/winevulkan/vulkan.c
+++ b/dlls/winevulkan/vulkan.c
@@ -57,6 +57,21 @@ static void *wine_vk_find_struct_(void *s, VkStructureType t)
     return NULL;
 }
 
+#define wine_vk_count_struct(s, t) wine_vk_count_struct_((void *)s, VK_STRUCTURE_TYPE_##t)
+static uint32_t wine_vk_count_struct_(void *s, VkStructureType t)
+{
+    const VkBaseInStructure *header;
+    uint32_t result = 0;
+
+    for (header = s; header; header = header->pNext)
+    {
+        if (header->sType == t)
+            result++;
+    }
+
+    return result;
+}
+
 static void *wine_vk_get_global_proc_addr(const char *name);
 
 static HINSTANCE hinstance;
@@ -113,6 +128,68 @@ static uint64_t wine_vk_get_wrapper(struct VkInstance_T *instance, uint64_t nati
     return result;
 }
 
+static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
+    VkDebugUtilsMessageTypeFlagsEXT message_types,
+#if defined(USE_STRUCT_CONVERSION)
+    const VkDebugUtilsMessengerCallbackDataEXT_host *callback_data,
+#else
+    const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
+#endif
+    void *user_data)
+{
+    struct VkDebugUtilsMessengerCallbackDataEXT wine_callback_data;
+    VkDebugUtilsObjectNameInfoEXT *object_name_infos;
+    struct wine_debug_utils_messenger *object;
+    VkBool32 result;
+    unsigned int i;
+
+    TRACE("%i, %u, %p, %p\n", severity, message_types, callback_data, user_data);
+
+    object = user_data;
+
+    if (!object->instance->instance)
+    {
+        /* instance wasn't yet created, this is a message from the native loader */
+        return VK_FALSE;
+    }
+
+    wine_callback_data = *((VkDebugUtilsMessengerCallbackDataEXT *) callback_data);
+
+    object_name_infos = heap_calloc(wine_callback_data.objectCount, sizeof(*object_name_infos));
+
+    for (i = 0; i < wine_callback_data.objectCount; i++)
+    {
+        object_name_infos[i].sType = callback_data->pObjects[i].sType;
+        object_name_infos[i].pNext = callback_data->pObjects[i].pNext;
+        object_name_infos[i].objectType = callback_data->pObjects[i].objectType;
+        object_name_infos[i].pObjectName = callback_data->pObjects[i].pObjectName;
+
+        if (wine_vk_is_type_wrapped(callback_data->pObjects[i].objectType))
+        {
+            object_name_infos[i].objectHandle = wine_vk_get_wrapper(object->instance, callback_data->pObjects[i].objectHandle);
+            if (!object_name_infos[i].objectHandle)
+            {
+                WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data->pObjects[i].objectHandle));
+                heap_free(object_name_infos);
+                return VK_FALSE;
+            }
+        }
+        else
+        {
+            object_name_infos[i].objectHandle = callback_data->pObjects[i].objectHandle;
+        }
+    }
+
+    wine_callback_data.pObjects = object_name_infos;
+
+    /* applications should always return VK_FALSE */
+    result = object->user_callback(severity, message_types, &wine_callback_data, object->user_data);
+
+    heap_free(object_name_infos);
+
+    return result;
+}
+
 static void wine_vk_physical_device_free(struct VkPhysicalDevice_T *phys_dev)
 {
     if (!phys_dev)
@@ -393,6 +470,8 @@ static void wine_vk_init_once(void)
 static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo *src,
         VkInstanceCreateInfo *dst, struct VkInstance_T *object)
 {
+    VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger;
+    VkBaseInStructure *header;
     unsigned int i;
     VkResult res;
 
@@ -404,6 +483,26 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
         return res;
     }
 
+    object->utils_messenger_count = wine_vk_count_struct(dst, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT);
+    object->utils_messengers =  heap_calloc(object->utils_messenger_count, sizeof(*object->utils_messengers));
+    header = (VkBaseInStructure *) dst;
+    for (i = 0; i < object->utils_messenger_count; i++)
+    {
+        header = wine_vk_find_struct(header->pNext, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT);
+        debug_utils_messenger = (VkDebugUtilsMessengerCreateInfoEXT *) header;
+
+        object->utils_messengers[i].instance = object;
+        object->utils_messengers[i].debug_messenger = VK_NULL_HANDLE;
+        object->utils_messengers[i].user_callback = debug_utils_messenger->pfnUserCallback;
+        object->utils_messengers[i].user_data = debug_utils_messenger->pUserData;
+
+        /* convert_VkInstanceCreateInfo_struct_chain already copied the chain,
+         * so we can modify it in-place.
+         */
+        debug_utils_messenger->pfnUserCallback = (void *) &debug_utils_callback_conversion;
+        debug_utils_messenger->pUserData = &object->utils_messengers[i];
+    }
+
     /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader
      * filter this data out as well.
      */
@@ -427,6 +526,10 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
             free_VkInstanceCreateInfo_struct_chain(dst);
             return VK_ERROR_EXTENSION_NOT_PRESENT;
         }
+        if (!strcmp(extension_name, "VK_EXT_debug_utils"))
+        {
+            object->enable_wrapper_list = VK_TRUE;
+        }
     }
 
     return VK_SUCCESS;
@@ -527,6 +630,8 @@ static void wine_vk_instance_free(struct VkInstance_T *instance)
         WINE_VK_REMOVE_HANDLE_MAPPING(instance, instance);
     }
 
+    heap_free(instance->utils_messengers);
+
     heap_free(instance);
 }
 
@@ -1673,6 +1778,108 @@ VkResult WINAPI wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice
     return res;
 }
 
+VkResult WINAPI wine_vkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *create_info,
+        const VkAllocationCallbacks *allocator, VkDebugUtilsMessengerEXT *messenger)
+{
+    VkDebugUtilsMessengerCreateInfoEXT wine_create_info;
+    struct wine_debug_utils_messenger *object;
+    VkResult res;
+
+    TRACE("%p, %p, %p, %p\n", instance, create_info, allocator, messenger);
+
+    if (allocator)
+        FIXME("Support for allocation callbacks not implemented yet\n");
+
+    if (!(object = heap_alloc_zero(sizeof(*object))))
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    object->instance = instance;
+    object->user_callback = create_info->pfnUserCallback;
+    object->user_data = create_info->pUserData;
+
+    wine_create_info = *create_info;
+
+    wine_create_info.pfnUserCallback = (void *) &debug_utils_callback_conversion;
+    wine_create_info.pUserData = object;
+
+    res = instance->funcs.p_vkCreateDebugUtilsMessengerEXT(instance->instance, &wine_create_info, NULL,  &object->debug_messenger);
+
+    if (res != VK_SUCCESS)
+    {
+        heap_free(object);
+        return res;
+    }
+
+    WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, object->debug_messenger);
+    *messenger = wine_debug_utils_messenger_to_handle(object);
+
+    return VK_SUCCESS;
+}
+
+void WINAPI wine_vkDestroyDebugUtilsMessengerEXT(
+        VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks *allocator)
+{
+    struct wine_debug_utils_messenger *object;
+
+    TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(messenger), allocator);
+
+    object = wine_debug_utils_messenger_from_handle(messenger);
+
+    instance->funcs.p_vkDestroyDebugUtilsMessengerEXT(instance->instance, object->debug_messenger, NULL);
+    WINE_VK_REMOVE_HANDLE_MAPPING(instance, object);
+
+    heap_free(object);
+}
+
+void WINAPI wine_vkSubmitDebugUtilsMessageEXT(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT severity,
+        VkDebugUtilsMessageTypeFlagsEXT types, const VkDebugUtilsMessengerCallbackDataEXT *callback_data)
+{
+    VkDebugUtilsMessengerCallbackDataEXT native_callback_data;
+    VkDebugUtilsObjectNameInfoEXT *object_names;
+    unsigned int i;
+
+    TRACE("%p, %#x, %#x, %p\n", instance, severity, types, callback_data);
+
+    native_callback_data = *callback_data;
+    object_names = heap_calloc(callback_data->objectCount, sizeof(*object_names));
+    memcpy(object_names, callback_data->pObjects, callback_data->objectCount * sizeof(*object_names));
+    native_callback_data.pObjects = object_names;
+
+    for (i = 0; i < callback_data->objectCount; i++)
+    {
+        object_names[i].objectHandle =
+                wine_vk_unwrap_handle(callback_data->pObjects[i].objectType, callback_data->pObjects[i].objectHandle);
+    }
+
+    thunk_vkSubmitDebugUtilsMessageEXT(instance, severity, types, &native_callback_data);
+
+    heap_free(object_names);
+}
+
+VkResult WINAPI wine_vkSetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsObjectTagInfoEXT *tag_info)
+{
+    VkDebugUtilsObjectTagInfoEXT wine_tag_info;
+
+    TRACE("%p, %p\n", device, tag_info);
+
+    wine_tag_info = *tag_info;
+    wine_tag_info.objectHandle = wine_vk_unwrap_handle(tag_info->objectType, tag_info->objectHandle);
+
+    return thunk_vkSetDebugUtilsObjectTagEXT(device, &wine_tag_info);
+}
+
+VkResult WINAPI wine_vkSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT *name_info)
+{
+    VkDebugUtilsObjectNameInfoEXT wine_name_info;
+
+    TRACE("%p, %p\n", device, name_info);
+
+    wine_name_info = *name_info;
+    wine_name_info.objectHandle = wine_vk_unwrap_handle(name_info->objectType, name_info->objectHandle);
+
+    return thunk_vkSetDebugUtilsObjectNameEXT(device, &wine_name_info);
+}
+
 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved)
 {
     TRACE("%p, %u, %p\n", hinst, reason, reserved);
diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h
index 959a813a213..eec0ef595d0 100644
--- a/dlls/winevulkan/vulkan_private.h
+++ b/dlls/winevulkan/vulkan_private.h
@@ -95,6 +95,8 @@ struct VkDevice_T
     struct wine_vk_mapping mapping;
 };
 
+struct wine_debug_utils_messenger;
+
 struct VkInstance_T
 {
     struct wine_vk_base base;
@@ -111,6 +113,9 @@ struct VkInstance_T
     struct list wrappers;
     SRWLOCK wrapper_lock;
 
+    struct wine_debug_utils_messenger *utils_messengers;
+    uint32_t utils_messenger_count;
+
     unsigned int quirks;
 
     struct wine_vk_mapping mapping;
@@ -158,6 +163,30 @@ static inline VkCommandPool wine_cmd_pool_to_handle(struct wine_cmd_pool *cmd_po
     return (VkCommandPool)(uintptr_t)cmd_pool;
 }
 
+struct wine_debug_utils_messenger
+{
+    struct VkInstance_T *instance; /* parent */
+    VkDebugUtilsMessengerEXT debug_messenger; /* native messenger */
+
+    /* application callback + data */
+    PFN_vkDebugUtilsMessengerCallbackEXT user_callback;
+    void *user_data;
+
+    struct wine_vk_mapping mapping;
+};
+
+static inline struct wine_debug_utils_messenger *wine_debug_utils_messenger_from_handle(
+        VkDebugUtilsMessengerEXT handle)
+{
+    return (struct wine_debug_utils_messenger *)(uintptr_t)handle;
+}
+
+static inline VkDebugUtilsMessengerEXT wine_debug_utils_messenger_to_handle(
+        struct wine_debug_utils_messenger *debug_messenger)
+{
+    return (VkDebugUtilsMessengerEXT)(uintptr_t)debug_messenger;
+}
+
 void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN;
 void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
 
-- 
2.28.0




More information about the wine-devel mailing list