Flutter Engine
 
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
14namespace impeller {
15
16namespace {
17const std::unordered_map<std::string_view, AdrenoGPU> kAdrenoVersions = {
18 // X
19 // Note: I don't know if these strings actually match as there don't seem to
20 // be any android devices that use these GPUs.
21 {"X185", AdrenoGPU::kAdrenoX185},
22 {"X145", AdrenoGPU::kAdrenoX145},
23 // 700
24 {"750", AdrenoGPU::kAdreno750},
25 {"740", AdrenoGPU::kAdreno740},
26 {"735", AdrenoGPU::kAdreno735},
27 {"721", AdrenoGPU::kAdreno732},
28 {"730", AdrenoGPU::kAdreno730},
29 {"725", AdrenoGPU::kAdreno725},
30 {"720", AdrenoGPU::kAdreno720},
31 {"710", AdrenoGPU::kAdreno710},
32 {"702", AdrenoGPU::kAdreno702},
33
34 // 600
35 {"695", AdrenoGPU::kAdreno695},
36 {"690", AdrenoGPU::kAdreno690},
37 {"685", AdrenoGPU::kAdreno685},
38 {"680", AdrenoGPU::kAdreno680},
39 {"675", AdrenoGPU::kAdreno675},
40 {"663", AdrenoGPU::kAdreno663},
41 {"660", AdrenoGPU::kAdreno660},
42 {"650", AdrenoGPU::kAdreno650},
43 {"644", AdrenoGPU::kAdreno644},
44 {"643L", AdrenoGPU::kAdreno643L},
45 {"642", AdrenoGPU::kAdreno642},
46 {"642L", AdrenoGPU::kAdreno642L},
47 {"640", AdrenoGPU::kAdreno640},
48 {"630", AdrenoGPU::kAdreno630},
49 {"620", AdrenoGPU::kAdreno620},
50 {"619", AdrenoGPU::kAdreno619},
51 {"619L", AdrenoGPU::kAdreno619L},
52 {"618", AdrenoGPU::kAdreno618},
53 {"616", AdrenoGPU::kAdreno616},
54 {"615", AdrenoGPU::kAdreno615},
55 {"613", AdrenoGPU::kAdreno613},
56 {"612", AdrenoGPU::kAdreno612},
57 {"610", AdrenoGPU::kAdreno610},
58 {"608", AdrenoGPU::kAdreno608},
59 {"605", AdrenoGPU::kAdreno605},
60 // 500
61 {"540", AdrenoGPU::kAdreno540},
62 {"530", AdrenoGPU::kAdreno530},
63 {"512", AdrenoGPU::kAdreno512},
64 {"510", AdrenoGPU::kAdreno510},
65 {"509", AdrenoGPU::kAdreno509},
66 {"508", AdrenoGPU::kAdreno508},
67 {"506", AdrenoGPU::kAdreno506},
68 {"505", AdrenoGPU::kAdreno505},
69 {"504", AdrenoGPU::kAdreno504},
70};
71
72const std::unordered_map<std::string_view, MaliGPU> kMaliVersions = {
73 // 5th Gen.
74 {"G925", MaliGPU::kG925},
75 {"G725", MaliGPU::kG725},
76 {"G625", MaliGPU::kG625},
77 {"G720", MaliGPU::kG720},
78 {"G620", MaliGPU::kG620},
79
80 // Valhall
81 // Note: there is an Immortalis-G715 a Mali-G715
82 {"G715", MaliGPU::kG715},
83 {"G615", MaliGPU::kG615},
84 {"G710", MaliGPU::kG710},
85 {"G610", MaliGPU::kG610},
86 {"G510", MaliGPU::kG510},
87 {"G310", MaliGPU::kG310},
88 {"G78", MaliGPU::kG78},
89 {"G68", MaliGPU::kG68},
90 {"G77", MaliGPU::kG77},
91 {"G57", MaliGPU::kG57},
92
93 // Bifrost
94 {"G76", MaliGPU::kG76},
95 {"G72", MaliGPU::kG72},
96 {"G52", MaliGPU::kG52},
97 {"G71", MaliGPU::kG71},
98 {"G51", MaliGPU::kG51},
99 {"G31", MaliGPU::kG31},
100
101 // These might be Vulkan 1.0 Only.
102 {"T880", MaliGPU::kT880},
103 {"T860", MaliGPU::kT860},
104 {"T830", MaliGPU::kT830},
105 {"T820", MaliGPU::kT820},
106 {"T760", MaliGPU::kT760},
107};
108
109constexpr std::array<std::pair<std::string_view, PowerVRGPU>, 6> kGpuSeriesMap =
110 {{
111 {"BXE", PowerVRGPU::kBXE},
112 {"BXM", PowerVRGPU::kBXM},
113 {"BXS", PowerVRGPU::kBXS},
114 {"BXT", PowerVRGPU::kBXT},
115 {"CXT", PowerVRGPU::kCXT},
116 {"DXT", PowerVRGPU::kDXT},
117 }};
118} // namespace
119
120AdrenoGPU GetAdrenoVersion(std::string_view version) {
121 /// The format that Adreno names follow is "Adreno (TM) VERSION".
122 auto paren_pos = version.find("Adreno (TM) ");
123 if (paren_pos == std::string::npos) {
124 return AdrenoGPU::kUnknown;
125 }
126 auto version_string = version.substr(paren_pos + 12);
127 const auto& result = kAdrenoVersions.find(version_string);
128 if (result == kAdrenoVersions.end()) {
129 return AdrenoGPU::kUnknown;
130 }
131 return result->second;
132}
133
134PowerVRGPU GetPowerVRVersion(std::string_view version) {
135 for (const auto& entry : kGpuSeriesMap) {
136 if (version.find(entry.first) != std::string::npos) {
137 return entry.second;
138 }
139 }
140
142}
143
144MaliGPU GetMaliVersion(std::string_view version) {
145 // These names are usually Mali-VERSION or Mali-Version-EXTRA_CRAP.
146 auto dash_pos = version.find("Mali-");
147 if (dash_pos == std::string::npos) {
148 return MaliGPU::kUnknown;
149 }
150 auto version_string_with_trailing = version.substr(dash_pos + 5);
151 // Remove any trailing crap if present.
152 auto more_dash_pos = version_string_with_trailing.find("-");
153 if (more_dash_pos != std::string::npos) {
154 version_string_with_trailing =
155 version_string_with_trailing.substr(0, more_dash_pos);
156 }
157
158 const auto& result = kMaliVersions.find(version_string_with_trailing);
159 if (result == kMaliVersions.end()) {
160 return MaliGPU::kUnknown;
161 }
162 return result->second;
163}
164
165constexpr VendorVK IdentifyVendor(uint32_t vendor) {
166 // Check if the vendor has a PCI ID:
167 // https://pcisig.com/membership/member-companies
168 switch (vendor) {
169 case 0x1AE0:
170 return VendorVK::kGoogle;
171 case 0x168C:
172 case 0x17CB:
173 case 0x1969:
174 case 0x5143:
175 return VendorVK::kQualcomm;
176 case 0x13B5:
177 return VendorVK::kARM;
178 case 0x1010:
179 return VendorVK::kImgTec;
180 case 0x1002:
181 case 0x1022:
182 return VendorVK::kAMD;
183 case 0x10DE:
184 return VendorVK::kNvidia;
185 case 0x8086: // :)
186 return VendorVK::kIntel;
187 case 0x106B:
188 return VendorVK::kApple;
189 case 0x19E5:
190 return VendorVK::kHuawei;
191 case 0x144D:
192 return VendorVK::kSamsung;
193 }
194 // Check if the ID is a known Khronos vendor.
195 switch (vendor) {
196 case VK_VENDOR_ID_MESA:
197 return VendorVK::kMesa;
198 // There are others but have never been observed. These can be added as
199 // needed.
200 }
201 return VendorVK::kUnknown;
202}
203
204constexpr const char* VendorToString(VendorVK vendor) {
205 switch (vendor) {
207 return "Unknown";
209 return "Google";
211 return "Qualcomm";
212 case VendorVK::kARM:
213 return "ARM";
215 return "ImgTec PowerVR";
216 case VendorVK::kAMD:
217 return "AMD";
219 return "Nvidia";
220 case VendorVK::kIntel:
221 return "Intel";
222 case VendorVK::kMesa:
223 return "Mesa";
224 case VendorVK::kApple:
225 return "Apple";
227 return "Huawei";
229 return "Samsung";
230 }
232}
233
234constexpr const char* DeviceTypeToString(DeviceTypeVK type) {
235 switch (type) {
237 return "Unknown";
239 return "Integrated GPU";
241 return "Discrete GPU";
243 return "Virtual GPU";
245 return "CPU";
246 }
248}
249
250constexpr DeviceTypeVK ToDeviceType(const vk::PhysicalDeviceType& type) {
251 switch (type) {
252 case vk::PhysicalDeviceType::eOther:
254 case vk::PhysicalDeviceType::eIntegratedGpu:
256 case vk::PhysicalDeviceType::eDiscreteGpu:
258 case vk::PhysicalDeviceType::eVirtualGpu:
260 case vk::PhysicalDeviceType::eCpu:
261 return DeviceTypeVK::kCPU;
262 break;
263 }
265}
266
267DriverInfoVK::DriverInfoVK(const vk::PhysicalDevice& device) {
268 auto props = device.getProperties();
269 api_version_ = Version{VK_API_VERSION_MAJOR(props.apiVersion),
270 VK_API_VERSION_MINOR(props.apiVersion),
271 VK_API_VERSION_PATCH(props.apiVersion)};
272 vendor_ = IdentifyVendor(props.vendorID);
273 if (vendor_ == VendorVK::kUnknown) {
274 FML_LOG(WARNING) << "Unknown GPU Driver Vendor: " << props.vendorID
275 << ". This is not an error.";
276 }
277 type_ = ToDeviceType(props.deviceType);
278 if (props.deviceName.data() != nullptr) {
279 driver_name_ = props.deviceName.data();
280 }
281
282 switch (vendor_) {
284 adreno_gpu_ = GetAdrenoVersion(driver_name_);
285 break;
286 case VendorVK::kARM:
287 mali_gpu_ = GetMaliVersion(driver_name_);
288 break;
290 powervr_gpu_ = GetPowerVRVersion(driver_name_);
291 break;
292 default:
293 break;
294 }
295}
296
298
300 return api_version_;
301}
302
304 return vendor_;
305}
306
308 return type_;
309}
310
311const std::string& DriverInfoVK::GetDriverName() const {
312 return driver_name_;
313}
314
316 std::vector<std::pair<std::string, std::string>> items;
317 items.emplace_back("Name", driver_name_);
318 items.emplace_back("API Version", api_version_.ToString());
319 items.emplace_back("Vendor", VendorToString(vendor_));
320 items.emplace_back("Device Type", DeviceTypeToString(type_));
321 items.emplace_back("Is Emulator", std::to_string(IsEmulator()));
322
323 size_t padding = 0;
324
325 for (const auto& item : items) {
326 padding = std::max(padding, item.first.size());
327 }
328
329 padding += 1;
330
331 std::stringstream stream;
332
333 stream << std::endl;
334
335 stream << "--- Driver Information ------------------------------------------";
336
337 stream << std::endl;
338
339 for (const auto& item : items) {
340 stream << "| " << std::setw(static_cast<int>(padding)) << item.first
341 << std::setw(0) << ": " << item.second << std::endl;
342 }
343
344 stream << "-----------------------------------------------------------------";
345
346 FML_LOG(IMPORTANT) << stream.str();
347}
348
350#if FML_OS_ANDROID
351 // Google SwiftShader on Android.
352 if (type_ == DeviceTypeVK::kCPU && vendor_ == VendorVK::kGoogle &&
353 driver_name_.find("SwiftShader") != std::string::npos) {
354 return true;
355 }
356#endif // FML_OS_ANDROID
357 return false;
358}
359
361 // Fall back to OpenGL ES on older Adreno devices that require additional
362 // workarounds in the Impeller Vulkan back end such as disabling framebuffer
363 // fetch.
364 if (adreno_gpu_ && *adreno_gpu_ <= AdrenoGPU::kAdreno630) {
365 return true;
366 }
367
368 // Disable Maleoon series GPUs, see:
369 // https://github.com/flutter/flutter/issues/156623
370 if (vendor_ == VendorVK::kHuawei) {
371 return true;
372 }
373
374 if (vendor_ == VendorVK::kSamsung) {
375 // The first version of the Xclipse series GPU has reported
376 // bugs, unfortunately all versions of this GPU report the
377 // same driver version. Instead we use the Vulkan version
378 // as a proxy, assuming that any newer devices would not
379 // lower the supported Vulkan API level.
380 // See
381 // https://vulkan.gpuinfo.org/listreports.php?devicename=samsung+SM-S906B&platform=android
382 // https://github.com/flutter/flutter/issues/161334
383 return !api_version_.IsAtLeast(Version{1, 3, 0});
384 }
385
386 // https://github.com/flutter/flutter/issues/161122
387 // https://github.com/flutter/flutter/issues/160960
388 // https://github.com/flutter/flutter/issues/160866
389 // https://github.com/flutter/flutter/issues/160804
390 // https://github.com/flutter/flutter/issues/160406
391 if (powervr_gpu_.has_value() && powervr_gpu_.value() < PowerVRGPU::kBXE) {
392 return true;
393 }
394 return false;
395}
396
397std::optional<MaliGPU> DriverInfoVK::GetMaliGPUInfo() const {
398 return mali_gpu_;
399}
400
401std::optional<AdrenoGPU> DriverInfoVK::GetAdrenoGPUInfo() const {
402 return adreno_gpu_;
403}
404
405std::optional<PowerVRGPU> DriverInfoVK::GetPowerVRGPUInfo() const {
406 return powervr_gpu_;
407}
408
409} // 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)
PowerVRGPU GetPowerVRVersion(std::string_view version)
constexpr const char * VendorToString(VendorVK vendor)
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