[PATCH v2] winevulkan: Implement VK_EXT_debug_report.

Georg Lehmann dadschoorse at gmail.com
Tue Oct 27 15:18:54 CDT 2020


Messages from the driver/layers won't be reported twice.
Messages during instance creation by the host loader won't be reported,
since the information is partly wrong and the windows loader reports the
correct information.
Other messages by the loader will be reported twice if lunarg's vulkan-1.dll
is used. This shouldn't be a problem because the messages are just used
for logging/debugging.

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

Needed for Quake2RTX.

Signed-off-by: Georg Lehmann <dadschoorse at gmail.com>
---
 dlls/winevulkan/make_vulkan      |  14 +++--
 dlls/winevulkan/vulkan.c         | 105 ++++++++++++++++++++++++++++++-
 dlls/winevulkan/vulkan_private.h |  26 ++++++++
 3 files changed, 138 insertions(+), 7 deletions(-)

diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index a07c1d77bf5..7e5bd030867 100755
--- a/dlls/winevulkan/make_vulkan
+++ b/dlls/winevulkan/make_vulkan
@@ -86,12 +86,7 @@ EXT_BLOCK_SIZE = 1000
 
 UNSUPPORTED_EXTENSIONS = [
     # Instance extensions
-    "VK_EXT_debug_report",
-    # Handling of VK_EXT_debug_report requires some consideration. The win32
-    # loader already provides it for us and it is somewhat usable. If we add
-    # 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_marker", # Needs handle unwrapping
     "VK_EXT_validation_features",
     "VK_EXT_validation_flags",
     "VK_KHR_display", # Needs WSI work.
@@ -234,6 +229,11 @@ FUNCTION_OVERRIDES = {
     "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},
+
+    # VK_EXT_debug_report
+    "vkCreateDebugReportCallbackEXT" : {"dispatch": True, "driver" : False, "thunk" : False},
+    "vkDestroyDebugReportCallbackEXT" : {"dispatch": True, "driver" : False, "thunk" : False},
+    "vkDebugReportMessageEXT" : {"dispatch": True, "driver" : False, "thunk" : False},
 }
 
 STRUCT_CHAIN_CONVERSIONS = [
@@ -955,6 +955,8 @@ class VkHandle(object):
             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)
+        if self.name == "VkDebugReportCallbackEXT":
+            return "wine_debug_report_callback_from_handle({0})->debug_callback".format(name)
 
         native_handle_name = None
 
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c
index 92c26be1fc0..d486f43e66c 100644
--- a/dlls/winevulkan/vulkan.c
+++ b/dlls/winevulkan/vulkan.c
@@ -190,6 +190,30 @@ static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagB
     return result;
 }
 
+static VkBool32 debug_report_callback_conversion(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT object_type,
+    uint64_t object_handle, size_t location, int32_t code, const char *layer_prefix, const char *message, void *user_data)
+{
+    struct wine_debug_report_callback *object;
+
+    TRACE("%#x, %#x, 0x%s, 0x%s, %d, %p, %p, %p\n", flags, object_type, wine_dbgstr_longlong(object_handle),
+        wine_dbgstr_longlong(location), code, layer_prefix, message, 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;
+    }
+
+    object_handle = wine_vk_get_wrapper(object->instance, object_handle);
+    if (!object_handle)
+        object_type = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
+
+    return object->user_callback(
+        flags, object_type, object_handle, location, code, layer_prefix, message, object->user_data);
+}
+
 static void wine_vk_physical_device_free(struct VkPhysicalDevice_T *phys_dev)
 {
     if (!phys_dev)
@@ -471,6 +495,7 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
         VkInstanceCreateInfo *dst, struct VkInstance_T *object)
 {
     VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger;
+    VkDebugReportCallbackCreateInfoEXT *debug_report_callback;
     VkBaseInStructure *header;
     unsigned int i;
     VkResult res;
@@ -503,6 +528,18 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
         debug_utils_messenger->pUserData = &object->utils_messengers[i];
     }
 
+    debug_report_callback = wine_vk_find_struct(header->pNext, DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT);
+    if (debug_report_callback)
+    {
+        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;
+
+        debug_report_callback->pfnCallback = (void *) &debug_report_callback_conversion;
+        debug_report_callback->pUserData = &object->default_callback;
+    }
+
     /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader
      * filter this data out as well.
      */
