Disable unnecessary Khronos Validation Layer logs

The Khronos Validation Layer can often generate warning/error logs due to our intentional breakage from Vulkan specification, these can occur several times a frame resulting in the logs being spammed and making it difficult to extract useful information out of logs. The scope of these logs has now been reduced with more general filtering and the introduction of specialized filtering to handle complex cases such as BCn hacks with `libadrenotools` on Adreno devices.
This commit is contained in:
PixelyIon 2022-05-04 11:53:58 +05:30
parent 23c9388caf
commit 5d08d6e06f
3 changed files with 85 additions and 25 deletions

View File

@ -69,7 +69,7 @@ namespace skyline::gpu {
}); });
} }
static VkBool32 DebugCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char *layerPrefix, const char *message) { static VkBool32 DebugCallback(vk::DebugReportFlagsEXT flags, vk::DebugReportObjectTypeEXT objectType, u64 object, size_t location, i32 messageCode, const char *layerPrefix, const char *messageCStr, GPU *gpu) {
constexpr std::array<Logger::LogLevel, 5> severityLookup{ constexpr std::array<Logger::LogLevel, 5> severityLookup{
Logger::LogLevel::Info, // VK_DEBUG_REPORT_INFORMATION_BIT_EXT Logger::LogLevel::Info, // VK_DEBUG_REPORT_INFORMATION_BIT_EXT
Logger::LogLevel::Warn, // VK_DEBUG_REPORT_WARNING_BIT_EXT Logger::LogLevel::Warn, // VK_DEBUG_REPORT_WARNING_BIT_EXT
@ -78,33 +78,85 @@ namespace skyline::gpu {
Logger::LogLevel::Debug, // VK_DEBUG_REPORT_DEBUG_BIT_EXT Logger::LogLevel::Debug, // VK_DEBUG_REPORT_DEBUG_BIT_EXT
}; };
#define IGNORE_VALIDATION(string) \ #define IGNORE_VALIDATION_C(string, function) \
case util::Hash(string): \ case util::Hash(string): { \
if (string == type) \ if (string == type) { \
return VK_FALSE; \ function \
break } \
break; \
}
#define DEBUG_VALIDATION(string) \ #define IGNORE_VALIDATION_CL(string, functionName) IGNORE_VALIDATION_C(string, { if (!functionName()) return VK_FALSE; })
case util::Hash(string): \
if (string == type) \
raise(SIGTRAP); \
break
// Using __builtin_debugtrap() as opposed to raise(SIGTRAP) will result in the inability to continue
std::string_view type(message); #define IGNORE_VALIDATION(string) IGNORE_VALIDATION_C(string, { return VK_FALSE; })
#define DEBUG_VALIDATION(string) IGNORE_VALIDATION_C(string, { raise(SIGTRAP); }) // Using __builtin_debugtrap() as opposed to raise(SIGTRAP) will result in the inability to continue
std::string_view message{messageCStr};
std::string_view type{message};
auto first{type.find('[')}; auto first{type.find('[')};
auto last{type.find(']', first)}; auto last{type.find(']', first)};
if (first != std::string_view::npos && last != std::string_view::npos) { if (first != std::string_view::npos && last != std::string_view::npos) {
type = type.substr(first + 2, last != std::string_view::npos ? (last - first) - 3 : last); type = type.substr(first + 2, last != std::string_view::npos ? (last - first) - 3 : last);
auto returnIfBcn{[&] {
if (gpu->traits.hasPatchedBcn && message.find("VK_FORMAT_BC") != std::string_view::npos)
return false;
return true;
}};
switch (util::Hash(type)) { switch (util::Hash(type)) {
IGNORE_VALIDATION("UNASSIGNED-CoreValidation-SwapchainPreTransform"); // We handle transformation via Android APIs directly IGNORE_VALIDATION("UNASSIGNED-CoreValidation-SwapchainPreTransform") // We handle transformation via Android APIs directly
IGNORE_VALIDATION("UNASSIGNED-GeneralParameterPerfWarn-SuboptimalSwapchain"); // Same as SwapchainPreTransform IGNORE_VALIDATION("UNASSIGNED-GeneralParameterPerfWarn-SuboptimalSwapchain") // Same as SwapchainPreTransform
IGNORE_VALIDATION("UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout"); // We utilize images as VK_IMAGE_LAYOUT_GENERAL rather than optimal layouts for operations IGNORE_VALIDATION("UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout") // We utilize images as VK_IMAGE_LAYOUT_GENERAL rather than optimal layouts for operations
IGNORE_VALIDATION("VUID-VkImageViewCreateInfo-image-01762") // We allow aliasing of certain formats and handle warning in other cases ourselves
/* BCn format missing due to adrenotools */
IGNORE_VALIDATION_CL("VUID-VkImageCreateInfo-imageCreateMaxMipLevels-02251", returnIfBcn)
IGNORE_VALIDATION_CL("VUID-VkImageViewCreateInfo-None-02273", returnIfBcn)
IGNORE_VALIDATION_CL("VUID-vkCmdDraw-magFilter-04553", returnIfBcn)
IGNORE_VALIDATION_CL("VUID-vkCmdDrawIndexed-magFilter-04553", returnIfBcn)
IGNORE_VALIDATION_C("VUID-vkCmdCopyBufferToImage-dstImage-01997", {
if (!gpu->traits.hasPatchedBcn)
break;
constexpr std::string_view FormatTag{"format"}; // The format is provided as "format {}" where {} is the VkFormat value in numerical form
auto formatNumber{message.find_first_of("0123456789", message.find(FormatTag) + FormatTag.size())};
if (formatNumber != std::string_view::npos) {
switch (static_cast<vk::Format>(std::stoi(std::string{message.substr(formatNumber)}))) {
case vk::Format::eBc1RgbUnormBlock:
case vk::Format::eBc1RgbSrgbBlock:
case vk::Format::eBc1RgbaUnormBlock:
case vk::Format::eBc1RgbaSrgbBlock:
case vk::Format::eBc2UnormBlock:
case vk::Format::eBc2SrgbBlock:
case vk::Format::eBc3UnormBlock:
case vk::Format::eBc3SrgbBlock:
case vk::Format::eBc4UnormBlock:
case vk::Format::eBc4SnormBlock:
case vk::Format::eBc5UnormBlock:
case vk::Format::eBc5SnormBlock:
case vk::Format::eBc6HUfloatBlock:
case vk::Format::eBc6HSfloatBlock:
case vk::Format::eBc7UnormBlock:
case vk::Format::eBc7SrgbBlock:
return false;
default:
break;
}
}
})
/* Guest driven performance warnings, these cannot be fixed by us */
IGNORE_VALIDATION("UNASSIGNED-CoreValidation-Shader-OutputNotConsumed")
/* Pipeline Cache isn't compliant with the Vulkan specification, it depends on driver support for a relaxed version of Vulkan specification's Render Pass Compatibility clause and this will result in validation errors regardless which we need to ignore */ /* Pipeline Cache isn't compliant with the Vulkan specification, it depends on driver support for a relaxed version of Vulkan specification's Render Pass Compatibility clause and this will result in validation errors regardless which we need to ignore */
IGNORE_VALIDATION("VUID-vkCmdDrawIndexed-renderPass-02684"); IGNORE_VALIDATION("VUID-vkCmdDraw-renderPass-02684")
IGNORE_VALIDATION("VUID-vkCmdDrawIndexed-subpass-02685"); IGNORE_VALIDATION("VUID-vkCmdDraw-subpass-02685")
IGNORE_VALIDATION("VUID-vkCmdDrawIndexed-renderPass-02684")
IGNORE_VALIDATION("VUID-vkCmdDrawIndexed-subpass-02685")
} }
#undef IGNORE_TYPE #undef IGNORE_TYPE
@ -115,10 +167,11 @@ namespace skyline::gpu {
return VK_FALSE; return VK_FALSE;
} }
static vk::raii::DebugReportCallbackEXT CreateDebugReportCallback(const vk::raii::Instance &instance) { static vk::raii::DebugReportCallbackEXT CreateDebugReportCallback(GPU *gpu, const vk::raii::Instance &instance) {
return vk::raii::DebugReportCallbackEXT(instance, vk::DebugReportCallbackCreateInfoEXT{ return vk::raii::DebugReportCallbackEXT(instance, vk::DebugReportCallbackCreateInfoEXT{
.flags = vk::DebugReportFlagBitsEXT::eError | vk::DebugReportFlagBitsEXT::eWarning | vk::DebugReportFlagBitsEXT::ePerformanceWarning | vk::DebugReportFlagBitsEXT::eInformation | vk::DebugReportFlagBitsEXT::eDebug, .flags = vk::DebugReportFlagBitsEXT::eError | vk::DebugReportFlagBitsEXT::eWarning | vk::DebugReportFlagBitsEXT::ePerformanceWarning | vk::DebugReportFlagBitsEXT::eInformation | vk::DebugReportFlagBitsEXT::eDebug,
.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(&DebugCallback), .pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(&DebugCallback),
.pUserData = gpu,
}); });
} }
@ -241,21 +294,25 @@ namespace skyline::gpu {
static PFN_vkGetInstanceProcAddr LoadVulkanDriver(const DeviceState &state) { static PFN_vkGetInstanceProcAddr LoadVulkanDriver(const DeviceState &state) {
// Try turnip first, if not then fallback to regular with file redirect then plain dlopen // Try turnip first, if not then fallback to regular with file redirect then plain dlopen
auto libvulkanHandle{adrenotools_open_libvulkan(RTLD_NOW, auto libvulkanHandle{adrenotools_open_libvulkan(
RTLD_NOW,
ADRENOTOOLS_DRIVER_CUSTOM, ADRENOTOOLS_DRIVER_CUSTOM,
nullptr, // We require Android 10 so don't need to supply nullptr, // We require Android 10 so don't need to supply
state.os->nativeLibraryPath.c_str(), state.os->nativeLibraryPath.c_str(),
(state.os->publicAppFilesPath + "gpu/turnip/").c_str(), (state.os->publicAppFilesPath + "gpu/turnip/").c_str(),
"libvulkan_freedreno.so", "libvulkan_freedreno.so",
nullptr)}; nullptr
)};
if (!libvulkanHandle) { if (!libvulkanHandle) {
libvulkanHandle = adrenotools_open_libvulkan(RTLD_NOW, libvulkanHandle = adrenotools_open_libvulkan(
RTLD_NOW,
ADRENOTOOLS_DRIVER_FILE_REDIRECT, ADRENOTOOLS_DRIVER_FILE_REDIRECT,
nullptr, // We require Android 10 so don't need to supply nullptr, // We require Android 10 so don't need to supply
state.os->nativeLibraryPath.c_str(), state.os->nativeLibraryPath.c_str(),
nullptr, nullptr,
nullptr, nullptr,
(state.os->publicAppFilesPath + "gpu/vk_file_redirect/").c_str()); (state.os->publicAppFilesPath + "gpu/vk_file_redirect/").c_str()
);
if (!libvulkanHandle) if (!libvulkanHandle)
libvulkanHandle = dlopen("libvulkan.so", RTLD_NOW); libvulkanHandle = dlopen("libvulkan.so", RTLD_NOW);
} }
@ -263,12 +320,11 @@ namespace skyline::gpu {
return reinterpret_cast<PFN_vkGetInstanceProcAddr>(dlsym(libvulkanHandle, "vkGetInstanceProcAddr")); return reinterpret_cast<PFN_vkGetInstanceProcAddr>(dlsym(libvulkanHandle, "vkGetInstanceProcAddr"));
} }
GPU::GPU(const DeviceState &state) GPU::GPU(const DeviceState &state)
: state(state), : state(state),
vkContext(LoadVulkanDriver(state)), vkContext(LoadVulkanDriver(state)),
vkInstance(CreateInstance(state, vkContext)), vkInstance(CreateInstance(state, vkContext)),
vkDebugReportCallback(CreateDebugReportCallback(vkInstance)), vkDebugReportCallback(CreateDebugReportCallback(this, vkInstance)),
vkPhysicalDevice(CreatePhysicalDevice(vkInstance)), vkPhysicalDevice(CreatePhysicalDevice(vkInstance)),
vkDevice(CreateDevice(vkContext, vkPhysicalDevice, vkQueueFamilyIndex, traits)), vkDevice(CreateDevice(vkContext, vkPhysicalDevice, vkQueueFamilyIndex, traits)),
vkQueue(vkDevice, vkQueueFamilyIndex, 0), vkQueue(vkDevice, vkQueueFamilyIndex, 0),

View File

@ -210,6 +210,8 @@ namespace skyline::gpu {
Logger::Info("Applied BCeNabler patch"); Logger::Info("Applied BCeNabler patch");
else else
throw exception("Failed to apply BCeNabler patch!"); throw exception("Failed to apply BCeNabler patch!");
hasPatchedBcn = true;
} else if (type == ADRENOTOOLS_BCN_BLOB) { } else if (type == ADRENOTOOLS_BCN_BLOB) {
Logger::Info("BCeNabler skipped, blob BCN support is present"); Logger::Info("BCeNabler skipped, blob BCN support is present");
} }

View File

@ -40,6 +40,8 @@ namespace skyline::gpu {
bool supportsSubgroupVote{}; //!< If subgroup votes are supported in shaders with SPV_KHR_subgroup_vote bool supportsSubgroupVote{}; //!< If subgroup votes are supported in shaders with SPV_KHR_subgroup_vote
u32 subgroupSize{}; //!< Size of a subgroup on the host GPU u32 subgroupSize{}; //!< Size of a subgroup on the host GPU
bool hasPatchedBcn{}; //!< If the device has been patched to support BCN and may not report texture support correctly
/** /**
* @brief Manages a list of any vendor/device-specific errata in the host GPU * @brief Manages a list of any vendor/device-specific errata in the host GPU
*/ */