[PATCH] winevulkan: Implement VK_EXT_debug_report.

Liam Middlebrook lmiddlebrook at nvidia.com
Fri Oct 16 05:26:33 CDT 2020



On 10/14/20 3:21 PM, Georg Lehmann wrote:
> 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 f3f2da7548c..5304a139bae 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.

I recall at one point offline we had discussed this and I had done a 
quick sanity check and didn't see this duplication occur, but I think it 
would be good to verify (or better, prove) that's the case and note such 
in the commit message.

Other than that this looks reasonable to me.


Thanks,

Liam Middlebrook

> +    "VK_EXT_debug_marker", # Needs handle unwrapping
>       "VK_EXT_validation_features",
>       "VK_EXT_validation_flags",
>       "VK_KHR_display", # Needs WSI work.
> @@ -231,6 +226,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 = [
> @@ -952,6 +952,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;
>   
> 



More information about the wine-devel mailing list