/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "ValidationLayer.hpp" #include "Base/Logger.hpp" #include #define RENDER_DOC namespace openVulkanoCpp::Vulkan { const std::initializer_list activeValidationLayerNames = { "VK_LAYER_LUNARG_assistant_layer", "VK_LAYER_LUNARG_standard_validation", "VK_LAYER_KHRONOS_validation", //"VK_EXT_debug_marker", #ifdef RENDER_DOC "VK_LAYER_RENDERDOC_Capture", // RenderDoc must be open for this layer to work! #endif }; std::set Debug::GetAvailableValidationLayers() { static std::set availableLayers; if (availableLayers.empty()) { auto layers = vk::enumerateInstanceLayerProperties(); for (const auto& layer: layers) { availableLayers.insert(layer.layerName.data()); } Logger::RENDER->debug("Available Vulkan Validation Layers: {0}", fmt::join(availableLayers, ", ")); } return availableLayers; } std::vector Debug::GetValidationLayers() { std::set availableLayers = GetAvailableValidationLayers(); std::vector layers; for (const auto& name : activeValidationLayerNames) { if (availableLayers.count(name) != 0) { layers.push_back(name.c_str()); } } Logger::RENDER->debug("Active Vulkan Validation Layers: {0}", fmt::join(layers, ", ")); return layers; } VkBool32 ValidationLayerCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* layerPrefix, const char* msg, void* pUserData) { std::string prefix = "VK_DEBUG:"; spdlog::level::level_enum level = spdlog::level::info; if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) level = spdlog::level::err; else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) level = spdlog::level::warn; else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) { level = spdlog::level::warn; prefix = "[PERF] " + prefix; } else if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) level = spdlog::level::debug; Logger::RENDER->log(level, "{0} [{1}] Code {2}: {3}", prefix, layerPrefix, msgCode, msg); return false; } static std::once_flag dispatcherInitFlag; vk::DispatchLoaderDynamic dispatcher; vk::DebugReportCallbackEXT msgCallback; void Debug::SetupValidationLayers(const vk::Instance& instance, const vk::DebugReportFlagsEXT& flags) { Logger::RENDER->info("Setting up Vulkan Validation Layer"); std::call_once(dispatcherInitFlag, [&] { dispatcher.init(instance, &vkGetInstanceProcAddr); }); vk::DebugReportCallbackCreateInfoEXT dbgCreateInfo = {}; dbgCreateInfo.pfnCallback = (PFN_vkDebugReportCallbackEXT)ValidationLayerCallback; dbgCreateInfo.flags = flags; msgCallback = instance.createDebugReportCallbackEXT(dbgCreateInfo, nullptr, dispatcher); Logger::RENDER->info("Vulkan Validation Layer setup"); } void Debug::CloseValidationLayers(const vk::Instance& instance) { std::call_once(dispatcherInitFlag, [&] { dispatcher.init(instance, &vkGetInstanceProcAddr); }); instance.destroyDebugReportCallbackEXT(msgCallback, nullptr, dispatcher); } }