<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>