2017-12-13 19:29:42 +01:00
// 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 <string>
# include <sstream>
2022-12-22 23:07:42 +01:00
# include <map>
# include <mutex>
2017-12-13 19:29:42 +01:00
2020-08-15 12:25:39 +02:00
# include "Common/Log.h"
2020-10-04 23:24:14 +02:00
# include "Common/GPU/Vulkan/VulkanContext.h"
# include "Common/GPU/Vulkan/VulkanDebug.h"
2019-02-05 13:00:23 +01:00
2022-12-22 23:07:42 +01:00
const int MAX_SAME_ERROR_COUNT = 10 ;
// Used to stop outputting the same message over and over.
static std : : map < int , int > g_errorCount ;
std : : mutex g_errorCountMutex ;
// TODO: Call this when launching games in some clean way.
void VulkanClearValidationErrorCounts ( ) {
std : : lock_guard < std : : mutex > lock ( g_errorCountMutex ) ;
g_errorCount . clear ( ) ;
}
2020-06-21 23:13:05 +02:00
VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugUtilsCallback (
2019-02-05 13:00:23 +01:00
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity ,
VkDebugUtilsMessageTypeFlagsEXT messageType ,
2022-12-22 23:07:42 +01:00
const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData ,
void * pUserData ) {
2019-02-05 13:00:23 +01:00
const VulkanLogOptions * options = ( const VulkanLogOptions * ) pUserData ;
std : : ostringstream message ;
const char * pMessage = pCallbackData - > pMessage ;
2019-08-21 10:23:36 +02:00
2020-08-02 15:41:30 +02:00
int messageCode = pCallbackData - > messageIdNumber ;
2023-03-26 00:13:07 +01:00
switch ( messageCode ) {
case 101294395 :
2020-08-02 15:41:30 +02:00
// UNASSIGNED-CoreValidation-Shader-OutputNotConsumed - benign perf warning
2019-08-21 10:23:36 +02:00
return false ;
2023-03-26 00:13:07 +01:00
case 1303270965 :
2021-01-30 21:36:01 +01:00
// Benign perf warning, image blit using GENERAL layout.
2023-05-30 18:12:20 +02:00
// TODO: Oops, turns out we filtered out a bit too much here!
// We really need that performance flag check to sort out the stuff that matters.
// Will enable it soon, but it'll take some fixing.
//
2023-05-30 18:32:33 +02:00
if ( messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT )
2023-05-30 17:32:11 +02:00
return false ;
break ;
2023-03-26 00:13:07 +01:00
case 606910136 :
case - 392708513 :
case - 384083808 :
2022-11-07 09:14:55 +01:00
// VUID-vkCmdDraw-None-02686
2022-11-07 09:50:47 +01:00
// Kinda false positive, or at least very unnecessary, now that I solved the real issue.
// See https://github.com/hrydgard/ppsspp/pull/16354
2022-11-07 09:14:55 +01:00
return false ;
2023-03-26 00:13:07 +01:00
case - 375211665 :
2023-03-10 12:20:55 +01:00
// VUID-vkAllocateMemory-pAllocateInfo-01713
// Can happen when VMA aggressively tries to allocate aperture memory for upload. It gracefully
// falls back to regular video memory, so we just ignore this. I'd argue this is a VMA bug, actually.
return false ;
2023-03-26 00:13:07 +01:00
case 181611958 :
// Extended validation.
// UNASSIGNED-BestPractices-vkCreateDevice-deprecated-extension
// Doing what this one says doesn't seem very reliable - if I rely strictly on the Vulkan version, I don't get some function pointers? Like createrenderpass2.
return false ;
case 657182421 :
// Extended validation (ARM best practices)
// Non-fifo validation not recommended
return false ;
2023-08-01 18:04:44 +02:00
case 337425955 :
// False positive
// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/3615
return false ;
2023-03-26 00:13:07 +01:00
default :
break ;
2023-03-10 12:20:55 +01:00
}
2019-08-21 10:23:36 +02:00
2023-09-19 11:36:36 +02:00
/*
// Can be used to temporarily turn errors into info for easier debugging.
switch ( messageCode ) {
case 1544472022 :
if ( messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT ) {
messageSeverity = ( VkDebugUtilsMessageSeverityFlagBitsEXT ) ( ( messageSeverity & ~ VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT ) | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT ) ;
}
break ;
default :
break ;
}
*/
2022-12-22 23:07:42 +01:00
int count ;
{
std : : lock_guard < std : : mutex > lock ( g_errorCountMutex ) ;
count = g_errorCount [ messageCode ] + + ;
}
if ( count = = MAX_SAME_ERROR_COUNT ) {
WARN_LOG ( G3D , " Too many validation messages with message %d, stopping " , messageCode ) ;
}
if ( count > = MAX_SAME_ERROR_COUNT ) {
return false ;
}
2019-02-05 13:00:23 +01:00
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 " ;
}
2020-08-02 15:41:30 +02:00
message < < " : " < < messageCode < < " ) " < < pMessage < < " \n " ;
2019-02-05 13:00:23 +01:00
std : : string msg = message . str ( ) ;
2020-06-21 22:49:44 +02:00
# ifdef _WIN32
2019-02-05 13:00:23 +01:00
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 ) {
2019-02-07 14:56:29 +01:00
// Don't break on perf warnings for now, even with a debugger. We log them at least.
2019-02-05 13:00:23 +01:00
if ( options - > breakOnWarning & & IsDebuggerPresent ( ) & & 0 = = ( messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT ) ) {
DebugBreak ( ) ;
}
}
2020-08-27 21:07:54 +02:00
# endif
2020-06-21 22:49:44 +02:00
if ( messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT ) {
2020-08-15 12:25:39 +02:00
ERROR_LOG ( G3D , " VKDEBUG: %s " , msg . c_str ( ) ) ;
2020-06-21 22:49:44 +02:00
} else {
2020-08-15 12:25:39 +02:00
WARN_LOG ( G3D , " VKDEBUG: %s " , msg . c_str ( ) ) ;
2020-06-21 22:49:44 +02:00
}
2022-11-23 23:15:37 +01:00
2019-02-05 13:00:23 +01:00
// 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 ;
}