diff --git a/app/src/main/cpp/skyline/gpu.cpp b/app/src/main/cpp/skyline/gpu.cpp index 19cdfa55..31b81cd2 100644 --- a/app/src/main/cpp/skyline/gpu.cpp +++ b/app/src/main/cpp/skyline/gpu.cpp @@ -100,9 +100,69 @@ namespace skyline::gpu { 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); - auto returnIfBcn{[&] { - if (gpu->traits.hasPatchedBcn && message.find("VK_FORMAT_BC") != std::string_view::npos) - return false; + auto &traits{gpu->traits.quirks}; + + auto returnIfBrokenFormat1{[&] { + if (!traits.adrenoRelaxedFormatAliasing) + return true; + + constexpr std::string_view FormatTag{"VK_FORMAT_"}; + auto start{message.find(FormatTag)}, end{message.find(' ', start)}; + if (start == std::string_view::npos || end == std::string_view::npos) + return true; + + std::string_view formatName{message.data() + start + FormatTag.length(), message.data() + end}; + if (formatName.ends_with(')')) + formatName.remove_suffix(1); + + if (formatName.starts_with("BC") && formatName.ends_with("_BLOCK")) + return false; // BCn formats + + #define FMT(name) if (formatName == name) return false + + FMT("B5G6R5_UNORM_PACK16"); + FMT("R5G6B5_UNORM_PACK16"); + + #undef FMT + + return true; + }}; + + auto returnIfBrokenFormat2{[&] { + if (!traits.adrenoRelaxedFormatAliasing) + return true; + + 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) { + auto format{static_cast(std::stoi(std::string{message.substr(formatNumber)}))}; + switch (format) { + case vk::Format::eR5G6B5UnormPack16: + case vk::Format::eB5G6R5UnormPack16: + + 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: + return true; + } + } + return true; }}; @@ -113,43 +173,16 @@ namespace skyline::gpu { 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(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; - } - } - }) + IGNORE_VALIDATION_CL("VUID-VkImageCreateInfo-imageCreateMaxMipLevels-02251", returnIfBrokenFormat1) + IGNORE_VALIDATION_CL("VUID-VkImageViewCreateInfo-None-02273", returnIfBrokenFormat1) + IGNORE_VALIDATION_CL("VUID-VkImageViewCreateInfo-usage-02274", returnIfBrokenFormat1) + IGNORE_VALIDATION_CL("VUID-vkCmdDraw-magFilter-04553", returnIfBrokenFormat1) + IGNORE_VALIDATION_CL("VUID-vkCmdDrawIndexed-magFilter-04553", returnIfBrokenFormat1) + IGNORE_VALIDATION_CL("VUID-vkCmdCopyImageToBuffer-srcImage-01998", returnIfBrokenFormat2) + IGNORE_VALIDATION_CL("VUID-vkCmdCopyBufferToImage-dstImage-01997", returnIfBrokenFormat2) /* Guest driven performance warnings, these cannot be fixed by us */ + IGNORE_VALIDATION("UNASSIGNED-CoreValidation-Shader-InputNotProduced") 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 */ diff --git a/app/src/main/cpp/skyline/gpu/trait_manager.cpp b/app/src/main/cpp/skyline/gpu/trait_manager.cpp index ecec9604..992e08e0 100644 --- a/app/src/main/cpp/skyline/gpu/trait_manager.cpp +++ b/app/src/main/cpp/skyline/gpu/trait_manager.cpp @@ -150,6 +150,7 @@ namespace skyline::gpu { needsIndividualTextureBindingWrites = true; vkImageMutableFormatCostly = true; // Disables UBWC adrenoRelaxedFormatAliasing = true; + adrenoBrokenFormatReport = true; brokenDescriptorAliasing = true; relaxedRenderPassCompatibility = true; // Adreno drivers support relaxed render pass compatibility rules @@ -187,8 +188,8 @@ namespace skyline::gpu { std::string TraitManager::QuirkManager::Summary() { return fmt::format( - "\n* Needs Individual Texture Binding Writes: {}\n* VkImage Mutable Format is costly: {}\n* Adreno Relaxed Format Aliasing: {}\n* Broken Descriptor Aliasing: {}\n* Relaxed Render Pass Compatibility: {}\n* Max Subpass Count: {}\n* Max Global Queue Priority: {}", - needsIndividualTextureBindingWrites, vkImageMutableFormatCostly, adrenoRelaxedFormatAliasing, brokenDescriptorAliasing, relaxedRenderPassCompatibility, maxSubpassCount, vk::to_string(maxGlobalPriority) + "\n* Needs Individual Texture Binding Writes: {}\n* VkImage Mutable Format is costly: {}\n* Adreno Relaxed Format Aliasing: {}\n* Adreno Broken Format Reporting: {}\n* Broken Descriptor Aliasing: {}\n* Relaxed Render Pass Compatibility: {}\n* Max Subpass Count: {}\n* Max Global Queue Priority: {}", + needsIndividualTextureBindingWrites, vkImageMutableFormatCostly, adrenoRelaxedFormatAliasing, adrenoBrokenFormatReport, brokenDescriptorAliasing, relaxedRenderPassCompatibility, maxSubpassCount, vk::to_string(maxGlobalPriority) ); } @@ -212,8 +213,6 @@ namespace skyline::gpu { Logger::Info("Applied BCeNabler patch"); else throw exception("Failed to apply BCeNabler patch!"); - - hasPatchedBcn = true; } else if (type == ADRENOTOOLS_BCN_BLOB) { Logger::Info("BCeNabler skipped, blob BCN support is present"); } diff --git a/app/src/main/cpp/skyline/gpu/trait_manager.h b/app/src/main/cpp/skyline/gpu/trait_manager.h index 7ed1cee6..4eb821a2 100644 --- a/app/src/main/cpp/skyline/gpu/trait_manager.h +++ b/app/src/main/cpp/skyline/gpu/trait_manager.h @@ -40,8 +40,6 @@ namespace skyline::gpu { bool supportsSubgroupVote{}; //!< If subgroup votes are supported in shaders with SPV_KHR_subgroup_vote 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 */ @@ -49,6 +47,7 @@ namespace skyline::gpu { bool needsIndividualTextureBindingWrites{}; //!< [Adreno Proprietary] A bug that requires descriptor set writes for VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER to be done individually with descriptorCount = 1 rather than batched bool vkImageMutableFormatCostly{}; //!< [Adreno Proprietary/Freedreno] An indication that VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT is costly and should not be enabled unless absolutely necessary (Disables UBWC on Adreno GPUs) bool adrenoRelaxedFormatAliasing{}; //!< [Adreno Proprietary/Freedreno] An indication that the GPU supports a relaxed version of view format aliasing without needing VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, this is designed to work in tandem with 'vkImageMutableFormatCostly' + bool adrenoBrokenFormatReport{}; //!< [Adreno Proprietary] If the drivers report format support incorrectly and include cases that are supported by the hardware bool brokenDescriptorAliasing{}; //!< [Adreno Proprietary] A bug that causes alised descriptor sets to be incorrectly interpreted by the shader compiler leading to it buggering up LLVM function argument types and crashing bool relaxedRenderPassCompatibility{}; //!< [Adreno Proprietary/Freedreno] A relaxed version of Vulkan specification's render pass compatibility clause which allows for caching pipeline objects for multi-subpass renderpasses, this is intentionally disabled by default as it requires testing prior to enabling @@ -57,7 +56,7 @@ namespace skyline::gpu { QuirkManager() = default; - QuirkManager(const vk::PhysicalDeviceProperties& deviceProperties, const vk::PhysicalDeviceDriverProperties& driverProperties); + QuirkManager(const vk::PhysicalDeviceProperties &deviceProperties, const vk::PhysicalDeviceDriverProperties &driverProperties); /** * @return A summary of all the GPU quirks as a human-readable string