From 9600f99b1a22c19dc6fd8b6ca4cbee68653678ab Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Thu, 6 Nov 2025 14:39:39 -0400 Subject: [PATCH] Maintance for older driver statements and new handling on QCOM drivers --- .../vulkan_common/vulkan_device.cpp | 67 +++++++++++++++++-- src/video_core/vulkan_common/vulkan_device.h | 36 ++++++++-- 2 files changed, 92 insertions(+), 11 deletions(-) diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 1a94c50e38..1108578b6b 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -501,10 +501,25 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR } if ((is_qualcomm || is_turnip) && !force_extensions) { - LOG_WARNING(Render_Vulkan, - "Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color"); - RemoveExtensionFeature(extensions.custom_border_color, features.custom_border_color, - VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); + // Some Qualcomm/Turnip drivers have a broken implementation of + // VK_EXT_custom_border_color, but on certain devices the driver may + // still implement a subset of the extension's functions. If the + // driver reports any of the useful custom border color features, allow + // them; otherwise remove the extension to avoid crashes. + const bool has_custom_border_colors = + features.custom_border_color.customBorderColors || + features.custom_border_color.customBorderColorWithoutFormat; + if (!has_custom_border_colors) { + LOG_WARNING(Render_Vulkan, + "Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color"); + RemoveExtensionFeature(extensions.custom_border_color, features.custom_border_color, + VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); + } else { + LOG_INFO(Render_Vulkan, + "Partial VK_EXT_custom_border_color support detected on driver '{}'; enabling available features", + properties.driver.driverName); + // Keep extensions.custom_border_color set based on RemoveUnsuitableExtensions later. + } } if (is_qualcomm || is_arm) { @@ -1034,6 +1049,25 @@ bool Device::GetSuitability(bool requires_swapchain) { FOR_EACH_VK_FEATURE_EXT(FEATURE_EXTENSION); FOR_EACH_VK_EXTENSION(EXTENSION); + // Maintenance extensions may not have corresponding macros in older Vulkan + // headers. Detect them by name and enable them if present. + if (supported_extensions.contains("VK_KHR_maintenance1")) { + loaded_extensions.insert("VK_KHR_maintenance1"); + extensions.maintenance1 = true; + } + if (supported_extensions.contains("VK_KHR_maintenance2")) { + loaded_extensions.insert("VK_KHR_maintenance2"); + extensions.maintenance2 = true; + } + if (supported_extensions.contains("VK_KHR_maintenance3")) { + loaded_extensions.insert("VK_KHR_maintenance3"); + extensions.maintenance3 = true; + } + if (supported_extensions.contains("VK_KHR_maintenance4")) { + loaded_extensions.insert("VK_KHR_maintenance4"); + extensions.maintenance4 = true; + } + #undef FEATURE_EXTENSION #undef EXTENSION @@ -1254,9 +1288,30 @@ bool Device::GetSuitability(bool requires_swapchain) { } void Device::RemoveUnsuitableExtensions() { + // Restrict NV-specific extensions to NVIDIA drivers only. + if (!IsNvidia()) { + RemoveExtension(extensions.device_diagnostics_config, + VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME); + RemoveExtension(extensions.geometry_shader_passthrough, + VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME); + RemoveExtension(extensions.viewport_array2, VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME); + RemoveExtension(extensions.viewport_swizzle, VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME); + } + // VK_EXT_custom_border_color - extensions.custom_border_color = features.custom_border_color.customBorderColors && - features.custom_border_color.customBorderColorWithoutFormat; + // On most drivers we require both customBorderColors and + // customBorderColorWithoutFormat. However, some Qualcomm drivers expose a + // subset of the functionality; when running on Qualcomm, enable the + // extension if the driver reports any useful feature. + if (IsQualcomm()) { + extensions.custom_border_color = + features.custom_border_color.customBorderColors || + features.custom_border_color.customBorderColorWithoutFormat; + } else { + extensions.custom_border_color = + features.custom_border_color.customBorderColors && + features.custom_border_color.customBorderColorWithoutFormat; + } RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 9d5c4c4eae..cfc684ae07 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -445,6 +445,26 @@ public: return extensions.shader_float_controls; } + /// Returns true if VK_KHR_maintenance1 is enabled. + bool IsKhrMaintenance1Supported() const { + return extensions.maintenance1; + } + + /// Returns true if VK_KHR_maintenance2 is enabled. + bool IsKhrMaintenance2Supported() const { + return extensions.maintenance2; + } + + /// Returns true if VK_KHR_maintenance3 is enabled. + bool IsKhrMaintenance3Supported() const { + return extensions.maintenance3; + } + + /// Returns true if VK_KHR_maintenance4 is enabled. + bool IsKhrMaintenance4Supported() const { + return extensions.maintenance4; + } + /// Returns true if VK_KHR_sampler_mirror_clamp_to_edge is enabled. bool IsKhrSamplerMirrorClampToEdgeSupported() const { return extensions.sampler_mirror_clamp_to_edge; @@ -792,11 +812,17 @@ private: #define EXTENSION(prefix, macro_name, var_name) bool var_name{}; #define FEATURE(prefix, struct_name, macro_name, var_name) bool var_name{}; - FOR_EACH_VK_FEATURE_1_1(FEATURE); - FOR_EACH_VK_FEATURE_1_2(FEATURE); - FOR_EACH_VK_FEATURE_1_3(FEATURE); - FOR_EACH_VK_FEATURE_EXT(FEATURE); - FOR_EACH_VK_EXTENSION(EXTENSION); + FOR_EACH_VK_FEATURE_1_1(FEATURE); + FOR_EACH_VK_FEATURE_1_2(FEATURE); + FOR_EACH_VK_FEATURE_1_3(FEATURE); + FOR_EACH_VK_FEATURE_EXT(FEATURE); + FOR_EACH_VK_EXTENSION(EXTENSION); + + // Maintenance extensions (may not be present in older Vulkan headers). + bool maintenance1{}; + bool maintenance2{}; + bool maintenance3{}; + bool maintenance4{}; #undef EXTENSION #undef FEATURE