From feb9462bb19096ecfcc11b42d5474c6309594cd9 Mon Sep 17 00:00:00 2001 From: Duncan Hopkins Date: Wed, 4 Nov 2020 15:41:11 +0000 Subject: [PATCH] zink: Added inbuilt debug logging from the VK_LAYER_LUNARG_standard_validation layer. Set the ZINK_DEBUG environment variable to 'validation' to automatically setup. The debug util extnsion callback is used to capture information and logs the results to the error stream. Reviewed-By: Mike Blumenkrantz Reviewed-by: Erik Faye-Lund Part-of: --- src/gallium/drivers/zink/zink_screen.c | 96 ++++++++++++++++++++++++++ src/gallium/drivers/zink/zink_screen.h | 6 ++ 2 files changed, 102 insertions(+) diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index a310de78b59..3749ce955c8 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -45,6 +45,7 @@ debug_options[] = { { "nir", ZINK_DEBUG_NIR, "Dump NIR during program compile" }, { "spirv", ZINK_DEBUG_SPIRV, "Dump SPIR-V during program compile" }, { "tgsi", ZINK_DEBUG_TGSI, "Dump TGSI during program compile" }, + { "validation", ZINK_DEBUG_VALIDATION, "Dump Validation layer output" }, DEBUG_NAMED_VALUE_END }; @@ -632,6 +633,11 @@ static void zink_destroy_screen(struct pipe_screen *pscreen) { struct zink_screen *screen = zink_screen(pscreen); + + if (VK_NULL_HANDLE != screen->debugUtilsCallbackHandle) { + screen->vk_DestroyDebugUtilsMessengerEXT(screen->instance, screen->debugUtilsCallbackHandle, NULL); + } + slab_destroy_parent(&screen->transfer_pool); FREE(screen); } @@ -644,6 +650,7 @@ create_instance(struct zink_screen *screen) const char *extensions[4] = { 0 }; uint32_t num_extensions = 0; + bool have_debug_utils_ext = false; #if defined(MVK_VERSION) bool have_moltenvk_layer = false; bool have_moltenvk_layer_ext = false; @@ -659,6 +666,9 @@ create_instance(struct zink_screen *screen) err = vkEnumerateInstanceExtensionProperties(NULL, &extension_count, extension_props); if (err == VK_SUCCESS) { for (uint32_t i = 0; i < extension_count; i++) { + if (!strcmp(extension_props[i].extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) { + have_debug_utils_ext = true; + } if (!strcmp(extension_props[i].extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { extensions[num_extensions++] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; } @@ -678,9 +688,18 @@ create_instance(struct zink_screen *screen) } } + // Clear have_debug_utils_ext if we do not want debug info + if (!(zink_debug & ZINK_DEBUG_VALIDATION)) { + have_debug_utils_ext = false; + } + { // Build up the layers from the reported ones uint32_t layer_count = 0; + // Init has_validation_layer so if we have debug_util allow a validation layer to be added. + // Once a validation layer has been found, do not add any more. + bool has_validation_layer = !have_debug_utils_ext; + VkResult err = vkEnumerateInstanceLayerProperties(&layer_count, NULL); if (err == VK_SUCCESS) { VkLayerProperties *layer_props = malloc(layer_count * sizeof(VkLayerProperties)); @@ -688,6 +707,14 @@ create_instance(struct zink_screen *screen) err = vkEnumerateInstanceLayerProperties(&layer_count, layer_props); if (err == VK_SUCCESS) { for (uint32_t i = 0; i < layer_count; i++) { + if (!strcmp(layer_props[i].layerName, "VK_LAYER_KHRONOS_validation") && !has_validation_layer) { + layers[num_layers++] = "VK_LAYER_KHRONOS_validation"; + has_validation_layer = true; + } + if (!strcmp(layer_props[i].layerName, "VK_LAYER_LUNARG_standard_validation") && !has_validation_layer) { + layers[num_layers++] = "VK_LAYER_LUNARG_standard_validation"; + has_validation_layer = true; + } #if defined(MVK_VERSION) if (!strcmp(layer_props[i].layerName, "MoltenVK")) { have_moltenvk_layer = true; @@ -701,6 +728,11 @@ create_instance(struct zink_screen *screen) } } + if (have_debug_utils_ext) { + extensions[num_extensions++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME; + screen->have_debug_utils_ext = have_debug_utils_ext; + } + #if defined(MVK_VERSION) if (have_moltenvk_layer_ext && have_moltenvk_layer) { screen->have_moltenvk = true; @@ -889,6 +921,67 @@ load_device_extensions(struct zink_screen *screen) return true; } +static VkBool32 VKAPI_CALL +zink_debug_util_callback( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, + void *pUserData) +{ + const char *severity = "MSG"; + + // Pick message prefix and color to use. + // Only MacOS and Linux have been tested for color support + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { + severity = "ERR"; + } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { + severity = "WRN"; + } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) { + severity = "NFO"; + } + + fprintf(stderr, "zink DEBUG: %s: '%s'\n", severity, pCallbackData->pMessage); + return VK_FALSE; +} + +static bool +create_debug(struct zink_screen *screen) +{ + GET_PROC_ADDR_INSTANCE(CreateDebugUtilsMessengerEXT); + GET_PROC_ADDR_INSTANCE(DestroyDebugUtilsMessengerEXT); + + if (!screen->vk_CreateDebugUtilsMessengerEXT || !screen->vk_DestroyDebugUtilsMessengerEXT) + return false; + + VkDebugUtilsMessengerCreateInfoEXT vkDebugUtilsMessengerCreateInfoEXT = { + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, + NULL, + 0, // flags + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, + zink_debug_util_callback, + NULL + }; + + VkDebugUtilsMessengerEXT vkDebugUtilsCallbackEXT = VK_NULL_HANDLE; + + screen->vk_CreateDebugUtilsMessengerEXT( + screen->instance, + &vkDebugUtilsMessengerCreateInfoEXT, + NULL, + &vkDebugUtilsCallbackEXT + ); + + screen->debugUtilsCallbackHandle = vkDebugUtilsCallbackEXT; + + return true; +} + #if defined(MVK_VERSION) static bool zink_internal_setup_moltenvk(struct zink_screen *screen) @@ -943,6 +1036,9 @@ zink_internal_create_screen(struct sw_winsys *winsys, int fd, const struct pipe_ if(!screen->instance) goto fail; + if (screen->have_debug_utils_ext && !create_debug(screen)) + debug_printf("ZINK: failed to setup debug utils\n"); + screen->pdev = choose_pdev(screen->instance); update_queue_props(screen); diff --git a/src/gallium/drivers/zink/zink_screen.h b/src/gallium/drivers/zink/zink_screen.h index 2e00a204d3f..39c7e146476 100644 --- a/src/gallium/drivers/zink/zink_screen.h +++ b/src/gallium/drivers/zink/zink_screen.h @@ -41,6 +41,7 @@ extern uint32_t zink_debug; #define ZINK_DEBUG_NIR 0x1 #define ZINK_DEBUG_SPIRV 0x2 #define ZINK_DEBUG_TGSI 0x4 +#define ZINK_DEBUG_VALIDATION 0x8 struct zink_screen { struct pipe_screen base; @@ -60,7 +61,9 @@ struct zink_screen { uint32_t gfx_queue; uint32_t timestamp_valid_bits; VkDevice dev; + VkDebugUtilsMessengerEXT debugUtilsCallbackHandle; + bool have_debug_utils_ext; #if defined(MVK_VERSION) bool have_moltenvk; #endif @@ -82,6 +85,9 @@ struct zink_screen { PFN_vkCmdSetViewportWithCountEXT vk_CmdSetViewportWithCountEXT; PFN_vkCmdSetScissorWithCountEXT vk_CmdSetScissorWithCountEXT; + PFN_vkCreateDebugUtilsMessengerEXT vk_CreateDebugUtilsMessengerEXT; + PFN_vkDestroyDebugUtilsMessengerEXT vk_DestroyDebugUtilsMessengerEXT; + #if defined(MVK_VERSION) PFN_vkGetMoltenVKConfigurationMVK vk_GetMoltenVKConfigurationMVK; PFN_vkSetMoltenVKConfigurationMVK vk_SetMoltenVKConfigurationMVK;