diff options
Diffstat (limited to 'src/video_core/vulkan_common')
-rw-r--r-- | src/video_core/vulkan_common/vulkan_debug_callback.cpp | 28 | ||||
-rw-r--r-- | src/video_core/vulkan_common/vulkan_device.cpp | 103 | ||||
-rw-r--r-- | src/video_core/vulkan_common/vulkan_device.h | 14 | ||||
-rw-r--r-- | src/video_core/vulkan_common/vulkan_library.cpp | 18 | ||||
-rw-r--r-- | src/video_core/vulkan_common/vulkan_library.h | 6 |
5 files changed, 155 insertions, 14 deletions
diff --git a/src/video_core/vulkan_common/vulkan_debug_callback.cpp b/src/video_core/vulkan_common/vulkan_debug_callback.cpp index 10a001b8f..9de484c29 100644 --- a/src/video_core/vulkan_common/vulkan_debug_callback.cpp +++ b/src/video_core/vulkan_common/vulkan_debug_callback.cpp @@ -13,11 +13,39 @@ VkBool32 Callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, [[maybe_unused]] void* user_data) { // Skip logging known false-positive validation errors switch (static_cast<u32>(data->messageIdNumber)) { +#ifdef ANDROID + case 0xbf9cf353u: // VUID-vkCmdBindVertexBuffers2-pBuffers-04111 + // The below are due to incorrect reporting of extendedDynamicState + case 0x1093bebbu: // VUID-vkCmdSetCullMode-None-03384 + case 0x9215850fu: // VUID-vkCmdSetDepthTestEnable-None-03352 + case 0x86bf18dcu: // VUID-vkCmdSetDepthWriteEnable-None-03354 + case 0x0792ad08u: // VUID-vkCmdSetStencilOp-None-03351 + case 0x93e1ba4eu: // VUID-vkCmdSetFrontFace-None-03383 + case 0xac9c13c5u: // VUID-vkCmdSetStencilTestEnable-None-03350 + case 0xc9a2001bu: // VUID-vkCmdSetDepthBoundsTestEnable-None-03349 + case 0x8b7159a7u: // VUID-vkCmdSetDepthCompareOp-None-03353 + // The below are due to incorrect reporting of extendedDynamicState2 + case 0xb13c8036u: // VUID-vkCmdSetDepthBiasEnable-None-04872 + case 0xdff2e5c1u: // VUID-vkCmdSetRasterizerDiscardEnable-None-04871 + case 0x0cc85f41u: // VUID-vkCmdSetPrimitiveRestartEnable-None-04866 + case 0x01257b492: // VUID-vkCmdSetLogicOpEXT-None-0486 + // The below are due to incorrect reporting of vertexInputDynamicState + case 0x398e0dabu: // VUID-vkCmdSetVertexInputEXT-None-04790 + // The below are due to incorrect reporting of extendedDynamicState3 + case 0x970c11a5u: // VUID-vkCmdSetColorWriteMaskEXT-extendedDynamicState3ColorWriteMask-07364 + case 0x6b453f78u: // VUID-vkCmdSetColorBlendEnableEXT-extendedDynamicState3ColorBlendEnable-07355 + case 0xf66469d0u: // VUID-vkCmdSetColorBlendEquationEXT-extendedDynamicState3ColorBlendEquation-07356 + case 0x1d43405eu: // VUID-vkCmdSetLogicOpEnableEXT-extendedDynamicState3LogicOpEnable-07365 + case 0x638462e8u: // VUID-vkCmdSetDepthClampEnableEXT-extendedDynamicState3DepthClampEnable-07448 + // Misc + case 0xe0a2da61u: // VUID-vkCmdDrawIndexed-format-07753 +#else case 0x682a878au: // VUID-vkCmdBindVertexBuffers2EXT-pBuffers-parameter case 0x99fb7dfdu: // UNASSIGNED-RequiredParameter (vkCmdBindVertexBuffers2EXT pBuffers[0]) case 0xe8616bf2u: // Bound VkDescriptorSet 0x0[] was destroyed. Likely push_descriptor related case 0x1608dec0u: // Image layout in vkUpdateDescriptorSet doesn't match descriptor use case 0x55362756u: // Descriptor binding and framebuffer attachment overlap +#endif return VK_FALSE; default: break; diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index aea677cb3..0158b6b0d 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -18,6 +18,10 @@ #include "video_core/vulkan_common/vulkan_device.h" #include "video_core/vulkan_common/vulkan_wrapper.h" +#if defined(ANDROID) && defined(ARCHITECTURE_arm64) +#include <adrenotools/bcenabler.h> +#endif + namespace Vulkan { using namespace Common::Literals; namespace { @@ -262,6 +266,32 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(vk::Physica return format_properties; } +#if defined(ANDROID) && defined(ARCHITECTURE_arm64) +void OverrideBcnFormats(std::unordered_map<VkFormat, VkFormatProperties>& format_properties) { + // These properties are extracted from Adreno driver 512.687.0 + constexpr VkFormatFeatureFlags tiling_features{ + VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | + VK_FORMAT_FEATURE_TRANSFER_DST_BIT}; + + constexpr VkFormatFeatureFlags buffer_features{VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT}; + + static constexpr std::array bcn_formats{ + VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_FORMAT_BC1_RGBA_UNORM_BLOCK, VK_FORMAT_BC2_SRGB_BLOCK, + VK_FORMAT_BC2_UNORM_BLOCK, VK_FORMAT_BC3_SRGB_BLOCK, VK_FORMAT_BC3_UNORM_BLOCK, + VK_FORMAT_BC4_SNORM_BLOCK, VK_FORMAT_BC4_UNORM_BLOCK, VK_FORMAT_BC5_SNORM_BLOCK, + VK_FORMAT_BC5_UNORM_BLOCK, VK_FORMAT_BC6H_SFLOAT_BLOCK, VK_FORMAT_BC6H_UFLOAT_BLOCK, + VK_FORMAT_BC7_SRGB_BLOCK, VK_FORMAT_BC7_UNORM_BLOCK, + }; + + for (const auto format : bcn_formats) { + format_properties[format].linearTilingFeatures = tiling_features; + format_properties[format].optimalTilingFeatures = tiling_features; + format_properties[format].bufferFeatures = buffer_features; + } +} +#endif + NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical, const std::set<std::string, std::less<>>& exts) { if (exts.contains(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) { @@ -302,6 +332,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR const bool is_suitable = GetSuitability(surface != nullptr); const VkDriverId driver_id = properties.driver.driverID; + const auto device_id = properties.properties.deviceID; const bool is_radv = driver_id == VK_DRIVER_ID_MESA_RADV; const bool is_amd_driver = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE; @@ -310,9 +341,12 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR const bool is_intel_anv = driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA; const bool is_nvidia = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY; const bool is_mvk = driver_id == VK_DRIVER_ID_MOLTENVK; + const bool is_qualcomm = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY; + const bool is_turnip = driver_id == VK_DRIVER_ID_MESA_TURNIP; + const bool is_s8gen2 = device_id == 0x43050a01; - if (is_mvk && !is_suitable) { - LOG_WARNING(Render_Vulkan, "Unsuitable driver is MoltenVK, continuing anyway"); + if ((is_mvk || is_qualcomm || is_turnip) && !is_suitable) { + LOG_WARNING(Render_Vulkan, "Unsuitable driver, continuing anyway"); } else if (!is_suitable) { throw vk::Exception(VK_ERROR_INCOMPATIBLE_DRIVER); } @@ -355,6 +389,59 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR CollectPhysicalMemoryInfo(); CollectToolingInfo(); +#ifdef ANDROID + if (is_qualcomm || is_turnip) { + LOG_WARNING(Render_Vulkan, + "Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color"); + extensions.custom_border_color = false; + loaded_extensions.erase(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); + } + + if (is_qualcomm) { + must_emulate_scaled_formats = true; + + LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken VK_EXT_extended_dynamic_state"); + extensions.extended_dynamic_state = false; + loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); + + LOG_WARNING(Render_Vulkan, + "Qualcomm drivers have a slow VK_KHR_push_descriptor implementation"); + extensions.push_descriptor = false; + loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); + +#ifdef ARCHITECTURE_arm64 + // Patch the driver to enable BCn textures. + const auto major = (properties.properties.driverVersion >> 24) << 2; + const auto minor = (properties.properties.driverVersion >> 12) & 0xFFFU; + const auto vendor = properties.properties.vendorID; + const auto patch_status = adrenotools_get_bcn_type(major, minor, vendor); + + if (patch_status == ADRENOTOOLS_BCN_PATCH) { + LOG_INFO(Render_Vulkan, "Patching Adreno driver to support BCn texture formats"); + if (adrenotools_patch_bcn( + reinterpret_cast<void*>(dld.vkGetPhysicalDeviceFormatProperties))) { + OverrideBcnFormats(format_properties); + } else { + LOG_ERROR(Render_Vulkan, "Patch failed! Driver code may now crash"); + } + } else if (patch_status == ADRENOTOOLS_BCN_BLOB) { + LOG_INFO(Render_Vulkan, "Adreno driver supports BCn textures without patches"); + } else { + LOG_WARNING(Render_Vulkan, "Adreno driver can't be patched to enable BCn textures"); + } +#endif // ARCHITECTURE_arm64 + } + + const bool is_arm = driver_id == VK_DRIVER_ID_ARM_PROPRIETARY; + if (is_arm) { + must_emulate_scaled_formats = true; + + LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state"); + extensions.extended_dynamic_state = false; + loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); + } +#endif // ANDROID + if (is_nvidia) { const u32 nv_major_version = (properties.properties.driverVersion >> 22) & 0x3ff; const auto arch = GetNvidiaArchitecture(physical, supported_extensions); @@ -388,7 +475,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); } } - if (extensions.extended_dynamic_state2 && is_radv) { + if (extensions.extended_dynamic_state2 && (is_radv || is_qualcomm)) { const u32 version = (properties.properties.driverVersion << 3) >> 3; if (version < VK_MAKE_API_VERSION(0, 22, 3, 1)) { LOG_WARNING( @@ -415,7 +502,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR dynamic_state3_enables = false; } } - if (extensions.vertex_input_dynamic_state && is_radv) { + if (extensions.vertex_input_dynamic_state && (is_radv || is_qualcomm)) { + // Qualcomm S8gen2 drivers do not properly support vertex_input_dynamic_state. // TODO(ameerj): Blacklist only offending driver versions // TODO(ameerj): Confirm if RDNA1 is affected const bool is_rdna2 = @@ -467,8 +555,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR LOG_WARNING(Render_Vulkan, "Intel proprietary drivers do not support MSAA image blits"); cant_blit_msaa = true; } - if (is_intel_anv) { - LOG_WARNING(Render_Vulkan, "ANV driver does not support native BGR format"); + if (is_intel_anv || (is_qualcomm && !is_s8gen2)) { + LOG_WARNING(Render_Vulkan, "Driver does not support native BGR format"); must_emulate_bgr565 = true; } if (extensions.push_descriptor && is_intel_anv) { @@ -633,7 +721,8 @@ bool Device::ShouldBoostClocks() const { driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE || driver_id == VK_DRIVER_ID_MESA_RADV || driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY || driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS || - driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA; + driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA || + driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP; const bool is_steam_deck = vendor_id == 0x1002 && device_id == 0x163F; diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 5f1c63ff9..b692b4be4 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -295,6 +295,11 @@ public: return features.features.textureCompressionASTC_LDR; } + /// Returns true if descriptor aliasing is natively supported. + bool IsDescriptorAliasingSupported() const { + return GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY; + } + /// Returns true if the device supports float16 natively. bool IsFloat16Supported() const { return features.shader_float16_int8.shaderFloat16; @@ -495,6 +500,10 @@ public: } bool HasTimelineSemaphore() const { + if (GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) { + // Timeline semaphores do not work properly on all Qualcomm drivers. + return false; + } return features.timeline_semaphore.timelineSemaphore; } @@ -551,6 +560,10 @@ public: return cant_blit_msaa; } + bool MustEmulateScaledFormats() const { + return must_emulate_scaled_formats; + } + bool MustEmulateBGR565() const { return must_emulate_bgr565; } @@ -666,6 +679,7 @@ private: bool has_nsight_graphics{}; ///< Has Nsight Graphics attached bool supports_d24_depth{}; ///< Supports D24 depth buffers. bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting. + bool must_emulate_scaled_formats{}; ///< Requires scaled vertex format emulation bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format. bool dynamic_state3_blending{}; ///< Has all blending features of dynamic_state3. bool dynamic_state3_enables{}; ///< Has all enables features of dynamic_state3. diff --git a/src/video_core/vulkan_common/vulkan_library.cpp b/src/video_core/vulkan_common/vulkan_library.cpp index 4eb3913ee..47f6f2a03 100644 --- a/src/video_core/vulkan_common/vulkan_library.cpp +++ b/src/video_core/vulkan_common/vulkan_library.cpp @@ -10,29 +10,35 @@ namespace Vulkan { -Common::DynamicLibrary OpenLibrary() { +std::shared_ptr<Common::DynamicLibrary> OpenLibrary( + [[maybe_unused]] Core::Frontend::GraphicsContext* context) { LOG_DEBUG(Render_Vulkan, "Looking for a Vulkan library"); - Common::DynamicLibrary library; +#if defined(ANDROID) && defined(ARCHITECTURE_arm64) + // Android manages its Vulkan driver from the frontend. + return context->GetDriverLibrary(); +#else + auto library = std::make_shared<Common::DynamicLibrary>(); #ifdef __APPLE__ // Check if a path to a specific Vulkan library has been specified. char* const libvulkan_env = std::getenv("LIBVULKAN_PATH"); - if (!libvulkan_env || !library.Open(libvulkan_env)) { + if (!libvulkan_env || !library->Open(libvulkan_env)) { // Use the libvulkan.dylib from the application bundle. const auto filename = Common::FS::GetBundleDirectory() / "Contents/Frameworks/libvulkan.dylib"; - void(library.Open(Common::FS::PathToUTF8String(filename).c_str())); + void(library->Open(Common::FS::PathToUTF8String(filename).c_str())); } #else std::string filename = Common::DynamicLibrary::GetVersionedFilename("vulkan", 1); LOG_DEBUG(Render_Vulkan, "Trying Vulkan library: {}", filename); - if (!library.Open(filename.c_str())) { + if (!library->Open(filename.c_str())) { // Android devices may not have libvulkan.so.1, only libvulkan.so. filename = Common::DynamicLibrary::GetVersionedFilename("vulkan"); LOG_DEBUG(Render_Vulkan, "Trying Vulkan library (second attempt): {}", filename); - void(library.Open(filename.c_str())); + void(library->Open(filename.c_str())); } #endif return library; +#endif } } // namespace Vulkan diff --git a/src/video_core/vulkan_common/vulkan_library.h b/src/video_core/vulkan_common/vulkan_library.h index 364ca979b..e1734525e 100644 --- a/src/video_core/vulkan_common/vulkan_library.h +++ b/src/video_core/vulkan_common/vulkan_library.h @@ -3,10 +3,14 @@ #pragma once +#include <memory> + #include "common/dynamic_library.h" +#include "core/frontend/graphics_context.h" namespace Vulkan { -Common::DynamicLibrary OpenLibrary(); +std::shared_ptr<Common::DynamicLibrary> OpenLibrary( + [[maybe_unused]] Core::Frontend::GraphicsContext* context = nullptr); } // namespace Vulkan |