1 //
2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // SystemInfo.cpp: implementation of the system-agnostic parts of SystemInfo.h
8
9 #include "gpu_info_util/SystemInfo.h"
10
11 #include <cstring>
12 #include <iostream>
13 #include <sstream>
14
15 #include "common/debug.h"
16 #include "common/string_utils.h"
17
18 namespace angle
19 {
20 namespace
21 {
VendorName(VendorID vendor)22 std::string VendorName(VendorID vendor)
23 {
24 switch (vendor)
25 {
26 case kVendorID_AMD:
27 return "AMD";
28 case kVendorID_Intel:
29 return "Intel";
30 case kVendorID_ImgTec:
31 return "ImgTec";
32 case kVendorID_NVIDIA:
33 return "NVIDIA";
34 case kVendorID_Qualcomm:
35 return "Qualcomm";
36 case kVendorID_Vivante:
37 return "Vivante";
38 case kVendorID_VeriSilicon:
39 return "VeriSilicon";
40 case kVendorID_VMWare:
41 return "VMWare";
42 case kVendorID_Kazan:
43 return "Kazan";
44 default:
45 return "Unknown (" + std::to_string(vendor) + ")";
46 }
47 }
48 } // anonymous namespace
49 GPUDeviceInfo::GPUDeviceInfo() = default;
50
51 GPUDeviceInfo::~GPUDeviceInfo() = default;
52
53 GPUDeviceInfo::GPUDeviceInfo(const GPUDeviceInfo &other) = default;
54
55 SystemInfo::SystemInfo() = default;
56
57 SystemInfo::~SystemInfo() = default;
58
59 SystemInfo::SystemInfo(const SystemInfo &other) = default;
60
hasNVIDIAGPU() const61 bool SystemInfo::hasNVIDIAGPU() const
62 {
63 for (const GPUDeviceInfo &gpu : gpus)
64 {
65 if (IsNVIDIA(gpu.vendorId))
66 {
67 return true;
68 }
69 }
70 return false;
71 }
72
hasIntelGPU() const73 bool SystemInfo::hasIntelGPU() const
74 {
75 for (const GPUDeviceInfo &gpu : gpus)
76 {
77 if (IsIntel(gpu.vendorId))
78 {
79 return true;
80 }
81 }
82 return false;
83 }
84
hasAMDGPU() const85 bool SystemInfo::hasAMDGPU() const
86 {
87 for (const GPUDeviceInfo &gpu : gpus)
88 {
89 if (IsAMD(gpu.vendorId))
90 {
91 return true;
92 }
93 }
94 return false;
95 }
96
IsAMD(VendorID vendorId)97 bool IsAMD(VendorID vendorId)
98 {
99 return vendorId == kVendorID_AMD;
100 }
101
IsARM(VendorID vendorId)102 bool IsARM(VendorID vendorId)
103 {
104 return vendorId == kVendorID_ARM;
105 }
106
IsImgTec(VendorID vendorId)107 bool IsImgTec(VendorID vendorId)
108 {
109 return vendorId == kVendorID_ImgTec;
110 }
111
IsKazan(VendorID vendorId)112 bool IsKazan(VendorID vendorId)
113 {
114 return vendorId == kVendorID_Kazan;
115 }
116
IsIntel(VendorID vendorId)117 bool IsIntel(VendorID vendorId)
118 {
119 return vendorId == kVendorID_Intel;
120 }
121
IsNVIDIA(VendorID vendorId)122 bool IsNVIDIA(VendorID vendorId)
123 {
124 return vendorId == kVendorID_NVIDIA;
125 }
126
IsQualcomm(VendorID vendorId)127 bool IsQualcomm(VendorID vendorId)
128 {
129 return vendorId == kVendorID_Qualcomm;
130 }
131
IsVeriSilicon(VendorID vendorId)132 bool IsVeriSilicon(VendorID vendorId)
133 {
134 return vendorId == kVendorID_VeriSilicon;
135 }
136
IsVMWare(VendorID vendorId)137 bool IsVMWare(VendorID vendorId)
138 {
139 return vendorId == kVendorID_VMWare;
140 }
141
IsVivante(VendorID vendorId)142 bool IsVivante(VendorID vendorId)
143 {
144 return vendorId == kVendorID_Vivante;
145 }
146
ParseAMDBrahmaDriverVersion(const std::string & content,std::string * version)147 bool ParseAMDBrahmaDriverVersion(const std::string &content, std::string *version)
148 {
149 const size_t begin = content.find_first_of("0123456789");
150 if (begin == std::string::npos)
151 {
152 return false;
153 }
154
155 const size_t end = content.find_first_not_of("0123456789.", begin);
156 if (end == std::string::npos)
157 {
158 *version = content.substr(begin);
159 }
160 else
161 {
162 *version = content.substr(begin, end - begin);
163 }
164 return true;
165 }
166
ParseAMDCatalystDriverVersion(const std::string & content,std::string * version)167 bool ParseAMDCatalystDriverVersion(const std::string &content, std::string *version)
168 {
169 std::istringstream stream(content);
170
171 std::string line;
172 while (std::getline(stream, line))
173 {
174 static const char kReleaseVersion[] = "ReleaseVersion=";
175 if (line.compare(0, std::strlen(kReleaseVersion), kReleaseVersion) != 0)
176 {
177 continue;
178 }
179
180 if (ParseAMDBrahmaDriverVersion(line, version))
181 {
182 return true;
183 }
184 }
185 return false;
186 }
187
ParseMacMachineModel(const std::string & identifier,std::string * type,int32_t * major,int32_t * minor)188 bool ParseMacMachineModel(const std::string &identifier,
189 std::string *type,
190 int32_t *major,
191 int32_t *minor)
192 {
193 size_t numberLoc = identifier.find_first_of("0123456789");
194 if (numberLoc == std::string::npos)
195 {
196 return false;
197 }
198
199 size_t commaLoc = identifier.find(',', numberLoc);
200 if (commaLoc == std::string::npos || commaLoc >= identifier.size())
201 {
202 return false;
203 }
204
205 const char *numberPtr = &identifier[numberLoc];
206 const char *commaPtr = &identifier[commaLoc + 1];
207 char *endPtr = nullptr;
208
209 int32_t majorTmp = static_cast<int32_t>(std::strtol(numberPtr, &endPtr, 10));
210 if (endPtr == numberPtr)
211 {
212 return false;
213 }
214
215 int32_t minorTmp = static_cast<int32_t>(std::strtol(commaPtr, &endPtr, 10));
216 if (endPtr == commaPtr)
217 {
218 return false;
219 }
220
221 *major = majorTmp;
222 *minor = minorTmp;
223 *type = identifier.substr(0, numberLoc);
224
225 return true;
226 }
227
CMDeviceIDToDeviceAndVendorID(const std::string & id,uint32_t * vendorId,uint32_t * deviceId)228 bool CMDeviceIDToDeviceAndVendorID(const std::string &id, uint32_t *vendorId, uint32_t *deviceId)
229 {
230 unsigned int vendor = 0;
231 unsigned int device = 0;
232
233 bool success = id.length() >= 21 && HexStringToUInt(id.substr(8, 4), &vendor) &&
234 HexStringToUInt(id.substr(17, 4), &device);
235
236 *vendorId = vendor;
237 *deviceId = device;
238 return success;
239 }
240
FindActiveGPU(SystemInfo * info)241 void FindActiveGPU(SystemInfo *info)
242 {
243 ASSERT(!info->gpus.empty());
244
245 // On dual-GPU systems we assume the non-Intel GPU is the graphics one.
246 int active = 0;
247 bool hasIntel = false;
248 for (size_t i = 0; i < info->gpus.size(); ++i)
249 {
250 if (IsIntel(info->gpus[i].vendorId))
251 {
252 hasIntel = true;
253 }
254 if (IsIntel(info->gpus[active].vendorId))
255 {
256 active = static_cast<int>(i);
257 }
258 }
259
260 // Assume that a combination of NVIDIA or AMD with Intel means Optimus or AMD Switchable
261 info->activeGPUIndex = active;
262 info->isOptimus = hasIntel && IsNVIDIA(info->gpus[active].vendorId);
263 info->isAMDSwitchable = hasIntel && IsAMD(info->gpus[active].vendorId);
264 }
265
PrintSystemInfo(const SystemInfo & info)266 void PrintSystemInfo(const SystemInfo &info)
267 {
268 std::cout << info.gpus.size() << " GPUs:\n";
269
270 for (size_t i = 0; i < info.gpus.size(); i++)
271 {
272 const auto &gpu = info.gpus[i];
273
274 std::cout << " " << i << " - " << VendorName(gpu.vendorId) << " device id: 0x" << std::hex
275 << std::uppercase << gpu.deviceId << std::dec << "\n";
276 if (!gpu.driverVendor.empty())
277 {
278 std::cout << " Driver Vendor: " << gpu.driverVendor << "\n";
279 }
280 if (!gpu.driverVersion.empty())
281 {
282 std::cout << " Driver Version: " << gpu.driverVersion << "\n";
283 }
284 if (!gpu.driverDate.empty())
285 {
286 std::cout << " Driver Date: " << gpu.driverDate << "\n";
287 }
288 }
289
290 std::cout << "\n";
291 std::cout << "Active GPU: " << info.activeGPUIndex << "\n";
292
293 std::cout << "\n";
294 std::cout << "Optimus: " << (info.isOptimus ? "true" : "false") << "\n";
295 std::cout << "AMD Switchable: " << (info.isAMDSwitchable ? "true" : "false") << "\n";
296
297 std::cout << "\n";
298 if (!info.machineManufacturer.empty())
299 {
300 std::cout << "Machine Manufacturer: " << info.machineManufacturer << "\n";
301 }
302 if (!info.machineModelName.empty())
303 {
304 std::cout << "Machine Model: " << info.machineModelName << "\n";
305 }
306 if (!info.machineModelVersion.empty())
307 {
308 std::cout << "Machine Model Version: " << info.machineModelVersion << "\n";
309 }
310 std::cout << std::endl;
311 }
312 } // namespace angle
313