<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <div class="moz-cite-prefix">I was testing Serious Sam 4 crash on
      start on Nvidia and found that it also happens due to debug
      function implementation in winevulkan. More precisely, in case of
      Serious Sam, the crash happens in host
      vkSetDebugUtilsObjectNameEXT() when called with objectType
      VK_OBJECT_TYPE_SURFACE_KHR. wine_vk_unwrap_handle() returns an
      unwrapped handler for this object type, while the native handle is
      actually wrapped in struct wine_vk_surfaceby wine driver
      (winex11.drv). I tested that correctly unwrapping it fixes the
      crash.</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">I am a bit unsure how to properly fix
      it. The straightforward way is to pull all the debug functions to
      wine[x11|mac].drv, but that means pulling rather lot. Besides,
      debugging functions have to be queried from device which winex11
      currently doesn't do so we would probably need to also pull
      vkCreateDevice() to initialize native function pointers.</div>
    <div class="moz-cite-prefix">The other much shorter way would be to
      export the unwrapping function from the wine driver which will be
      unwrapping handles wrapped in there. It would probably be
      unfortunate to introduce a special export for that, maybe we could
      put it in the generated 'struct vulkan_funcs' somehow?</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">Any suggestions?<br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix"><br>
    </div>
    <div class="moz-cite-prefix">On 10/6/20 06:35, Thomas Crider wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAJ6D9hS+a=uBqWq+Ci=MVPAGjhMEbG_4zkr_rtgJswkq2tQ3hg@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">Just a heads up, I was testing these patches and
        found they cause Horizon Zero Dawn to crash on startup on
        nvidia. works fine on AMD/radv</div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Tue, Sep 29, 2020 at 5:21
          PM Liam Middlebrook <<a
            href="mailto:lmiddlebrook@nvidia.com" moz-do-not-send="true">lmiddlebrook@nvidia.com</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px
          0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">This
          looks good to me, but given the requested changes to dependent
          <br>
          patches 1/3 and 2/3, I'll wait to sign-off on this one.<br>
          <br>
          <br>
          Thanks,<br>
          <br>
          Liam Middlebrook<br>
          <br>
          On 9/25/20 8:16 AM, Georg Lehmann wrote:<br>
          > Wine-Bug: <a
            href="https://bugs.winehq.org/show_bug.cgi?id=49813"
            rel="noreferrer" target="_blank" moz-do-not-send="true">https://bugs.winehq.org/show_bug.cgi?id=49813</a><br>
          > <br>
          > Signed-off-by: Georg Lehmann <<a
            href="mailto:dadschoorse@gmail.com" target="_blank"
            moz-do-not-send="true">dadschoorse@gmail.com</a>><br>
          > ---<br>
          >   dlls/winevulkan/make_vulkan      |   8 +-<br>
          >   dlls/winevulkan/vulkan.c         | 183
          +++++++++++++++++++++++++++++++<br>
          >   dlls/winevulkan/vulkan_private.h |  31 ++++++<br>
          >   3 files changed, 221 insertions(+), 1 deletion(-)<br>
          > <br>
          > diff --git a/dlls/winevulkan/make_vulkan
          b/dlls/winevulkan/make_vulkan<br>
          > index afea087a92..623d1b9cde 100755<br>
          > --- a/dlls/winevulkan/make_vulkan<br>
          > +++ b/dlls/winevulkan/make_vulkan<br>
          > @@ -92,7 +92,6 @@ UNSUPPORTED_EXTENSIONS = [<br>
          >       # plumbing down to the native layer, we will get
          each message twice as we<br>
          >       # use 2 loaders (win32+native), but we may get
          output from the driver.<br>
          >       # In any case callback conversion is required.<br>
          > -    "VK_EXT_debug_utils",<br>
          >       "VK_EXT_validation_features",<br>
          >       "VK_EXT_validation_flags",<br>
          >       "VK_KHR_display", # Needs WSI work.<br>
          > @@ -225,6 +224,11 @@ FUNCTION_OVERRIDES = {<br>
          >       # VK_EXT_calibrated_timestamps<br>
          >       "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT" :
          {"dispatch" : True, "driver" : False, "thunk" : False},<br>
          >       "vkGetCalibratedTimestampsEXT" : {"dispatch" :
          True, "driver" : False, "thunk" : False},<br>
          > +<br>
          > +    # VK_EXT_debug_utils<br>
          > +    "vkCreateDebugUtilsMessengerEXT" : {"dispatch":
          True, "driver" : False, "thunk" : False},<br>
          > +    "vkDestroyDebugUtilsMessengerEXT" : {"dispatch":
          True, "driver" : False, "thunk" : False},<br>
          > +    "vkSubmitDebugUtilsMessageEXT" : {"dispatch": True,
          "driver" : False, "thunk" : True, "private_thunk" : True},<br>
          >   }<br>
          >   <br>
          >   STRUCT_CHAIN_CONVERSIONS = [<br>
          > @@ -941,6 +945,8 @@ class VkHandle(object):<br>
          >   <br>
          >           if <a href="http://self.name" rel="noreferrer"
            target="_blank" moz-do-not-send="true">self.name</a> ==
          "VkCommandPool":<br>
          >               return
          "wine_cmd_pool_from_handle({0})->command_pool".format(name)<br>
          > +        if <a href="http://self.name" rel="noreferrer"
            target="_blank" moz-do-not-send="true">self.name</a> ==
          "VkDebugUtilsMessengerEXT":<br>
          > +            return
"wine_debug_utils_messenger_from_handle({0})->debug_messenger".format(name)<br>
          >   <br>
          >           native_handle_name = None<br>
          >   <br>
          > diff --git a/dlls/winevulkan/vulkan.c
          b/dlls/winevulkan/vulkan.c<br>
          > index 54b910c5e5..f831d486d0 100644<br>
          > --- a/dlls/winevulkan/vulkan.c<br>
          > +++ b/dlls/winevulkan/vulkan.c<br>
          > @@ -57,6 +57,21 @@ static void *wine_vk_find_struct_(void
          *s, VkStructureType t)<br>
          >       return NULL;<br>
          >   }<br>
          >   <br>
          > +#define wine_vk_count_struct(s, t)
          wine_vk_count_struct_((void *)s, VK_STRUCTURE_TYPE_##t)<br>
          > +static uint32_t wine_vk_count_struct_(void *s,
          VkStructureType t)<br>
          > +{<br>
          > +    const VkBaseInStructure *header;<br>
          > +    uint32_t result = 0;<br>
          > +<br>
          > +    for (header = s; header; header = header->pNext)<br>
          > +    {<br>
          > +        if (header->sType == t)<br>
          > +            result++;<br>
          > +    }<br>
          > +<br>
          > +    return result;<br>
          > +}<br>
          > +<br>
          >   static void *wine_vk_get_global_proc_addr(const char
          *name);<br>
          >   <br>
          >   static HINSTANCE hinstance;<br>
          > @@ -113,6 +128,68 @@ static uint64_t
          wine_vk_get_wrapper(struct VkInstance_T *instance, uint64_t
          nati<br>
          >       return result;<br>
          >   }<br>
          >   <br>
          > +static VkBool32
          debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagBitsEXT
          severity,<br>
          > +    VkDebugUtilsMessageTypeFlagsEXT message_types,<br>
          > +#if defined(USE_STRUCT_CONVERSION)<br>
          > +    const VkDebugUtilsMessengerCallbackDataEXT_host
          *callback_data,<br>
          > +#else<br>
          > +    const VkDebugUtilsMessengerCallbackDataEXT
          *callback_data,<br>
          > +#endif<br>
          > +    void *user_data)<br>
          > +{<br>
          > +    struct VkDebugUtilsMessengerCallbackDataEXT
          wine_callback_data;<br>
          > +    VkDebugUtilsObjectNameInfoEXT *object_name_infos;<br>
          > +    struct wine_debug_utils_messenger *object;<br>
          > +    VkBool32 result;<br>
          > +    int i;<br>
          > +<br>
          > +    TRACE("%i, %u, %p, %p\n", severity, message_types,
          callback_data, user_data);<br>
          > +<br>
          > +    object = user_data;<br>
          > +<br>
          > +    if (!object->instance->instance)<br>
          > +    {<br>
          > +        /* instance wasn't yet created, this is a
          message from the native loader */<br>
          > +        return VK_FALSE;<br>
          > +    }<br>
          > +<br>
          > +    wine_callback_data =
          *((VkDebugUtilsMessengerCallbackDataEXT *) callback_data);<br>
          > +<br>
          > +    object_name_infos =
          heap_calloc(wine_callback_data.objectCount,
          sizeof(*object_name_infos));<br>
          > +<br>
          > +    for (i = 0; i < wine_callback_data.objectCount;
          i++)<br>
          > +    {<br>
          > +        object_name_infos[i].sType =
          callback_data->pObjects[i].sType;<br>
          > +        object_name_infos[i].pNext =
          callback_data->pObjects[i].pNext;<br>
          > +        object_name_infos[i].objectType =
          callback_data->pObjects[i].objectType;<br>
          > +        object_name_infos[i].pObjectName =
          callback_data->pObjects[i].pObjectName;<br>
          > +<br>
          > +        if
          (wine_vk_is_type_wrapped(callback_data->pObjects[i].objectType))<br>
          > +        {<br>
          > +            object_name_infos[i].objectHandle =
          wine_vk_get_wrapper(object->instance,
          callback_data->pObjects[i].objectHandle);<br>
          > +            if (!object_name_infos[i].objectHandle)<br>
          > +            {<br>
          > +                WARN("handle conversion failed 0x%s\n",
wine_dbgstr_longlong(callback_data->pObjects[i].objectHandle));<br>
          > +                heap_free(object_name_infos);<br>
          > +                return VK_FALSE;<br>
          > +            }<br>
          > +        }<br>
          > +        else<br>
          > +        {<br>
          > +            object_name_infos[i].objectHandle =
          callback_data->pObjects[i].objectHandle;<br>
          > +        }<br>
          > +    }<br>
          > +<br>
          > +    wine_callback_data.pObjects = object_name_infos;<br>
          > +<br>
          > +    /* applications should always return VK_FALSE */<br>
          > +    result = object->user_callback(severity,
          message_types, &wine_callback_data, object->user_data);<br>
          > +<br>
          > +    heap_free(object_name_infos);<br>
          > +<br>
          > +    return result;<br>
          > +}<br>
          > +<br>
          >   static void wine_vk_physical_device_free(struct
          VkPhysicalDevice_T *phys_dev)<br>
          >   {<br>
          >       if (!phys_dev)<br>
          > @@ -393,6 +470,8 @@ static void wine_vk_init_once(void)<br>
          >   static VkResult
          wine_vk_instance_convert_create_info(const
          VkInstanceCreateInfo *src,<br>
          >           VkInstanceCreateInfo *dst, struct VkInstance_T
          *object)<br>
          >   {<br>
          > +    VkDebugUtilsMessengerCreateInfoEXT
          *debug_utils_messenger;<br>
          > +    VkBaseInStructure *header;<br>
          >       unsigned int i;<br>
          >       VkResult res;<br>
          >   <br>
          > @@ -404,6 +483,26 @@ static VkResult
          wine_vk_instance_convert_create_info(const
          VkInstanceCreateInfo<br>
          >           return res;<br>
          >       }<br>
          >   <br>
          > +    object->utils_messenger_count =
          wine_vk_count_struct(dst,
          DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT);<br>
          > +    object->utils_messengers = 
          heap_calloc(object->utils_messenger_count,
          sizeof(*object->utils_messengers));<br>
          > +    header = (VkBaseInStructure *) dst;<br>
          > +    for (i = 0; i < object->utils_messenger_count;
          i++)<br>
          > +    {<br>
          > +        header = wine_vk_find_struct(header->pNext,
          DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT);<br>
          > +        debug_utils_messenger =
          (VkDebugUtilsMessengerCreateInfoEXT *) header;<br>
          > +<br>
          > +        object->utils_messengers[i].instance =
          object;<br>
          > +        object->utils_messengers[i].debug_messenger =
          VK_NULL_HANDLE;<br>
          > +        object->utils_messengers[i].user_callback =
          debug_utils_messenger->pfnUserCallback;<br>
          > +        object->utils_messengers[i].user_data =
          debug_utils_messenger->pUserData;<br>
          > +<br>
          > +        /* convert_VkInstanceCreateInfo_struct_chain
          already copied the chain,<br>
          > +         * so we can modify it in-place.<br>
          > +         */<br>
          > +        debug_utils_messenger->pfnUserCallback =
          (void *) &debug_utils_callback_conversion;<br>
          > +        debug_utils_messenger->pUserData =
          &object->utils_messengers[i];<br>
          > +    }<br>
          > +<br>
          >       /* ICDs don't support any layers, so nothing to
          copy. Modern versions of the loader<br>
          >        * filter this data out as well.<br>
          >        */<br>
          > @@ -427,6 +526,10 @@ static VkResult
          wine_vk_instance_convert_create_info(const
          VkInstanceCreateInfo<br>
          >             
           free_VkInstanceCreateInfo_struct_chain(dst);<br>
          >               return VK_ERROR_EXTENSION_NOT_PRESENT;<br>
          >           }<br>
          > +        if (!strcmp(extension_name,
          "VK_EXT_debug_utils"))<br>
          > +        {<br>
          > +            object->enable_wrapper_list = VK_TRUE;<br>
          > +        }<br>
          >       }<br>
          >   <br>
          >       return VK_SUCCESS;<br>
          > @@ -527,6 +630,8 @@ static void
          wine_vk_instance_free(struct VkInstance_T *instance)<br>
          >           WINE_VK_REMOVE_HANDLE_MAPPING(instance,
          instance);<br>
          >       }<br>
          >   <br>
          > +    heap_free(instance->utils_messengers);<br>
          > +<br>
          >       heap_free(instance);<br>
          >   }<br>
          >   <br>
          > @@ -1673,6 +1778,84 @@ VkResult WINAPI
          wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice<br>
          >       return res;<br>
          >   }<br>
          >   <br>
          > +VkResult WINAPI
          wine_vkCreateDebugUtilsMessengerEXT(VkInstance instance, const
          VkDebugUtilsMessengerCreateInfoEXT *create_info,<br>
          > +        const VkAllocationCallbacks *allocator,
          VkDebugUtilsMessengerEXT *messenger)<br>
          > +{<br>
          > +    VkDebugUtilsMessengerCreateInfoEXT wine_create_info;<br>
          > +    struct wine_debug_utils_messenger *object;<br>
          > +    VkResult res;<br>
          > +<br>
          > +    TRACE("%p, %p, %p, %p\n", instance, create_info,
          allocator, messenger);<br>
          > +<br>
          > +    if (allocator)<br>
          > +        FIXME("Support for allocation callbacks not
          implemented yet\n");<br>
          > +<br>
          > +    if (!(object = heap_alloc_zero(sizeof(*object))))<br>
          > +        return VK_ERROR_OUT_OF_HOST_MEMORY;<br>
          > +<br>
          > +    object->instance = instance;<br>
          > +    object->user_callback =
          create_info->pfnUserCallback;<br>
          > +    object->user_data = create_info->pUserData;<br>
          > +<br>
          > +    wine_create_info = *create_info;<br>
          > +<br>
          > +    wine_create_info.pfnUserCallback = (void *)
          &debug_utils_callback_conversion;<br>
          > +    wine_create_info.pUserData = object;<br>
          > +<br>
          > +    res =
instance->funcs.p_vkCreateDebugUtilsMessengerEXT(instance->instance,
          &wine_create_info, NULL, 
          &object->debug_messenger);<br>
          > +<br>
          > +    if (res != VK_SUCCESS)<br>
          > +    {<br>
          > +        heap_free(object);<br>
          > +        return res;<br>
          > +    }<br>
          > +<br>
          > +    WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance,
          object, object->debug_messenger);<br>
          > +    *messenger =
          wine_debug_utils_messenger_to_handle(object);<br>
          > +<br>
          > +    return VK_SUCCESS;<br>
          > +}<br>
          > +<br>
          > +void WINAPI wine_vkDestroyDebugUtilsMessengerEXT(<br>
          > +        VkInstance instance, VkDebugUtilsMessengerEXT
          messenger, const VkAllocationCallbacks *allocator)<br>
          > +{<br>
          > +    struct wine_debug_utils_messenger *object;<br>
          > +<br>
          > +    TRACE("%p, 0x%s, %p\n", instance,
          wine_dbgstr_longlong(messenger), allocator);<br>
          > +<br>
          > +    object =
          wine_debug_utils_messenger_from_handle(messenger);<br>
          > +<br>
          > +   
instance->funcs.p_vkDestroyDebugUtilsMessengerEXT(instance->instance,
          object->debug_messenger, NULL);<br>
          > +    WINE_VK_REMOVE_HANDLE_MAPPING(instance, object);<br>
          > +<br>
          > +    heap_free(object);<br>
          > +}<br>
          > +<br>
          > +void WINAPI wine_vkSubmitDebugUtilsMessageEXT(VkInstance
          instance, VkDebugUtilsMessageSeverityFlagBitsEXT severity,<br>
          > +        VkDebugUtilsMessageTypeFlagsEXT types, const
          VkDebugUtilsMessengerCallbackDataEXT *callback_data)<br>
          > +{<br>
          > +    VkDebugUtilsMessengerCallbackDataEXT
          native_callback_data;<br>
          > +    VkDebugUtilsObjectNameInfoEXT *object_names;<br>
          > +    int i;<br>
          > +<br>
          > +    TRACE("%p, %#x, %#x, %p\n", instance, severity,
          types, callback_data);<br>
          > +<br>
          > +    native_callback_data = *callback_data;<br>
          > +    object_names =
          heap_calloc(callback_data->objectCount,
          sizeof(*object_names));<br>
          > +    memcpy(object_names, callback_data->pObjects,
          callback_data->objectCount * sizeof(*object_names));<br>
          > +    native_callback_data.pObjects = object_names;<br>
          > +<br>
          > +    for (i = 0; i < callback_data->objectCount;
          i++)<br>
          > +    {<br>
          > +        object_names[i].objectHandle =<br>
          > +               
          wine_vk_unwrap_handle(callback_data->pObjects[i].objectType,
          callback_data->pObjects[i].objectHandle);<br>
          > +    }<br>
          > +<br>
          > +   
          thunk_vkSubmitDebugUtilsMessageEXT(instance->instance,
          severity, types, &native_callback_data);<br>
          > +<br>
          > +    heap_free(object_names);<br>
          > +}<br>
          > +<br>
          >   BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void
          *reserved)<br>
          >   {<br>
          >       TRACE("%p, %u, %p\n", hinst, reason, reserved);<br>
          > diff --git a/dlls/winevulkan/vulkan_private.h
          b/dlls/winevulkan/vulkan_private.h<br>
          > index 7000da7133..8379fafecf 100644<br>
          > --- a/dlls/winevulkan/vulkan_private.h<br>
          > +++ b/dlls/winevulkan/vulkan_private.h<br>
          > @@ -95,6 +95,8 @@ struct VkDevice_T<br>
          >       struct wine_vk_mapping mapping;<br>
          >   };<br>
          >   <br>
          > +struct wine_debug_utils_messenger;<br>
          > +<br>
          >   struct VkInstance_T<br>
          >   {<br>
          >       struct wine_vk_base base;<br>
          > @@ -111,6 +113,9 @@ struct VkInstance_T<br>
          >       struct list wrappers;<br>
          >       SRWLOCK wrapper_lock;<br>
          >   <br>
          > +    struct wine_debug_utils_messenger *utils_messengers;<br>
          > +    uint32_t utils_messenger_count;<br>
          > +<br>
          >       unsigned int quirks;<br>
          >       <br>
          >       struct wine_vk_mapping mapping;<br>
          > @@ -158,6 +163,32 @@ static inline VkCommandPool
          wine_cmd_pool_to_handle(struct wine_cmd_pool *cmd_po<br>
          >       return (VkCommandPool)(uintptr_t)cmd_pool;<br>
          >   }<br>
          >   <br>
          > +struct wine_debug_utils_messenger<br>
          > +{<br>
          > +    struct VkInstance_T *instance; /* parent */<br>
          > +    VkDebugUtilsMessengerEXT debug_messenger; /* native
          messenger */<br>
          > +<br>
          > +    /* application callback + data */<br>
          > +    PFN_vkDebugUtilsMessengerCallbackEXT user_callback;<br>
          > +    void *user_data;<br>
          > +<br>
          > +    struct wine_vk_mapping mapping;<br>
          > +};<br>
          > +<br>
          > +static inline struct wine_debug_utils_messenger
          *wine_debug_utils_messenger_from_handle(<br>
          > +        VkDebugUtilsMessengerEXT handle)<br>
          > +{<br>
          > +    return (struct wine_debug_utils_messenger
          *)(uintptr_t)handle;<br>
          > +}<br>
          > +<br>
          > +static inline VkDebugUtilsMessengerEXT
          wine_debug_utils_messenger_to_handle(<br>
          > +        struct wine_debug_utils_messenger
          *debug_messenger)<br>
          > +{<br>
          > +    return
          (VkDebugUtilsMessengerEXT)(uintptr_t)debug_messenger;<br>
          > +}<br>
          > +<br>
          > +<br>
          > +<br>
          >   void *wine_vk_get_device_proc_addr(const char *name)
          DECLSPEC_HIDDEN;<br>
          >   void *wine_vk_get_instance_proc_addr(const char *name)
          DECLSPEC_HIDDEN;<br>
          >   <br>
          > <br>
          <br>
        </blockquote>
      </div>
    </blockquote>
    <p><br>
    </p>
  </body>
</html>