Commit 28d75542 authored by Georg Lehmann's avatar Georg Lehmann Committed by Alexandre Julliard

winevulkan: Implement VK_EXT_debug_report.

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. Needed for Quake2RTX. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49813Signed-off-by: 's avatarGeorg Lehmann <dadschoorse@gmail.com> Signed-off-by: 's avatarLiam Middlebrook <lmiddlebrook@nvidia.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 03395fdf
......@@ -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
......
......@@ -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);
......
......@@ -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;
......
......@@ -3126,6 +3126,24 @@ VkResult convert_VkInstanceCreateInfo_struct_chain(const void *pNext, VkInstance
case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO:
break;
case VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT:
{
const VkDebugReportCallbackCreateInfoEXT *in = (const VkDebugReportCallbackCreateInfoEXT *)in_header;
VkDebugReportCallbackCreateInfoEXT *out;
if (!(out = heap_alloc(sizeof(*out)))) goto out_of_memory;
out->sType = in->sType;
out->pNext = NULL;
out->flags = in->flags;
out->pfnCallback = in->pfnCallback;
out->pUserData = in->pUserData;
out_header->pNext = (VkBaseOutStructure *)out;
out_header = out_header->pNext;
break;
}
case VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT:
{
const VkDebugUtilsMessengerCreateInfoEXT *in = (const VkDebugUtilsMessengerCreateInfoEXT *)in_header;
......@@ -6210,10 +6228,13 @@ static const struct vulkan_func vk_device_dispatch_table[] =
static const struct vulkan_func vk_instance_dispatch_table[] =
{
{"vkCreateDebugReportCallbackEXT", &wine_vkCreateDebugReportCallbackEXT},
{"vkCreateDebugUtilsMessengerEXT", &wine_vkCreateDebugUtilsMessengerEXT},
{"vkCreateDevice", &wine_vkCreateDevice},
{"vkCreateHeadlessSurfaceEXT", &wine_vkCreateHeadlessSurfaceEXT},
{"vkCreateWin32SurfaceKHR", &wine_vkCreateWin32SurfaceKHR},
{"vkDebugReportMessageEXT", &wine_vkDebugReportMessageEXT},
{"vkDestroyDebugReportCallbackEXT", &wine_vkDestroyDebugReportCallbackEXT},
{"vkDestroyDebugUtilsMessengerEXT", &wine_vkDestroyDebugUtilsMessengerEXT},
{"vkDestroyInstance", &wine_vkDestroyInstance},
{"vkDestroySurfaceKHR", &wine_vkDestroySurfaceKHR},
......@@ -6457,6 +6478,7 @@ static const char * const vk_device_extensions[] =
static const char * const vk_instance_extensions[] =
{
"VK_EXT_debug_report",
"VK_EXT_debug_utils",
"VK_EXT_headless_surface",
"VK_EXT_swapchain_colorspace",
......@@ -6497,6 +6519,7 @@ BOOL wine_vk_is_type_wrapped(VkObjectType type)
return FALSE ||
type == VK_OBJECT_TYPE_COMMAND_BUFFER ||
type == VK_OBJECT_TYPE_COMMAND_POOL ||
type == VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT ||
type == VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT ||
type == VK_OBJECT_TYPE_DEVICE ||
type == VK_OBJECT_TYPE_INSTANCE ||
......@@ -6512,6 +6535,8 @@ uint64_t wine_vk_unwrap_handle(VkObjectType type, uint64_t handle)
return (uint64_t) (uintptr_t) ((VkCommandBuffer) (uintptr_t) handle)->command_buffer;
case VK_OBJECT_TYPE_COMMAND_POOL:
return (uint64_t) wine_cmd_pool_from_handle(handle)->command_pool;
case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT:
return (uint64_t) wine_debug_report_callback_from_handle(handle)->debug_callback;
case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT:
return (uint64_t) wine_debug_utils_messenger_from_handle(handle)->debug_messenger;
case VK_OBJECT_TYPE_DEVICE:
......
......@@ -18,9 +18,12 @@
VkResult WINAPI wine_vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers);
void WINAPI wine_vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers);
VkResult WINAPI wine_vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool);
VkResult WINAPI wine_vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) DECLSPEC_HIDDEN;
VkResult WINAPI wine_vkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger) DECLSPEC_HIDDEN;
VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice);
void WINAPI wine_vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char *pLayerPrefix, const char *pMessage) DECLSPEC_HIDDEN;
void WINAPI wine_vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator);
void WINAPI wine_vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN;
void WINAPI wine_vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN;
void WINAPI wine_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator);
void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator);
......@@ -1697,10 +1700,13 @@ struct vulkan_device_funcs
/* For use by vkInstance and children */
struct vulkan_instance_funcs
{
VkResult (*p_vkCreateDebugReportCallbackEXT)(VkInstance, const VkDebugReportCallbackCreateInfoEXT *, const VkAllocationCallbacks *, VkDebugReportCallbackEXT *);
VkResult (*p_vkCreateDebugUtilsMessengerEXT)(VkInstance, const VkDebugUtilsMessengerCreateInfoEXT *, const VkAllocationCallbacks *, VkDebugUtilsMessengerEXT *);
VkResult (*p_vkCreateDevice)(VkPhysicalDevice, const VkDeviceCreateInfo *, const VkAllocationCallbacks *, VkDevice *);
VkResult (*p_vkCreateHeadlessSurfaceEXT)(VkInstance, const VkHeadlessSurfaceCreateInfoEXT *, const VkAllocationCallbacks *, VkSurfaceKHR *);
VkResult (*p_vkCreateWin32SurfaceKHR)(VkInstance, const VkWin32SurfaceCreateInfoKHR *, const VkAllocationCallbacks *, VkSurfaceKHR *);
void (*p_vkDebugReportMessageEXT)(VkInstance, VkDebugReportFlagsEXT, VkDebugReportObjectTypeEXT, uint64_t, size_t, int32_t, const char *, const char *);
void (*p_vkDestroyDebugReportCallbackEXT)(VkInstance, VkDebugReportCallbackEXT, const VkAllocationCallbacks *);
void (*p_vkDestroyDebugUtilsMessengerEXT)(VkInstance, VkDebugUtilsMessengerEXT, const VkAllocationCallbacks *);
void (*p_vkDestroySurfaceKHR)(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks *);
VkResult (*p_vkEnumerateDeviceExtensionProperties)(VkPhysicalDevice, const char *, uint32_t *, VkExtensionProperties *);
......@@ -2081,10 +2087,13 @@ struct vulkan_instance_funcs
USE_VK_FUNC(vkWaitSemaphoresKHR)
#define ALL_VK_INSTANCE_FUNCS() \
USE_VK_FUNC(vkCreateDebugReportCallbackEXT) \
USE_VK_FUNC(vkCreateDebugUtilsMessengerEXT) \
USE_VK_FUNC(vkCreateDevice) \
USE_VK_FUNC(vkCreateHeadlessSurfaceEXT) \
USE_VK_FUNC(vkCreateWin32SurfaceKHR) \
USE_VK_FUNC(vkDebugReportMessageEXT) \
USE_VK_FUNC(vkDestroyDebugReportCallbackEXT) \
USE_VK_FUNC(vkDestroyDebugUtilsMessengerEXT) \
USE_VK_FUNC(vkDestroySurfaceKHR) \
USE_VK_FUNC(vkEnumerateDeviceExtensionProperties) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment