diff --git a/impeller/renderer/backend/vulkan/driver_info_vk.cc b/impeller/renderer/backend/vulkan/driver_info_vk.cc index 725acdad9052a..cda06e55bab7c 100644 --- a/impeller/renderer/backend/vulkan/driver_info_vk.cc +++ b/impeller/renderer/backend/vulkan/driver_info_vk.cc @@ -6,11 +6,19 @@ #include #include +#include #include "flutter/fml/build_config.h" namespace impeller { +/// Non functional Vulkan driver, see: +/// https://github.com/flutter/flutter/issues/154103 +/// +/// Reports "VK_INCOMPLETE" when compiling certain entity shader with +/// vkCreateGraphicsPipelines, which is not a valid return status. +constexpr std::string_view kAdreno630 = "Adreno (TM) 630"; + constexpr VendorVK IdentifyVendor(uint32_t vendor) { // Check if the vendor has a PCI ID: // https://pcisig.com/membership/member-companies @@ -188,4 +196,11 @@ bool DriverInfoVK::IsEmulator() const { return false; } +bool DriverInfoVK::IsKnownBadDriver() const { + if (vendor_ == VendorVK::kQualcomm && driver_name_ == kAdreno630) { + return true; + } + return false; +} + } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/driver_info_vk.h b/impeller/renderer/backend/vulkan/driver_info_vk.h index e973985105739..0966992d6a57e 100644 --- a/impeller/renderer/backend/vulkan/driver_info_vk.h +++ b/impeller/renderer/backend/vulkan/driver_info_vk.h @@ -123,6 +123,17 @@ class DriverInfoVK { /// bool IsEmulator() const; + //---------------------------------------------------------------------------- + /// @brief Determines if the driver has been tested and determined to be + /// non-functional. + /// + /// If true, context setup should fail such that the device falls + /// back to OpenGLES. + /// + /// @return True if non-functional device, False otherwiise. + /// + bool IsKnownBadDriver() const; + private: bool is_valid_ = false; Version api_version_; diff --git a/impeller/renderer/backend/vulkan/driver_info_vk_unittests.cc b/impeller/renderer/backend/vulkan/driver_info_vk_unittests.cc index dd047a9dfc2e6..9cebcbbae7fc7 100644 --- a/impeller/renderer/backend/vulkan/driver_info_vk_unittests.cc +++ b/impeller/renderer/backend/vulkan/driver_info_vk_unittests.cc @@ -4,7 +4,9 @@ #include "impeller/playground/playground_test.h" #include "impeller/renderer/backend/vulkan/context_vk.h" +#include "impeller/renderer/backend/vulkan/driver_info_vk.h" #include "impeller/renderer/backend/vulkan/surface_context_vk.h" +#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h" namespace impeller::testing { @@ -21,6 +23,7 @@ TEST_P(DriverInfoVKTest, CanQueryDriverInfo) { ASSERT_NE(driver_info->GetVendor(), VendorVK::kUnknown); ASSERT_NE(driver_info->GetDeviceType(), DeviceTypeVK::kUnknown); ASSERT_NE(driver_info->GetDriverName(), ""); + EXPECT_FALSE(driver_info->IsKnownBadDriver()); } TEST_P(DriverInfoVKTest, CanDumpToLog) { @@ -30,7 +33,23 @@ TEST_P(DriverInfoVKTest, CanDumpToLog) { ASSERT_NE(driver_info, nullptr); fml::testing::LogCapture log; driver_info->DumpToLog(); - ASSERT_TRUE(log.str().find("Driver Information") != std::string::npos); + EXPECT_TRUE(log.str().find("Driver Information") != std::string::npos); +} + +TEST(DriverInfoVKTest, DisabledDevices) { + std::string name = "Adreno (TM) 630"; + auto const context = MockVulkanContextBuilder() + .SetPhysicalPropertiesCallback( + [&name](VkPhysicalDevice device, + VkPhysicalDeviceProperties* prop) { + prop->vendorID = 0x168C; // Qualcomm + name.copy(prop->deviceName, name.size()); + prop->deviceType = + VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; + }) + .Build(); + + EXPECT_TRUE(context->GetDriverInfo()->IsKnownBadDriver()); } } // namespace impeller::testing diff --git a/impeller/renderer/backend/vulkan/test/mock_vulkan.cc b/impeller/renderer/backend/vulkan/test/mock_vulkan.cc index c18a569315863..0a1dd6fcdf53d 100644 --- a/impeller/renderer/backend/vulkan/test/mock_vulkan.cc +++ b/impeller/renderer/backend/vulkan/test/mock_vulkan.cc @@ -169,6 +169,10 @@ void vkGetPhysicalDeviceFormatProperties( g_format_properties_callback(physicalDevice, format, pFormatProperties); } +static thread_local std::function + g_physical_device_properties_callback; + void vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties) { pProperties->limits.framebufferColorSampleCounts = @@ -176,6 +180,9 @@ void vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VK_SAMPLE_COUNT_4_BIT); pProperties->limits.maxImageDimension2D = 4096; pProperties->limits.timestampPeriod = 1; + if (g_physical_device_properties_callback) { + g_physical_device_properties_callback(physicalDevice, pProperties); + } } void vkGetPhysicalDeviceQueueFamilyProperties( @@ -919,6 +926,7 @@ std::shared_ptr MockVulkanContextBuilder::Build() { g_instance_extensions = instance_extensions_; g_instance_layers = instance_layers_; g_format_properties_callback = format_properties_callback_; + g_physical_device_properties_callback = physical_properties_callback_; std::shared_ptr result = ContextVK::Create(std::move(settings)); return result; } diff --git a/impeller/renderer/backend/vulkan/test/mock_vulkan.h b/impeller/renderer/backend/vulkan/test/mock_vulkan.h index 3febfe3bc7ff7..adffe42202b8d 100644 --- a/impeller/renderer/backend/vulkan/test/mock_vulkan.h +++ b/impeller/renderer/backend/vulkan/test/mock_vulkan.h @@ -100,6 +100,14 @@ class MockVulkanContextBuilder { return *this; } + MockVulkanContextBuilder& SetPhysicalPropertiesCallback( + std::function + physical_properties_callback) { + physical_properties_callback_ = std::move(physical_properties_callback); + return *this; + } + private: std::function settings_callback_; std::vector instance_extensions_; @@ -108,6 +116,9 @@ class MockVulkanContextBuilder { VkFormat format, VkFormatProperties* pFormatProperties)> format_properties_callback_; + std::function + physical_properties_callback_; }; /// @brief Override the image size returned by all swapchain images. diff --git a/shell/platform/android/android_context_vk_impeller.cc b/shell/platform/android/android_context_vk_impeller.cc index b81f9cb6b1f34..5d3b49cb393f0 100644 --- a/shell/platform/android/android_context_vk_impeller.cc +++ b/shell/platform/android/android_context_vk_impeller.cc @@ -4,6 +4,7 @@ #include "flutter/shell/platform/android/android_context_vk_impeller.h" +#include "flutter/fml/logging.h" #include "flutter/fml/paths.h" #include "flutter/impeller/entity/vk/entity_shaders_vk.h" #include "flutter/impeller/entity/vk/framebuffer_blend_shaders_vk.h" @@ -67,6 +68,11 @@ static std::shared_ptr CreateImpellerContext( FML_LOG(IMPORTANT) << "Using the Impeller rendering backend (Vulkan)."; } } + if (context->GetDriverInfo()->IsKnownBadDriver()) { + FML_LOG(INFO) + << "Known bad Vulkan driver encountered, falling back to OpenGLES."; + return nullptr; + } return context; }