Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 4f62e0b

Browse files
author
Jonah Williams
authored
[Impeller] disable Adreno 630 vulkan and add mechanism for android driver denylisting. (#54920)
Fixes flutter/flutter#154103 From local testing, the Adreno 630 returns VK_INCOMPLETE when compiling certain shaders with no other error messages. That is not a valid return code from vkCreateGraphicsPipeline and likely indicates severe problems with the driver.
1 parent 872cbe8 commit 4f62e0b

File tree

6 files changed

+71
-1
lines changed

6 files changed

+71
-1
lines changed

impeller/renderer/backend/vulkan/driver_info_vk.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,19 @@
66

77
#include <iomanip>
88
#include <sstream>
9+
#include <string_view>
910

1011
#include "flutter/fml/build_config.h"
1112

1213
namespace impeller {
1314

15+
/// Non functional Vulkan driver, see:
16+
/// https://github.com/flutter/flutter/issues/154103
17+
///
18+
/// Reports "VK_INCOMPLETE" when compiling certain entity shader with
19+
/// vkCreateGraphicsPipelines, which is not a valid return status.
20+
constexpr std::string_view kAdreno630 = "Adreno (TM) 630";
21+
1422
constexpr VendorVK IdentifyVendor(uint32_t vendor) {
1523
// Check if the vendor has a PCI ID:
1624
// https://pcisig.com/membership/member-companies
@@ -188,4 +196,11 @@ bool DriverInfoVK::IsEmulator() const {
188196
return false;
189197
}
190198

199+
bool DriverInfoVK::IsKnownBadDriver() const {
200+
if (vendor_ == VendorVK::kQualcomm && driver_name_ == kAdreno630) {
201+
return true;
202+
}
203+
return false;
204+
}
205+
191206
} // namespace impeller

impeller/renderer/backend/vulkan/driver_info_vk.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,17 @@ class DriverInfoVK {
123123
///
124124
bool IsEmulator() const;
125125

126+
//----------------------------------------------------------------------------
127+
/// @brief Determines if the driver has been tested and determined to be
128+
/// non-functional.
129+
///
130+
/// If true, context setup should fail such that the device falls
131+
/// back to OpenGLES.
132+
///
133+
/// @return True if non-functional device, False otherwiise.
134+
///
135+
bool IsKnownBadDriver() const;
136+
126137
private:
127138
bool is_valid_ = false;
128139
Version api_version_;

impeller/renderer/backend/vulkan/driver_info_vk_unittests.cc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
#include "impeller/playground/playground_test.h"
66
#include "impeller/renderer/backend/vulkan/context_vk.h"
7+
#include "impeller/renderer/backend/vulkan/driver_info_vk.h"
78
#include "impeller/renderer/backend/vulkan/surface_context_vk.h"
9+
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
810

911
namespace impeller::testing {
1012

@@ -21,6 +23,7 @@ TEST_P(DriverInfoVKTest, CanQueryDriverInfo) {
2123
ASSERT_NE(driver_info->GetVendor(), VendorVK::kUnknown);
2224
ASSERT_NE(driver_info->GetDeviceType(), DeviceTypeVK::kUnknown);
2325
ASSERT_NE(driver_info->GetDriverName(), "");
26+
EXPECT_FALSE(driver_info->IsKnownBadDriver());
2427
}
2528

2629
TEST_P(DriverInfoVKTest, CanDumpToLog) {
@@ -30,7 +33,23 @@ TEST_P(DriverInfoVKTest, CanDumpToLog) {
3033
ASSERT_NE(driver_info, nullptr);
3134
fml::testing::LogCapture log;
3235
driver_info->DumpToLog();
33-
ASSERT_TRUE(log.str().find("Driver Information") != std::string::npos);
36+
EXPECT_TRUE(log.str().find("Driver Information") != std::string::npos);
37+
}
38+
39+
TEST(DriverInfoVKTest, DisabledDevices) {
40+
std::string name = "Adreno (TM) 630";
41+
auto const context = MockVulkanContextBuilder()
42+
.SetPhysicalPropertiesCallback(
43+
[&name](VkPhysicalDevice device,
44+
VkPhysicalDeviceProperties* prop) {
45+
prop->vendorID = 0x168C; // Qualcomm
46+
name.copy(prop->deviceName, name.size());
47+
prop->deviceType =
48+
VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
49+
})
50+
.Build();
51+
52+
EXPECT_TRUE(context->GetDriverInfo()->IsKnownBadDriver());
3453
}
3554

3655
} // namespace impeller::testing

impeller/renderer/backend/vulkan/test/mock_vulkan.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,20 @@ void vkGetPhysicalDeviceFormatProperties(
169169
g_format_properties_callback(physicalDevice, format, pFormatProperties);
170170
}
171171

172+
static thread_local std::function<void(VkPhysicalDevice physicalDevice,
173+
VkPhysicalDeviceProperties* pProperties)>
174+
g_physical_device_properties_callback;
175+
172176
void vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
173177
VkPhysicalDeviceProperties* pProperties) {
174178
pProperties->limits.framebufferColorSampleCounts =
175179
static_cast<VkSampleCountFlags>(VK_SAMPLE_COUNT_1_BIT |
176180
VK_SAMPLE_COUNT_4_BIT);
177181
pProperties->limits.maxImageDimension2D = 4096;
178182
pProperties->limits.timestampPeriod = 1;
183+
if (g_physical_device_properties_callback) {
184+
g_physical_device_properties_callback(physicalDevice, pProperties);
185+
}
179186
}
180187

181188
void vkGetPhysicalDeviceQueueFamilyProperties(
@@ -919,6 +926,7 @@ std::shared_ptr<ContextVK> MockVulkanContextBuilder::Build() {
919926
g_instance_extensions = instance_extensions_;
920927
g_instance_layers = instance_layers_;
921928
g_format_properties_callback = format_properties_callback_;
929+
g_physical_device_properties_callback = physical_properties_callback_;
922930
std::shared_ptr<ContextVK> result = ContextVK::Create(std::move(settings));
923931
return result;
924932
}

impeller/renderer/backend/vulkan/test/mock_vulkan.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ class MockVulkanContextBuilder {
100100
return *this;
101101
}
102102

103+
MockVulkanContextBuilder& SetPhysicalPropertiesCallback(
104+
std::function<void(VkPhysicalDevice device,
105+
VkPhysicalDeviceProperties* physicalProperties)>
106+
physical_properties_callback) {
107+
physical_properties_callback_ = std::move(physical_properties_callback);
108+
return *this;
109+
}
110+
103111
private:
104112
std::function<void(ContextVK::Settings&)> settings_callback_;
105113
std::vector<std::string> instance_extensions_;
@@ -108,6 +116,9 @@ class MockVulkanContextBuilder {
108116
VkFormat format,
109117
VkFormatProperties* pFormatProperties)>
110118
format_properties_callback_;
119+
std::function<void(VkPhysicalDevice device,
120+
VkPhysicalDeviceProperties* physicalProperties)>
121+
physical_properties_callback_;
111122
};
112123

113124
/// @brief Override the image size returned by all swapchain images.

shell/platform/android/android_context_vk_impeller.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "flutter/shell/platform/android/android_context_vk_impeller.h"
66

7+
#include "flutter/fml/logging.h"
78
#include "flutter/fml/paths.h"
89
#include "flutter/impeller/entity/vk/entity_shaders_vk.h"
910
#include "flutter/impeller/entity/vk/framebuffer_blend_shaders_vk.h"
@@ -67,6 +68,11 @@ static std::shared_ptr<impeller::Context> CreateImpellerContext(
6768
FML_LOG(IMPORTANT) << "Using the Impeller rendering backend (Vulkan).";
6869
}
6970
}
71+
if (context->GetDriverInfo()->IsKnownBadDriver()) {
72+
FML_LOG(INFO)
73+
<< "Known bad Vulkan driver encountered, falling back to OpenGLES.";
74+
return nullptr;
75+
}
7076

7177
return context;
7278
}

0 commit comments

Comments
 (0)