/* * 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 #include #include //#define RENDER_DOC namespace OpenVulkano::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; } #if VK_HEADER_VERSION > 303 VkBool32 ValidationLayerCallback(vk::DebugReportFlagsEXT flags, vk::DebugReportObjectTypeEXT 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::DebugReportFlagBitsEXT::eError) level = spdlog::level::err; else if (flags & vk::DebugReportFlagBitsEXT::eWarning) level = spdlog::level::warn; else if (flags & vk::DebugReportFlagBitsEXT::ePerformanceWarning) { level = spdlog::level::warn; prefix = "[PERF] " + prefix; } else if (flags & vk::DebugReportFlagBitsEXT::eDebug) level = spdlog::level::debug; Logger::RENDER->log(level, "{0} [{1}] Code {2}: {3}", prefix, layerPrefix, msgCode, msg); return false; } #else 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; } #endif namespace { vk::DebugReportCallbackEXT msgCallback; } void Debug::SetupValidationLayers(const vk::Instance& instance, const vk::DebugReportFlagsEXT& flags, vk::DispatchLoaderDynamic& dispatchLoaderDynamic) { Logger::RENDER->info("Setting up Vulkan Validation Layer"); vk::DebugReportCallbackCreateInfoEXT dbgCreateInfo = {}; dbgCreateInfo.pfnCallback = &ValidationLayerCallback; dbgCreateInfo.flags = flags; msgCallback = instance.createDebugReportCallbackEXT(dbgCreateInfo, nullptr, dispatchLoaderDynamic); Logger::RENDER->info("Vulkan Validation Layer setup"); } void Debug::CloseValidationLayers(const vk::Instance& instance, vk::DispatchLoaderDynamic& dispatchLoaderDynamic) { instance.destroyDebugReportCallbackEXT(msgCallback, nullptr, dispatchLoaderDynamic); } }