@@ -526,7 +563,7 @@ 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"))
+        if (!strcmp(extension_name, "VK_EXT_debug_utils") || !strcmp(extension_name, "VK_EXT_debug_report"))
         {
             object->enable_wrapper_list = VK_TRUE;
         }
@@ -1880,6 +1917,72 @@ VkResult WINAPI wine_vkSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebug
     return thunk_vkSetDebugUtilsObjectNameEXT(device, &wine_name_info);
 }
 
+VkResult WINAPI wine_vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *create_info,
+    const VkAllocationCallbacks *allocator, VkDebugReportCallbackEXT *callback)
+{
+    VkDebugReportCallbackCreateInfoEXT wine_create_info;
+    struct wine_debug_report_callback *object;
+    VkResult res;
+
+    TRACE("%p, %p, %p, %p\n", instance, create_info, allocator, callback);
+
+    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->pfnCallback;
+    object->user_data = create_info->pUserData;
+
+    wine_create_info = *create_info;
+
+    wine_create_info.pfnCallback = (void *) debug_report_callback_conversion;
+    wine_create_info.pUserData = object;
+
+    res = instance->funcs.p_vkCreateDebugReportCallbackEXT(instance->instance, &wine_create_info, NULL, &object->debug_callback);
+
+    if (res != VK_SUCCESS)
+    {
+        heap_free(object);
+        return res;
+    }
+
+    WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, object->debug_callback);
+    *callback = wine_debug_report_callback_to_handle(object);
+
+    return VK_SUCCESS;
+}
+
+void WINAPI wine_vkDestroyDebugReportCallbackEXT(
+    VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks *allocator)
+{
+    struct wine_debug_report_callback *object;
+
+    TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(callback), allocator);
+
+    object = wine_debug_report_callback_from_handle(callback);
+
+    instance->funcs.p_vkDestroyDebugReportCallbackEXT(instance->instance, object->debug_callback, NULL);
+
+    WINE_VK_REMOVE_HANDLE_MAPPING(instance, object);
+
+    heap_free(object);
+}
+
+void WINAPI wine_vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT object_type,
+    uint64_t object, size_t location, int32_t code, const char *layer_prefix, const char *message)
+{
+    TRACE("%p, %#x, %#x, 0x%s, 0x%s, %d, %p, %p\n", instance, flags, object_type, wine_dbgstr_longlong(object),
+        wine_dbgstr_longlong(location), code, layer_prefix, message);
+
+    object = wine_vk_unwrap_handle(object_type, object);
+
+    instance->funcs.p_vkDebugReportMessageEXT(
+        instance->instance, flags, object_type, object, location, code, layer_prefix, message);
+}
+
 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 eec0ef595d0..92c04543587 100644
--- a/dlls/winevulkan/vulkan_private.h
+++ b/dlls/winevulkan/vulkan_private.h
@@ -97,6 +97,18 @@ struct VkDevice_T
 
 struct wine_debug_utils_messenger;
 
+struct wine_debug_report_callback
+{
+    struct VkInstance_T *instance; /* parent */
+    VkDebugReportCallbackEXT debug_callback; /* native callback object */
+
+    /* application callback + data */
+    PFN_vkDebugReportCallbackEXT user_callback;
+    void *user_data;
+
+    struct wine_vk_mapping mapping;
+};
+
 struct VkInstance_T
 {
     struct wine_vk_base base;
@@ -116,6 +128,8 @@ struct VkInstance_T
     struct wine_debug_utils_messenger *utils_messengers;
     uint32_t utils_messenger_count;
 
+    struct wine_debug_report_callback default_callback;
+
     unsigned int quirks;
 
     struct wine_vk_mapping mapping;
@@ -187,6 +201,18 @@ static inline VkDebugUtilsMessengerEXT wine_debug_utils_messenger_to_handle(
     return (VkDebugUtilsMessengerEXT)(uintptr_t)debug_messenger;
 }
 
+static inline struct wine_debug_report_callback *wine_debug_report_callback_from_handle(
+        VkDebugReportCallbackEXT handle)
+{
+    return (struct wine_debug_report_callback *)(uintptr_t)handle;
+}
+
+static inline VkDebugReportCallbackEXT wine_debug_report_callback_to_handle(
+        struct wine_debug_report_callback *debug_messenger)
+{
+    return (VkDebugReportCallbackEXT)(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.29.1




More information about the wine-devel mailing list