Flutter Impeller
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 
12 #include "flutter/fml/build_config.h"
13 
14 namespace impeller {
15 
16 const std::unordered_map<std::string_view, AdrenoGPU> kAdrenoVersions = {
17  // X
18  // Note: I don't know if these strings actually match as there don't seem to
19  // be any android devices that use these GPUs.
20  {"X185", AdrenoGPU::kAdrenoX185},
21  {"X145", AdrenoGPU::kAdrenoX145},
22  // 700
23  {"750", AdrenoGPU::kAdreno750},
24  {"740", AdrenoGPU::kAdreno740},
25  {"735", AdrenoGPU::kAdreno735},
26  {"721", AdrenoGPU::kAdreno732},
27  {"730", AdrenoGPU::kAdreno730},
28  {"725", AdrenoGPU::kAdreno725},
29  {"720", AdrenoGPU::kAdreno720},
30  {"710", AdrenoGPU::kAdreno710},
31  {"702", AdrenoGPU::kAdreno702},
32 
33  // 600
34  {"695", AdrenoGPU::kAdreno695},
35  {"690", AdrenoGPU::kAdreno690},
36  {"685", AdrenoGPU::kAdreno685},
37  {"680", AdrenoGPU::kAdreno680},
38  {"675", AdrenoGPU::kAdreno675},
39  {"663", AdrenoGPU::kAdreno663},
40  {"660", AdrenoGPU::kAdreno660},
41  {"650", AdrenoGPU::kAdreno650},
42  {"644", AdrenoGPU::kAdreno644},
43  {"643L", AdrenoGPU::kAdreno643L},
44  {"642", AdrenoGPU::kAdreno642},
45  {"642L", AdrenoGPU::kAdreno642L},
46  {"640", AdrenoGPU::kAdreno640},
47  {"630", AdrenoGPU::kAdreno630},
48  {"620", AdrenoGPU::kAdreno620},
49  {"619", AdrenoGPU::kAdreno619},
50  {"619L", AdrenoGPU::kAdreno619L},
51  {"618", AdrenoGPU::kAdreno618},
52  {"616", AdrenoGPU::kAdreno616},
53  {"615", AdrenoGPU::kAdreno615},
54  {"613", AdrenoGPU::kAdreno613},
55  {"612", AdrenoGPU::kAdreno612},
56  {"610", AdrenoGPU::kAdreno610},
57  {"608", AdrenoGPU::kAdreno608},
58  {"605", AdrenoGPU::kAdreno605},
59  // 500
60  {"540", AdrenoGPU::kAdreno540},
61  {"530", AdrenoGPU::kAdreno530},
62  {"512", AdrenoGPU::kAdreno512},
63  {"510", AdrenoGPU::kAdreno510},
64  {"509", AdrenoGPU::kAdreno509},
65  {"508", AdrenoGPU::kAdreno508},
66  {"506", AdrenoGPU::kAdreno506},
67  {"505", AdrenoGPU::kAdreno505},
68  {"504", AdrenoGPU::kAdreno504},
69 };
70 
71 const std::unordered_map<std::string_view, MaliGPU> kMaliVersions = {
72  // 5th Gen.
73  {"G925", MaliGPU::kG925},
74  {"G725", MaliGPU::kG725},
75  {"G625", MaliGPU::kG625},
76  {"G720", MaliGPU::kG720},
77  {"G620", MaliGPU::kG620},
78 
79  // Valhall
80  // Note: there is an Immortalis-G715 a Mali-G715
81  {"G715", MaliGPU::kG715},
82  {"G615", MaliGPU::kG615},
83  {"G710", MaliGPU::kG710},
84  {"G610", MaliGPU::kG610},
85  {"G510", MaliGPU::kG510},
86  {"G310", MaliGPU::kG310},
87  {"G78", MaliGPU::kG78},
88  {"G68", MaliGPU::kG68},
89  {"G77", MaliGPU::kG77},
90  {"G57", MaliGPU::kG57},
91 
92  // Bifrost
93  {"G76", MaliGPU::kG76},
94  {"G72", MaliGPU::kG72},
95  {"G52", MaliGPU::kG52},
96  {"G71", MaliGPU::kG71},
97  {"G51", MaliGPU::kG51},
98  {"G31", MaliGPU::kG31},
99 
100  // These might be Vulkan 1.0 Only.
101  {"T880", MaliGPU::kT880},
102  {"T860", MaliGPU::kT860},
103  {"T830", MaliGPU::kT830},
104  {"T820", MaliGPU::kT820},
105  {"T760", MaliGPU::kT760},
106 };
107 
108 AdrenoGPU GetAdrenoVersion(std::string_view version) {
109  /// The format that Adreno names follow is "Adreno (TM) VERSION".
110  auto paren_pos = version.find("Adreno (TM) ");
111  if (paren_pos == std::string::npos) {
112  return AdrenoGPU::kUnknown;
113  }
114  auto version_string = version.substr(paren_pos + 12);
115  const auto& result = kAdrenoVersions.find(version_string);
116  if (result == kAdrenoVersions.end()) {
117  return AdrenoGPU::kUnknown;
118  }
119  return result->second;
120 }
121 
122 MaliGPU GetMaliVersion(std::string_view version) {
123  // These names are usually Mali-VERSION or Mali-Version-EXTRA_CRAP.
124  auto dash_pos = version.find("Mali-");
125  if (dash_pos == std::string::npos) {
126  return MaliGPU::kUnknown;
127  }
128  auto version_string_with_trailing = version.substr(dash_pos + 5);
129  // Remove any trailing crap if present.
130  auto more_dash_pos = version_string_with_trailing.find("-");
131  if (more_dash_pos != std::string::npos) {
132  version_string_with_trailing =
133  version_string_with_trailing.substr(0, more_dash_pos);
134  }
135 
136  const auto& result = kMaliVersions.find(version_string_with_trailing);
137  if (result == kMaliVersions.end()) {
138  return MaliGPU::kUnknown;
139  }
140  return result->second;
141 }
142 
143 constexpr VendorVK IdentifyVendor(uint32_t vendor) {
144  // Check if the vendor has a PCI ID:
145  // https://pcisig.com/membership/member-companies
146  switch (vendor) {
147  case 0x1AE0:
148  return VendorVK::kGoogle;
149  case 0x168C:
150  case 0x17CB:
151  case 0x1969:
152  case 0x5143:
153  return VendorVK::kQualcomm;
154  case 0x13B5:
155  return VendorVK::kARM;
156  case 0x1010:
157  return VendorVK::kImgTec;
158  case 0x1002:
159  case 0x1022:
160  return VendorVK::kAMD;
161  case 0x10DE:
162  return VendorVK::kNvidia;
163  case 0x8086: // :)
164  return VendorVK::kIntel;
165  case 0x106B:
166  return VendorVK::kApple;
167  case 0x19E5:
168  return VendorVK::kHuawei;
169  }
170  // Check if the ID is a known Khronos vendor.
171  switch (vendor) {
172  case VK_VENDOR_ID_MESA:
173  return VendorVK::kMesa;
174  // There are others but have never been observed. These can be added as
175  // needed.
176  }
177  return VendorVK::kUnknown;
178 }
179 
180 constexpr const char* VendorToString(VendorVK vendor) {
181  switch (vendor) {
182  case VendorVK::kUnknown:
183  return "Unknown";
184  case VendorVK::kGoogle:
185  return "Google";
186  case VendorVK::kQualcomm:
187  return "Qualcomm";
188  case VendorVK::kARM:
189  return "ARM";
190  case VendorVK::kImgTec:
191  return "ImgTec PowerVR";
192  case VendorVK::kAMD:
193  return "AMD";
194  case VendorVK::kNvidia:
195  return "Nvidia";
196  case VendorVK::kIntel:
197  return "Intel";
198  case VendorVK::kMesa:
199  return "Mesa";
200  case VendorVK::kApple:
201  return "Apple";
202  case VendorVK::kHuawei:
203  return "Huawei";
204  }
205  FML_UNREACHABLE();
206 }
207 
208 constexpr const char* DeviceTypeToString(DeviceTypeVK type) {
209  switch (type) {
211  return "Unknown";
213  return "Integrated GPU";
215  return "Discrete GPU";
217  return "Virtual GPU";
218  case DeviceTypeVK::kCPU:
219  return "CPU";
220  }
221  FML_UNREACHABLE();
222 }
223 
224 constexpr DeviceTypeVK ToDeviceType(const vk::PhysicalDeviceType& type) {
225  switch (type) {
226  case vk::PhysicalDeviceType::eOther:
227  return DeviceTypeVK::kUnknown;
228  case vk::PhysicalDeviceType::eIntegratedGpu:
230  case vk::PhysicalDeviceType::eDiscreteGpu:
232  case vk::PhysicalDeviceType::eVirtualGpu:
234  case vk::PhysicalDeviceType::eCpu:
235  return DeviceTypeVK::kCPU;
236  break;
237  }
238  return DeviceTypeVK::kUnknown;
239 }
240 
241 DriverInfoVK::DriverInfoVK(const vk::PhysicalDevice& device) {
242  auto props = device.getProperties();
243  api_version_ = Version{VK_API_VERSION_MAJOR(props.apiVersion),
244  VK_API_VERSION_MINOR(props.apiVersion),
245  VK_API_VERSION_PATCH(props.apiVersion)};
246  vendor_ = IdentifyVendor(props.vendorID);
247  if (vendor_ == VendorVK::kUnknown) {
248  FML_LOG(WARNING) << "Unknown GPU Driver Vendor: " << props.vendorID
249  << ". This is not an error.";
250  }
251  type_ = ToDeviceType(props.deviceType);
252  if (props.deviceName.data() != nullptr) {
253  driver_name_ = props.deviceName.data();
254  }
255 
256  switch (vendor_) {
257  case VendorVK::kQualcomm:
258  adreno_gpu_ = GetAdrenoVersion(driver_name_);
259  break;
260  case VendorVK::kARM:
261  mali_gpu_ = GetMaliVersion(driver_name_);
262  break;
263  default:
264  break;
265  }
266 }
267 
268 DriverInfoVK::~DriverInfoVK() = default;
269 
271  return api_version_;
272 }
273 
275  return vendor_;
276 }
277 
279  return type_;
280 }
281 
282 const std::string& DriverInfoVK::GetDriverName() const {
283  return driver_name_;
284 }
285 
287  std::vector<std::pair<std::string, std::string>> items;
288  items.emplace_back("Name", driver_name_);
289  items.emplace_back("API Version", api_version_.ToString());
290  items.emplace_back("Vendor", VendorToString(vendor_));
291  items.emplace_back("Device Type", DeviceTypeToString(type_));
292  items.emplace_back("Is Emulator", std::to_string(IsEmulator()));
293 
294  size_t padding = 0;
295 
296  for (const auto& item : items) {
297  padding = std::max(padding, item.first.size());
298  }
299 
300  padding += 1;
301 
302  std::stringstream stream;
303 
304  stream << std::endl;
305 
306  stream << "--- Driver Information ------------------------------------------";
307 
308  stream << std::endl;
309 
310  for (const auto& item : items) {
311  stream << "| " << std::setw(static_cast<int>(padding)) << item.first
312  << std::setw(0) << ": " << item.second << std::endl;
313  }
314 
315  stream << "-----------------------------------------------------------------";
316 
317  FML_LOG(IMPORTANT) << stream.str();
318 }
319 
321 #if FML_OS_ANDROID
322  // Google SwiftShader on Android.
323  if (type_ == DeviceTypeVK::kCPU && vendor_ == VendorVK::kGoogle &&
324  driver_name_.find("SwiftShader") != std::string::npos) {
325  return true;
326  }
327 #endif // FML_OS_ANDROID
328  return false;
329 }
330 
332  if (adreno_gpu_.has_value()) {
333  AdrenoGPU adreno = adreno_gpu_.value();
334  // See:
335  // https://github.com/flutter/flutter/issues/154103
336  //
337  // Reports "VK_INCOMPLETE" when compiling certain entity shader with
338  // vkCreateGraphicsPipelines, which is not a valid return status.
339  // See https://github.com/flutter/flutter/issues/155185 .
340  //
341  // https://github.com/flutter/flutter/issues/155185
342  // Unknown crashes but device is not easily acquirable.
343  switch (adreno) {
366  return true;
367  default:
368  return false;
369  }
370  }
371  // Disable Maleoon series GPUs, see:
372  // https://github.com/flutter/flutter/issues/156623
373  if (vendor_ == VendorVK::kHuawei) {
374  return true;
375  }
376  return false;
377 }
378 
379 } // namespace impeller
impeller::AdrenoGPU::kAdreno685
@ kAdreno685
impeller::MaliGPU::kG51
@ kG51
impeller::MaliGPU::kG310
@ kG310
impeller::AdrenoGPU::kAdreno530
@ kAdreno530
impeller::DriverInfoVK::GetVendor
const VendorVK & GetVendor() const
Get the vendor of the Vulkan implementation. This is a broad check and includes multiple drivers and ...
Definition: driver_info_vk.cc:274
impeller::DeviceTypeVK::kDiscreteGPU
@ kDiscreteGPU
impeller::DeviceTypeVK::kIntegratedGPU
@ kIntegratedGPU
impeller::MaliGPU::kG610
@ kG610
impeller::AdrenoGPU::kAdreno619L
@ kAdreno619L
impeller::AdrenoGPU::kAdreno720
@ kAdreno720
impeller::MaliGPU::kT820
@ kT820
impeller::DriverInfoVK::~DriverInfoVK
~DriverInfoVK()
impeller::AdrenoGPU::kAdreno644
@ kAdreno644
impeller::DriverInfoVK::GetDeviceType
const DeviceTypeVK & GetDeviceType() const
Get the device type. Typical use might be to check if the device is a CPU implementation.
Definition: driver_info_vk.cc:278
impeller::MaliGPU::kG710
@ kG710
impeller::AdrenoGPU::kAdreno735
@ kAdreno735
impeller::DriverInfoVK::DriverInfoVK
DriverInfoVK(const vk::PhysicalDevice &device)
Definition: driver_info_vk.cc:241
impeller::AdrenoGPU::kAdreno509
@ kAdreno509
impeller::DriverInfoVK::IsEmulator
bool IsEmulator() const
Determines if the driver represents an emulator. There is no definitive way to tell if a driver is an...
Definition: driver_info_vk.cc:320
impeller::MaliGPU::kG68
@ kG68
impeller::MaliGPU::kG715
@ kG715
impeller::AdrenoGPU::kAdreno618
@ kAdreno618
impeller::AdrenoGPU::kAdreno663
@ kAdreno663
impeller::DriverInfoVK::DumpToLog
void DumpToLog() const
Dumps the current driver info to the log.
Definition: driver_info_vk.cc:286
impeller::MaliGPU::kT760
@ kT760
impeller::AdrenoGPU::kAdreno730
@ kAdreno730
impeller::AdrenoGPU::kAdreno710
@ kAdreno710
padding
Vector2 padding
The halo padding in source space.
Definition: gaussian_blur_filter_contents.cc:85
impeller::MaliGPU::kG925
@ kG925
impeller::AdrenoGPU::kAdreno660
@ kAdreno660
impeller::AdrenoGPU::kAdrenoX145
@ kAdrenoX145
impeller::GetMaliVersion
MaliGPU GetMaliVersion(std::string_view version)
Definition: driver_info_vk.cc:122
impeller::Version
Definition: version.h:16
impeller::AdrenoGPU::kAdreno642
@ kAdreno642
impeller::AdrenoGPU::kAdreno650
@ kAdreno650
impeller::MaliGPU::kG620
@ kG620
impeller::AdrenoGPU::kAdreno640
@ kAdreno640
impeller::AdrenoGPU::kAdreno725
@ kAdreno725
impeller::AdrenoGPU::kAdreno680
@ kAdreno680
impeller::MaliGPU::kG52
@ kG52
impeller::MaliGPU::kG625
@ kG625
impeller::AdrenoGPU::kAdreno504
@ kAdreno504
impeller::AdrenoGPU
AdrenoGPU
Definition: driver_info_vk.h:14
impeller::VendorVK::kARM
@ kARM
impeller::VendorVK::kGoogle
@ kGoogle
impeller::AdrenoGPU::kAdreno615
@ kAdreno615
impeller::AdrenoGPU::kAdreno643L
@ kAdreno643L
impeller::VendorVK::kAMD
@ kAMD
impeller::MaliGPU::kG76
@ kG76
impeller::AdrenoGPU::kAdreno690
@ kAdreno690
impeller::MaliGPU
MaliGPU
Definition: driver_info_vk.h:73
impeller::AdrenoGPU::kAdreno620
@ kAdreno620
impeller::AdrenoGPU::kAdreno505
@ kAdreno505
impeller::AdrenoGPU::kAdreno675
@ kAdreno675
impeller::Version::ToString
std::string ToString() const
Definition: version.cc:27
impeller::VendorVK::kMesa
@ kMesa
impeller::VendorVK::kApple
@ kApple
impeller::AdrenoGPU::kAdreno506
@ kAdreno506
impeller::VendorVK::kImgTec
@ kImgTec
impeller::AdrenoGPU::kAdreno613
@ kAdreno613
type
GLenum type
Definition: blit_command_gles.cc:127
impeller::VendorToString
constexpr const char * VendorToString(VendorVK vendor)
Definition: driver_info_vk.cc:180
impeller::AdrenoGPU::kUnknown
@ kUnknown
impeller::MaliGPU::kUnknown
@ kUnknown
impeller::MaliGPU::kT830
@ kT830
impeller::AdrenoGPU::kAdreno642L
@ kAdreno642L
impeller::MaliGPU::kG720
@ kG720
impeller::MaliGPU::kG72
@ kG72
impeller::VendorVK::kQualcomm
@ kQualcomm
impeller::AdrenoGPU::kAdreno732
@ kAdreno732
impeller::DeviceTypeVK::kVirtualGPU
@ kVirtualGPU
driver_info_vk.h
impeller::AdrenoGPU::kAdreno512
@ kAdreno512
impeller::kMaliVersions
const std::unordered_map< std::string_view, MaliGPU > kMaliVersions
Definition: driver_info_vk.cc:71
impeller::DriverInfoVK::GetAPIVersion
const Version & GetAPIVersion() const
Gets the Vulkan API version. Should be at or above Vulkan 1.1 which is the Impeller baseline.
Definition: driver_info_vk.cc:270
impeller::MaliGPU::kG615
@ kG615
impeller::AdrenoGPU::kAdreno608
@ kAdreno608
impeller::AdrenoGPU::kAdreno702
@ kAdreno702
impeller::AdrenoGPU::kAdreno510
@ kAdreno510
impeller::DeviceTypeVK
DeviceTypeVK
Definition: driver_info_vk.h:135
impeller::AdrenoGPU::kAdreno616
@ kAdreno616
impeller::AdrenoGPU::kAdreno619
@ kAdreno619
impeller::DeviceTypeVK::kCPU
@ kCPU
impeller::VendorVK::kIntel
@ kIntel
impeller::MaliGPU::kG57
@ kG57
impeller::VendorVK
VendorVK
Definition: driver_info_vk.h:111
impeller::AdrenoGPU::kAdreno630
@ kAdreno630
impeller::VendorVK::kUnknown
@ kUnknown
impeller::IdentifyVendor
constexpr VendorVK IdentifyVendor(uint32_t vendor)
Definition: driver_info_vk.cc:143
impeller::MaliGPU::kG71
@ kG71
impeller::AdrenoGPU::kAdreno508
@ kAdreno508
impeller::VendorVK::kHuawei
@ kHuawei
impeller::AdrenoGPU::kAdreno695
@ kAdreno695
impeller::AdrenoGPU::kAdreno610
@ kAdreno610
impeller::AdrenoGPU::kAdreno750
@ kAdreno750
impeller::MaliGPU::kG31
@ kG31
impeller::MaliGPU::kT860
@ kT860
impeller::GetAdrenoVersion
AdrenoGPU GetAdrenoVersion(std::string_view version)
Definition: driver_info_vk.cc:108
impeller::AdrenoGPU::kAdreno740
@ kAdreno740
impeller::VendorVK::kNvidia
@ kNvidia
impeller::AdrenoGPU::kAdrenoX185
@ kAdrenoX185
impeller::DeviceTypeVK::kUnknown
@ kUnknown
impeller::DriverInfoVK::GetDriverName
const std::string & GetDriverName() const
Get the self-reported name of the graphics driver.
Definition: driver_info_vk.cc:282
impeller::AdrenoGPU::kAdreno605
@ kAdreno605
impeller::kAdrenoVersions
const std::unordered_map< std::string_view, AdrenoGPU > kAdrenoVersions
Definition: driver_info_vk.cc:16
impeller::MaliGPU::kG78
@ kG78
impeller::MaliGPU::kG77
@ kG77
impeller::DeviceTypeToString
constexpr const char * DeviceTypeToString(DeviceTypeVK type)
Definition: driver_info_vk.cc:208
impeller::MaliGPU::kT880
@ kT880
impeller::MaliGPU::kG510
@ kG510
impeller
Definition: allocation.cc:12
impeller::DriverInfoVK::IsKnownBadDriver
bool IsKnownBadDriver() const
Determines if the driver has been tested and determined to be non-functional.
Definition: driver_info_vk.cc:331
impeller::MaliGPU::kG725
@ kG725
impeller::AdrenoGPU::kAdreno540
@ kAdreno540
impeller::ToDeviceType
constexpr DeviceTypeVK ToDeviceType(const vk::PhysicalDeviceType &type)
Definition: driver_info_vk.cc:224
impeller::AdrenoGPU::kAdreno612
@ kAdreno612