// Copyright (c) 2016- PPSSPP Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, version 2.0 or later versions. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License 2.0 for more details. // A copy of the GPL 2.0 should have been included with the program. // If not, see http://www.gnu.org/licenses/ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include #include #include #include "Common/Vulkan/VulkanContext.h" #include "Common/Vulkan/VulkanDebug.h" #include "base/logging.h" VkBool32 VKAPI_CALL VulkanDebugReportCallback(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void *pUserData) { const VulkanLogOptions *options = (const VulkanLogOptions *)pUserData; std::ostringstream message; if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { message << "ERROR: "; } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { message << "WARNING: "; } else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) { message << "PERFORMANCE WARNING: "; } else if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) { message << "INFO: "; } else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) { message << "DEBUG: "; } message << "[" << pLayerPrefix << "] " << VulkanObjTypeToString(objType) << " Code " << msgCode << " : " << pMsg << "\n"; if (msgCode == 64) // Another useless perf warning that will be seen less and less as we optimize - vkCmdClearAttachments() issued on command buffer object 0x00000195296C6D40 prior to any Draw Cmds. It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw. return false; if (msgCode == 5) return false; // Not exactly a false positive, see https://github.com/KhronosGroup/glslang/issues/1418 #ifdef _WIN32 std::string msg = message.str(); OutputDebugStringA(msg.c_str()); if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { if (options->breakOnError && IsDebuggerPresent()) { DebugBreak(); } if (options->msgBoxOnError) { MessageBoxA(NULL, message.str().c_str(), "Alert", MB_OK); } } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { if (options->breakOnWarning && IsDebuggerPresent()) { DebugBreak(); } } #else ILOG("%s", message.str().c_str()); #endif // false indicates that layer should not bail-out of an // API call that had validation failures. This may mean that the // app dies inside the driver due to invalid parameter(s). // That's what would happen without validation layers, so we'll // keep that behavior here. return false; } VkBool32 VKAPI_CALL VulkanDebugUtilsCallback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) { const VulkanLogOptions *options = (const VulkanLogOptions *)pUserData; std::ostringstream message; const char *pMessage = pCallbackData->pMessage; // Apparent bugs around timestamp validation in the validation layers if (strstr(pMessage, "vkCmdBeginQuery(): VkQueryPool")) return false; if (strstr(pMessage, "vkGetQueryPoolResults() on VkQueryPool")) return false; int messageCode = pCallbackData->messageIdNumber; const char *pLayerPrefix = ""; if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { message << "ERROR("; } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { message << "WARNING("; } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) { message << "INFO("; } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) { message << "VERBOSE("; } if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) { message << "perf"; } else if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) { message << "general"; } else if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) { message << "validation"; } message << ":" << pCallbackData->messageIdNumber << ") " << pMessage << "\n"; #ifdef _WIN32 std::string msg = message.str(); OutputDebugStringA(msg.c_str()); if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { if (options->breakOnError && IsDebuggerPresent()) { DebugBreak(); } if (options->msgBoxOnError) { MessageBoxA(NULL, pMessage, "Alert", MB_OK); } } else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { // Don't break on perf warnings for now, even with a debugger. We log them at least. if (options->breakOnWarning && IsDebuggerPresent() && 0 == (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) { DebugBreak(); } } #endif // false indicates that layer should not bail-out of an // API call that had validation failures. This may mean that the // app dies inside the driver due to invalid parameter(s). // That's what would happen without validation layers, so we'll // keep that behavior here. return false; }