Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
driver_info_vk.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <iomanip>
8#include <sstream>
9#include <string_view>
10#include <unordered_map>
11
13
14#ifdef FML_OS_ANDROID
15#include <sys/system_properties.h>
16#endif // FML_OS_ANDROID
17
18namespace impeller {
19
20namespace {
21const std::unordered_map<std::string_view, AdrenoGPU> kAdrenoVersions = {
22 // X
23 // Note: I don't know if these strings actually match as there don't seem to
24 // be any android devices that use these GPUs.
25 {"X185", AdrenoGPU::kAdrenoX185},
26 {"X145", AdrenoGPU::kAdrenoX145},
27 // 700
28 {"750", AdrenoGPU::kAdreno750},
29 {"740", AdrenoGPU::kAdreno740},
30 {"735", AdrenoGPU::kAdreno735},
31 {"721", AdrenoGPU::kAdreno732},
32 {"730", AdrenoGPU::kAdreno730},
33 {"725", AdrenoGPU::kAdreno725},
34 {"720", AdrenoGPU::kAdreno720},
35 {"710", AdrenoGPU::kAdreno710},
36 {"702", AdrenoGPU::kAdreno702},
37
38 // 600
39 {"695", AdrenoGPU::kAdreno695},
40 {"690", AdrenoGPU::kAdreno690},
41 {"685", AdrenoGPU::kAdreno685},
42 {"680", AdrenoGPU::kAdreno680},
43 {"675", AdrenoGPU::kAdreno675},
44 {"663", AdrenoGPU::kAdreno663},
45 {"660", AdrenoGPU::kAdreno660},
46 {"650", AdrenoGPU::kAdreno650},
47 {"644", AdrenoGPU::kAdreno644},
48 {"643L", AdrenoGPU::kAdreno643L},
49 {"642", AdrenoGPU::kAdreno642},
50 {"642L", AdrenoGPU::kAdreno642L},
51 {"640", AdrenoGPU::kAdreno640},
52 {"630", AdrenoGPU::kAdreno630},
53 {"620", AdrenoGPU::kAdreno620},
54 {"619", AdrenoGPU::kAdreno619},
55 {"619L", AdrenoGPU::kAdreno619L},
56 {"618", AdrenoGPU::kAdreno618},
57 {"616", AdrenoGPU::kAdreno616},
58 {"615", AdrenoGPU::kAdreno615},
59 {"613", AdrenoGPU::kAdreno613},
60 {"612", AdrenoGPU::kAdreno612},
61 {"610", AdrenoGPU::kAdreno610},
62 {"608", AdrenoGPU::kAdreno608},
63 {"605", AdrenoGPU::kAdreno605},
64 // 500
65 {"540", AdrenoGPU::kAdreno540},
66 {"530", AdrenoGPU::kAdreno530},
67 {"512", AdrenoGPU::kAdreno512},
68 {"510", AdrenoGPU::kAdreno510},
69 {"509", AdrenoGPU::kAdreno509},
70 {"508", AdrenoGPU::kAdreno508},
71 {"506", AdrenoGPU::kAdreno506},
72 {"505", AdrenoGPU::kAdreno505},
73 {"504", AdrenoGPU::kAdreno504},
74};
75
76const std::unordered_map<std::string_view, MaliGPU> kMaliVersions = {
77 // 5th Gen.
78 {"G925", MaliGPU::kG925},
79 {"G725", MaliGPU::kG725},
80 {"G625", MaliGPU::kG625},
81 {"G720", MaliGPU::kG720},
82 {"G620", MaliGPU::kG620},
83
84 // Valhall
85 // Note: there is an Immortalis-G715 a Mali-G715
86 {"G715", MaliGPU::kG715},
87 {"G615", MaliGPU::kG615},
88 {"G710", MaliGPU::kG710},
89 {"G610", MaliGPU::kG610},
90 {"G510", MaliGPU::kG510},
91 {"G310", MaliGPU::kG310},
92 {"G78", MaliGPU::kG78},
93 {"G68", MaliGPU::kG68},
94 {"G77", MaliGPU::kG77},
95 {"G57", MaliGPU::kG57},
96
97 // Bifrost
98 {"G76", MaliGPU::kG76},
99 {"G72", MaliGPU::kG72},
100 {"G52", MaliGPU::kG52},
101 {"G71", MaliGPU::kG71},
102 {"G51", MaliGPU::kG51},
103 {"G31", MaliGPU::kG31},
104
105 // These might be Vulkan 1.0 Only.
106 {"T880", MaliGPU::kT880},
107 {"T860", MaliGPU::kT860},
108 {"T830", MaliGPU::kT830},
109 {"T820", MaliGPU::kT820},
110 {"T760", MaliGPU::kT760},
111};
112
113constexpr std::array<std::pair<std::string_view, PowerVRGPU>, 6> kGpuSeriesMap =
114 {{
115 {"BXE", PowerVRGPU::kBXE},
116 {"BXM", PowerVRGPU::kBXM},
117 {"BXS", PowerVRGPU::kBXS},
118 {"BXT", PowerVRGPU::kBXT},
119 {"CXT", PowerVRGPU::kCXT},
120 {"DXT", PowerVRGPU::kDXT},
121 }};
122} // namespace
123
124// Pixel 10 device ID from ANGLE/Chromium source code.
125// https://chromium.googlesource.com/chromium/src/+/main/testing/buildbot/buildbot_json_magic_substitutions.py#51
126// https://source.chromium.org/chromium/chromium/src/+/main:content/test/gpu/gpu_tests/gpu_integration_test.py;l=1396;drc=6cce000efb9f288a9d51d42c7ab38b38beb5d77c
127const uint32_t kPixel10DeviceID = 0x71061212;
128// PowerVR 25.1@6794074 - the device_driver_version_ is a packed version number
129// which is vendor specific. This appears to be the PowerVR DDK build number.
130// https://www.khronos.org/conformance/adopters/conformant-products/opencl#submission_466
131// https://vulkan.gpuinfo.org/listreports.php?devicename=Google+Pixel+10&platform=android
132const uint32_t kPixel10MinDriverVersion = 6794074; // Corresponds to 25.1
133
134AdrenoGPU GetAdrenoVersion(std::string_view version) {
135 /// The format that Adreno names follow is "Adreno (TM) VERSION".
136 auto paren_pos = version.find("Adreno (TM) ");
137 if (paren_pos == std::string::npos) {
138 return AdrenoGPU::kUnknown;
139 }
140 auto version_string = version.substr(paren_pos + 12);
141 const auto& result = kAdrenoVersions.find(version_string);
142 if (result == kAdrenoVersions.end()) {
143 return AdrenoGPU::kUnknown;
144 }
145 return result->second;
146}
147
148PowerVRGPU GetPowerVRVersion(std::string_view version) {
149 for (const auto& entry : kGpuSeriesMap) {
150 if (version.find(entry.first) != std::string::npos) {
151 return entry.second;
152 }
153 }
154
156}
157
158MaliGPU GetMaliVersion(std::string_view version) {
159 // These names are usually Mali-VERSION or Mali-Version-EXTRA_CRAP.
160 auto dash_pos = version.find("Mali-");
161 if (dash_pos == std::string::npos) {
162 return MaliGPU::kUnknown;
163 }
164 auto version_string_with_trailing = version.substr(dash_pos + 5);
165 // Remove any trailing crap if present.
166 auto more_dash_pos = version_string_with_trailing.find("-");
167 if (more_dash_pos != std::string::npos) {
168 version_string_with_trailing =
169 version_string_with_trailing.substr(0, more_dash_pos);
170 }
171
172 const auto& result = kMaliVersions.find(version_string_with_trailing);
173 if (result == kMaliVersions.end()) {
174 return MaliGPU::kUnknown;
175 }
176 return result->second;
177}
178
179constexpr VendorVK IdentifyVendor(uint32_t vendor) {
180 // Check if the vendor has a PCI ID:
181 // https://pcisig.com/membership/member-companies
182 switch (vendor) {
183 case 0x1AE0:
184 return VendorVK::kGoogle;
185 case 0x168C:
186 case 0x17CB:
187 case 0x1969:
188 case 0x5143:
189 return VendorVK::kQualcomm;
190 case 0x13B5:
191 return VendorVK::kARM;
192 case 0x1010:
193 return VendorVK::kImgTec;
194 case 0x1002:
195 case 0x1022:
196 return VendorVK::kAMD;
197 case 0x10DE:
198 return VendorVK::kNvidia;
199 case 0x8086: // :)
200 return VendorVK::kIntel;
201 case 0x106B:
202 return VendorVK::kApple;
203 case 0x19E5:
204 return VendorVK::kHuawei;
205 case 0x144D:
206 return VendorVK::kSamsung;
207 }
208 // Check if the ID is a known Khronos vendor.
209 switch (vendor) {
210 case VK_VENDOR_ID_MESA:
211 return VendorVK::kMesa;
212 // There are others but have never been observed. These can be added as
213 // needed.
214 }
215 return VendorVK::kUnknown;
216}
217
218constexpr const char* VendorToString(VendorVK vendor) {
219 switch (vendor) {
221 return "Unknown";
223 return "Google";
225 return "Qualcomm";
226 case VendorVK::kARM:
227 return "ARM";
229 return "ImgTec PowerVR";
230 case VendorVK::kAMD:
231 return "AMD";
233 return "Nvidia";
234 case VendorVK::kIntel:
235 return "Intel";
236 case VendorVK::kMesa:
237 return "Mesa";
238 case VendorVK::kApple:
239 return "Apple";
241 return "Huawei";
243 return "Samsung";
244 }
246}
247
248constexpr const char* DeviceTypeToString(DeviceTypeVK type) {
249 switch (type) {
251 return "Unknown";
253 return "Integrated GPU";
255 return "Discrete GPU";
257 return "Virtual GPU";
259 return "CPU";
260 }
262}
263
264constexpr DeviceTypeVK ToDeviceType(const vk::PhysicalDeviceType& type) {
265 switch (type) {
266 case vk::PhysicalDeviceType::eOther:
268 case vk::PhysicalDeviceType::eIntegratedGpu:
270 case vk::PhysicalDeviceType::eDiscreteGpu:
272 case vk::PhysicalDeviceType::eVirtualGpu:
274 case vk::PhysicalDeviceType::eCpu:
275 return DeviceTypeVK::kCPU;
276 break;
277 }
279}
280
281DriverInfoVK::DriverInfoVK(const vk::PhysicalDevice& device) {
282 auto props = device.getProperties();
283 api_version_ = Version{VK_API_VERSION_MAJOR(props.apiVersion),
284 VK_API_VERSION_MINOR(props.apiVersion),
285 VK_API_VERSION_PATCH(props.apiVersion)};
286 driver_version_ = props.driverVersion;
287 device_id_ = props.deviceID;
288 vendor_ = IdentifyVendor(props.vendorID);
289 if (vendor_ == VendorVK::kUnknown) {
290 FML_LOG(WARNING) << "Unknown GPU Driver Vendor: " << props.vendorID
291 << ". This is not an error.";
292 }
293 type_ = ToDeviceType(props.deviceType);
294 if (props.deviceName.data() != nullptr) {
295 driver_name_ = props.deviceName.data();
296 }
297
298 switch (vendor_) {
300 adreno_gpu_ = GetAdrenoVersion(driver_name_);
301 break;
302 case VendorVK::kARM:
303 mali_gpu_ = GetMaliVersion(driver_name_);
304 break;
306 powervr_gpu_ = GetPowerVRVersion(driver_name_);
307 break;
308 default:
309 break;
310 }
311}
312
314
316 return api_version_;
317}
318
320 return vendor_;
321}
322
324 return type_;
325}
326
327const std::string& DriverInfoVK::GetDriverName() const {
328 return driver_name_;
329}
330
332 std::vector<std::pair<std::string, std::string>> items;
333 items.emplace_back("Name", driver_name_);
334 items.emplace_back("API Version", api_version_.ToString());
335 items.emplace_back("Driver Version", std::to_string(driver_version_));
336 items.emplace_back("Vendor", VendorToString(vendor_));
337 items.emplace_back("Device Type", DeviceTypeToString(type_));
338 items.emplace_back("Is Emulator", std::to_string(IsEmulator()));
339
340 size_t padding = 0;
341
342 for (const auto& item : items) {
343 padding = std::max(padding, item.first.size());
344 }
345
346 padding += 1;
347
348 std::stringstream stream;
349
350 stream << std::endl;
351
352 stream << "--- Driver Information ------------------------------------------";
353
354 stream << std::endl;
355
356 for (const auto& item : items) {
357 stream << "| " << std::setw(static_cast<int>(padding)) << item.first
358 << std::setw(0) << ": " << item.second << std::endl;
359 }
360
361 stream << "-----------------------------------------------------------------";
362
363 FML_LOG(IMPORTANT) << stream.str();
364}
365
367#if FML_OS_ANDROID
368 // Google SwiftShader on Android.
369 if (type_ == DeviceTypeVK::kCPU && vendor_ == VendorVK::kGoogle &&
370 driver_name_.find("SwiftShader") != std::string::npos) {
371 return true;
372 }
373#endif // FML_OS_ANDROID
374 return false;
375}
376
378#if FML_OS_ANDROID
379 // Pixel 10 is identified by the PowerVR vendor and device ID 0x71061212.
380 // The driver version 25.1 or greater is required - which is device specific
381 // to 6794074 or greater.
382 if (vendor_ == VendorVK::kPowerVR && device_id_ == kPixel10DeviceID &&
383 driver_version_ < kPixel10MinDriverVersion) {
384 FML_LOG(WARNING) << "Pixel 10 driver version "
385 << std::to_string(driver_version_)
386 << " is less than 25.1. Blocking Vulkan initialization.";
387 return true;
388 }
389#endif // FML_OS_ANDROID
390
391 // Fall back to OpenGL ES on older Adreno devices that require additional
392 // workarounds in the Impeller Vulkan back end such as disabling framebuffer
393 // fetch.
394 //
395 // See the following issues:
396 // https://github.com/flutter/flutter/issues/178285
397 // https://github.com/flutter/flutter/issues/178498
398 if (adreno_gpu_ && *adreno_gpu_ <= AdrenoGPU::kAdreno650) {
399 return true;
400 }
401
402 // Disable Maleoon series GPUs, see:
403 // https://github.com/flutter/flutter/issues/156623
404 if (vendor_ == VendorVK::kHuawei) {
405 return true;
406 }
407
408 if (vendor_ == VendorVK::kSamsung) {
409 // The first version of the Xclipse series GPU has reported
410 // bugs, unfortunately all versions of this GPU report the
411 // same driver version. Instead we use the Vulkan version
412 // as a proxy, assuming that any newer devices would not
413 // lower the supported Vulkan API level.
414 // See
415 // https://vulkan.gpuinfo.org/listreports.php?devicename=samsung+SM-S906B&platform=android
416 // https://github.com/flutter/flutter/issues/161334
417 return !api_version_.IsAtLeast(Version{1, 3, 0});
418 }
419
420 // https://github.com/flutter/flutter/issues/161122
421 // https://github.com/flutter/flutter/issues/160960
422 // https://github.com/flutter/flutter/issues/160866
423 // https://github.com/flutter/flutter/issues/160804
424 // https://github.com/flutter/flutter/issues/160406
425 if (powervr_gpu_.has_value() && powervr_gpu_.value() < PowerVRGPU::kBXE) {
426 return true;
427 }
428 return false;
429}
430
431std::optional<MaliGPU> DriverInfoVK::GetMaliGPUInfo() const {
432 return mali_gpu_;
433}
434
435std::optional<AdrenoGPU> DriverInfoVK::GetAdrenoGPUInfo() const {
436 return adreno_gpu_;
437}
438
439std::optional<PowerVRGPU> DriverInfoVK::GetPowerVRGPUInfo() const {
440 return powervr_gpu_;
441}
442
443} // namespace impeller
GLenum type
const VendorVK & GetVendor() const
Get the vendor of the Vulkan implementation. This is a broad check and includes multiple drivers and ...
DriverInfoVK(const vk::PhysicalDevice &device)
std::optional< PowerVRGPU > GetPowerVRGPUInfo() const
Returns PowerVR GPU info if this is a PowerVR GPU, otherwise std::nullopt.
bool IsKnownBadDriver() const
Determines if the driver has been tested and determined to be non-functional.
const std::string & GetDriverName() const
Get the self-reported name of the graphics driver.
std::optional< AdrenoGPU > GetAdrenoGPUInfo() const
Returns Adreno GPU info if this is a Adreno GPU, otherwise std::nullopt.
void DumpToLog() const
Dumps the current driver info to the log.
std::optional< MaliGPU > GetMaliGPUInfo() const
Returns Mali GPU info if this is a Mali GPU, otherwise std::nullopt.
bool IsEmulator() const
Determines if the driver represents an emulator. There is no definitive way to tell if a driver is an...
const DeviceTypeVK & GetDeviceType() const
Get the device type. Typical use might be to check if the device is a CPU implementation.
const Version & GetAPIVersion() const
Gets the Vulkan API version. Should be at or above Vulkan 1.1 which is the Impeller baseline.
VkDevice device
Definition main.cc:69
#define FML_LOG(severity)
Definition logging.h:101
#define FML_UNREACHABLE()
Definition logging.h:128
Vector2 padding
The halo padding in source space.
constexpr VendorVK IdentifyVendor(uint32_t vendor)
MaliGPU GetMaliVersion(std::string_view version)
AdrenoGPU GetAdrenoVersion(std::string_view version)
constexpr const char * DeviceTypeToString(DeviceTypeVK type)
const uint32_t kPixel10DeviceID
PowerVRGPU GetPowerVRVersion(std::string_view version)
constexpr const char * VendorToString(VendorVK vendor)
const uint32_t kPixel10MinDriverVersion
constexpr DeviceTypeVK ToDeviceType(const vk::PhysicalDeviceType &type)
constexpr bool IsAtLeast(const Version &other) const
Definition version.h:31
std::string ToString() const
Definition version.cc:27