From e62405e56e4b9843bac229e0f9abd9b49f14eb66 Mon Sep 17 00:00:00 2001 From: tpoisonooo Date: Tue, 22 Mar 2022 16:29:45 +0800 Subject: [PATCH] feat(uvkc/vulkan): add validation_layer --- uvkc/vulkan/driver.cc | 85 +++++++++++++++++++++++++++-- uvkc/vulkan/driver.h | 16 +++++- uvkc/vulkan/dynamic_symbol_tables.h | 6 +- 3 files changed, 98 insertions(+), 9 deletions(-) diff --git a/uvkc/vulkan/driver.cc b/uvkc/vulkan/driver.cc index e1e2839..c20cb1e 100644 --- a/uvkc/vulkan/driver.cc +++ b/uvkc/vulkan/driver.cc @@ -74,30 +74,105 @@ absl::StatusOr SelectQueueFamily(VkPhysicalDevice physical_device, } // namespace +void Driver::PopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) { + createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + createInfo.pfnUserCallback = debugCallback; +} + +bool Driver::CheckValidationLayerSupport(DynamicSymbols *symbols) { + uint32_t layerCount; + symbols->vkEnumerateInstanceLayerProperties(&layerCount, nullptr); + + std::vector availableLayers(layerCount); + symbols->vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); + + const std::vector validationLayers = { + "VK_LAYER_KHRONOS_validation" + }; + for (const char* layerName : validationLayers) { + bool layerFound = false; + + for (const auto& layerProperties : availableLayers) { + if (strcmp(layerName, layerProperties.layerName) == 0) { + layerFound = true; + break; + } + } + + if (!layerFound) { + return false; + } + } + + return true; +} + absl::StatusOr> Driver::Create( const char *app_name, DynamicSymbols *symbols) { auto app_info = GetDefaultApplicationInfo(app_name); VkInstanceCreateInfo create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - create_info.pNext = nullptr; create_info.flags = 0; create_info.pApplicationInfo = &app_info; + +#define DEBUG (1) +#if DEBUG + const bool support_validation = CheckValidationLayerSupport(symbols); + if (not support_validation) { + fprintf(stderr, "validation layers requested, but not available!\n"); + } else { + std::vector applicationExtensions = {VK_EXT_DEBUG_REPORT_EXTENSION_NAME}; + create_info.enabledExtensionCount = static_cast(applicationExtensions.size()); + create_info.ppEnabledExtensionNames = applicationExtensions.data(); + + std::vector validLayerNames = { + "VK_LAYER_LUNARG_assistant_layer", + "VK_LAYER_LUNARG_standard_validation", + "VK_LAYER_KHRONOS_validation", + }; + create_info.enabledLayerCount = static_cast(validLayerNames.size()); + create_info.ppEnabledLayerNames = validLayerNames.data(); + + VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; + PopulateDebugMessengerCreateInfo(debugCreateInfo); + create_info.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo; + } +#else create_info.enabledLayerCount = 0; - create_info.ppEnabledExtensionNames = nullptr; + // create_info.ppEnabledLayerNames = nullptr; create_info.enabledExtensionCount = 0; create_info.ppEnabledExtensionNames = nullptr; + create_info.pNext = nullptr; +#endif VkInstance instance = VK_NULL_HANDLE; VK_RETURN_IF_ERROR(symbols->vkCreateInstance( &create_info, /*pAllocator=*/nullptr, &instance)); + VkDebugUtilsMessengerEXT messenger; +#if DEBUG + if (support_validation) { + VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; + PopulateDebugMessengerCreateInfo(debugCreateInfo); + if (symbols->vkCreateDebugUtilsMessengerEXT(instance, &debugCreateInfo, /*pAllocator=*/nullptr, &messenger) != VK_SUCCESS) { + throw std::runtime_error("failed to set up debug messenger!"); + } + } +#endif + UVKC_RETURN_IF_ERROR(symbols->LoadFromInstance(instance)); - return absl::WrapUnique(new Driver(instance, *symbols)); + return absl::WrapUnique(new Driver(instance, *symbols, messenger)); } Driver::~Driver() { +#if DEBUG + symbols_.vkDestroyDebugUtilsMessengerEXT(instance_, messenger_, /*pAllocator=*/nullptr); +#endif symbols_.vkDestroyInstance(instance_, /*pAllocator=*/nullptr); } @@ -171,8 +246,8 @@ absl::StatusOr> Driver::CreateDevice( physical_device.v10_properties.limits.timestampPeriod, device, symbols_); } -Driver::Driver(VkInstance instance, const DynamicSymbols &symbols) - : instance_(instance), symbols_(symbols) {} +Driver::Driver(VkInstance instance, const DynamicSymbols &symbols, VkDebugUtilsMessengerEXT messenger) + : instance_(instance), symbols_(symbols), messenger_(messenger){} } // namespace vulkan } // namespace uvkc diff --git a/uvkc/vulkan/driver.h b/uvkc/vulkan/driver.h index 79c7bf7..faf7593 100644 --- a/uvkc/vulkan/driver.h +++ b/uvkc/vulkan/driver.h @@ -27,6 +27,16 @@ namespace uvkc { namespace vulkan { +static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData) { + + std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl; + + return VK_FALSE; +} // A class representing a Vulkan driver. // // This class is the beginning of all interaction with the Vulkan system. It @@ -37,6 +47,8 @@ class Driver { // Creates a Vulkan driver for an application with the given |app_name|. static absl::StatusOr> Create( const char *app_name, DynamicSymbols *symbols); + static bool CheckValidationLayerSupport(DynamicSymbols *symbols); + static void PopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo); ~Driver(); @@ -55,11 +67,13 @@ class Driver { const PhysicalDeviceInfo &physical_device, VkQueueFlags queue_flags); private: - explicit Driver(VkInstance instance, const DynamicSymbols &symbols); + explicit Driver(VkInstance instance, const DynamicSymbols &symbols, VkDebugUtilsMessengerEXT messenger); VkInstance instance_; const DynamicSymbols &symbols_; + + VkDebugUtilsMessengerEXT messenger_; }; } // namespace vulkan diff --git a/uvkc/vulkan/dynamic_symbol_tables.h b/uvkc/vulkan/dynamic_symbol_tables.h index 564b391..906037e 100644 --- a/uvkc/vulkan/dynamic_symbol_tables.h +++ b/uvkc/vulkan/dynamic_symbol_tables.h @@ -42,7 +42,7 @@ namespace vulkan { #define UVKC_VULKAN_DYNAMIC_SYMBOL_INSTANCELESS_TABLE(INS_PFN) \ INS_PFN(REQUIRED, vkCreateInstance) \ INS_PFN(EXCLUDED, vkEnumerateInstanceExtensionProperties) \ - INS_PFN(EXCLUDED, vkEnumerateInstanceLayerProperties) \ + INS_PFN(REQUIRED, vkEnumerateInstanceLayerProperties) \ INS_PFN(OPTIONAL, vkEnumerateInstanceVersion) // Defines the list of instance/device symbols that are queried from @@ -300,12 +300,12 @@ namespace vulkan { DEV_PFN(EXCLUDED, vkSignalSemaphoreKHR) \ \ INS_PFN(EXCLUDED, vkCreateDebugReportCallbackEXT) \ - INS_PFN(EXCLUDED, vkCreateDebugUtilsMessengerEXT) \ + INS_PFN(REQUIRED, vkCreateDebugUtilsMessengerEXT) \ INS_PFN(EXCLUDED, vkCreateDisplayPlaneSurfaceKHR) \ INS_PFN(EXCLUDED, vkCreateHeadlessSurfaceEXT) \ INS_PFN(EXCLUDED, vkDebugReportMessageEXT) \ INS_PFN(EXCLUDED, vkDestroyDebugReportCallbackEXT) \ - INS_PFN(EXCLUDED, vkDestroyDebugUtilsMessengerEXT) \ + INS_PFN(REQUIRED, vkDestroyDebugUtilsMessengerEXT) \ INS_PFN(REQUIRED, vkDestroyInstance) \ INS_PFN(EXCLUDED, vkDestroySurfaceKHR) \ INS_PFN(EXCLUDED, vkEnumeratePhysicalDeviceGroups) \