• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ARM:
29             return "ARM";
30         case kVendorID_Broadcom:
31             return "Broadcom";
32         case kVendorID_GOOGLE:
33             return "Google";
34         case kVendorID_ImgTec:
35             return "ImgTec";
36         case kVendorID_Intel:
37             return "Intel";
38         case kVendorID_Kazan:
39             return "Kazan";
40         case kVendorID_NVIDIA:
41             return "NVIDIA";
42         case kVendorID_Qualcomm:
43             return "Qualcomm";
44         case kVendorID_VeriSilicon:
45             return "VeriSilicon";
46         case kVendorID_Vivante:
47             return "Vivante";
48         case kVendorID_VMWare:
49             return "VMWare";
50         case kVendorID_Apple:
51             return "Apple";
52         default:
53             return "Unknown (" + std::to_string(vendor) + ")";
54     }
55 }
56 }  // anonymous namespace
57 GPUDeviceInfo::GPUDeviceInfo() = default;
58 
59 GPUDeviceInfo::~GPUDeviceInfo() = default;
60 
61 GPUDeviceInfo::GPUDeviceInfo(const GPUDeviceInfo &other) = default;
62 
63 SystemInfo::SystemInfo() = default;
64 
65 SystemInfo::~SystemInfo() = default;
66 
67 SystemInfo::SystemInfo(const SystemInfo &other) = default;
68 
hasNVIDIAGPU() const69 bool SystemInfo::hasNVIDIAGPU() const
70 {
71     for (const GPUDeviceInfo &gpu : gpus)
72     {
73         if (IsNVIDIA(gpu.vendorId))
74         {
75             return true;
76         }
77     }
78     return false;
79 }
80 
hasIntelGPU() const81 bool SystemInfo::hasIntelGPU() const
82 {
83     for (const GPUDeviceInfo &gpu : gpus)
84     {
85         if (IsIntel(gpu.vendorId))
86         {
87             return true;
88         }
89     }
90     return false;
91 }
92 
hasAMDGPU() const93 bool SystemInfo::hasAMDGPU() const
94 {
95     for (const GPUDeviceInfo &gpu : gpus)
96     {
97         if (IsAMD(gpu.vendorId))
98         {
99             return true;
100         }
101     }
102     return false;
103 }
104 
IsAMD(VendorID vendorId)105 bool IsAMD(VendorID vendorId)
106 {
107     return vendorId == kVendorID_AMD;
108 }
109 
IsARM(VendorID vendorId)110 bool IsARM(VendorID vendorId)
111 {
112     return vendorId == kVendorID_ARM;
113 }
114 
IsBroadcom(VendorID vendorId)115 bool IsBroadcom(VendorID vendorId)
116 {
117     return vendorId == kVendorID_Broadcom;
118 }
119 
IsImgTec(VendorID vendorId)120 bool IsImgTec(VendorID vendorId)
121 {
122     return vendorId == kVendorID_ImgTec;
123 }
124 
IsKazan(VendorID vendorId)125 bool IsKazan(VendorID vendorId)
126 {
127     return vendorId == kVendorID_Kazan;
128 }
129 
IsIntel(VendorID vendorId)130 bool IsIntel(VendorID vendorId)
131 {
132     return vendorId == kVendorID_Intel;
133 }
134 
IsNVIDIA(VendorID vendorId)135 bool IsNVIDIA(VendorID vendorId)
136 {
137     return vendorId == kVendorID_NVIDIA;
138 }
139 
IsQualcomm(VendorID vendorId)140 bool IsQualcomm(VendorID vendorId)
141 {
142     return vendorId == kVendorID_Qualcomm;
143 }
144 
IsGoogle(VendorID vendorId)145 bool IsGoogle(VendorID vendorId)
146 {
147     return vendorId == kVendorID_GOOGLE;
148 }
149 
IsVeriSilicon(VendorID vendorId)150 bool IsVeriSilicon(VendorID vendorId)
151 {
152     return vendorId == kVendorID_VeriSilicon;
153 }
154 
IsVMWare(VendorID vendorId)155 bool IsVMWare(VendorID vendorId)
156 {
157     return vendorId == kVendorID_VMWare;
158 }
159 
IsVivante(VendorID vendorId)160 bool IsVivante(VendorID vendorId)
161 {
162     return vendorId == kVendorID_Vivante;
163 }
164 
IsApple(VendorID vendorId)165 bool IsApple(VendorID vendorId)
166 {
167     return vendorId == kVendorID_Apple;
168 }
169 
ParseAMDBrahmaDriverVersion(const std::string & content,std::string * version)170 bool ParseAMDBrahmaDriverVersion(const std::string &content, std::string *version)
171 {
172     const size_t begin = content.find_first_of("0123456789");
173     if (begin == std::string::npos)
174     {
175         return false;
176     }
177 
178     const size_t end = content.find_first_not_of("0123456789.", begin);
179     if (end == std::string::npos)
180     {
181         *version = content.substr(begin);
182     }
183     else
184     {
185         *version = content.substr(begin, end - begin);
186     }
187     return true;
188 }
189 
ParseAMDCatalystDriverVersion(const std::string & content,std::string * version)190 bool ParseAMDCatalystDriverVersion(const std::string &content, std::string *version)
191 {
192     std::istringstream stream(content);
193 
194     std::string line;
195     while (std::getline(stream, line))
196     {
197         static const char kReleaseVersion[] = "ReleaseVersion=";
198         if (line.compare(0, std::strlen(kReleaseVersion), kReleaseVersion) != 0)
199         {
200             continue;
201         }
202 
203         if (ParseAMDBrahmaDriverVersion(line, version))
204         {
205             return true;
206         }
207     }
208     return false;
209 }
210 
ParseMacMachineModel(const std::string & identifier,std::string * type,int32_t * major,int32_t * minor)211 bool ParseMacMachineModel(const std::string &identifier,
212                           std::string *type,
213                           int32_t *major,
214                           int32_t *minor)
215 {
216     size_t numberLoc = identifier.find_first_of("0123456789");
217     if (numberLoc == std::string::npos)
218     {
219         return false;
220     }
221 
222     size_t commaLoc = identifier.find(',', numberLoc);
223     if (commaLoc == std::string::npos || commaLoc >= identifier.size())
224     {
225         return false;
226     }
227 
228     const char *numberPtr = &identifier[numberLoc];
229     const char *commaPtr  = &identifier[commaLoc + 1];
230     char *endPtr          = nullptr;
231 
232     int32_t majorTmp = static_cast<int32_t>(std::strtol(numberPtr, &endPtr, 10));
233     if (endPtr == numberPtr)
234     {
235         return false;
236     }
237 
238     int32_t minorTmp = static_cast<int32_t>(std::strtol(commaPtr, &endPtr, 10));
239     if (endPtr == commaPtr)
240     {
241         return false;
242     }
243 
244     *major = majorTmp;
245     *minor = minorTmp;
246     *type  = identifier.substr(0, numberLoc);
247 
248     return true;
249 }
250 
CMDeviceIDToDeviceAndVendorID(const std::string & id,uint32_t * vendorId,uint32_t * deviceId)251 bool CMDeviceIDToDeviceAndVendorID(const std::string &id, uint32_t *vendorId, uint32_t *deviceId)
252 {
253     unsigned int vendor = 0;
254     unsigned int device = 0;
255 
256     bool success = id.length() >= 21 && HexStringToUInt(id.substr(8, 4), &vendor) &&
257                    HexStringToUInt(id.substr(17, 4), &device);
258 
259     *vendorId = vendor;
260     *deviceId = device;
261     return success;
262 }
263 
GetDualGPUInfo(SystemInfo * info)264 void GetDualGPUInfo(SystemInfo *info)
265 {
266     ASSERT(!info->gpus.empty());
267 
268     // On dual-GPU systems we assume the non-Intel GPU is the graphics one.
269     int active    = 0;
270     bool hasIntel = false;
271     for (size_t i = 0; i < info->gpus.size(); ++i)
272     {
273         if (IsIntel(info->gpus[i].vendorId))
274         {
275             hasIntel = true;
276         }
277         if (IsIntel(info->gpus[active].vendorId))
278         {
279             active = static_cast<int>(i);
280         }
281     }
282 
283     // Assume that a combination of NVIDIA or AMD with Intel means Optimus or AMD Switchable
284     info->activeGPUIndex  = active;
285     info->isOptimus       = hasIntel && IsNVIDIA(info->gpus[active].vendorId);
286     info->isAMDSwitchable = hasIntel && IsAMD(info->gpus[active].vendorId);
287 }
288 
PrintSystemInfo(const SystemInfo & info)289 void PrintSystemInfo(const SystemInfo &info)
290 {
291     std::cout << info.gpus.size() << " GPUs:\n";
292 
293     for (size_t i = 0; i < info.gpus.size(); i++)
294     {
295         const auto &gpu = info.gpus[i];
296 
297         std::cout << "  " << i << " - " << VendorName(gpu.vendorId) << " device id: 0x" << std::hex
298                   << std::uppercase << gpu.deviceId << std::dec << "\n";
299         if (!gpu.driverVendor.empty())
300         {
301             std::cout << "       Driver Vendor: " << gpu.driverVendor << "\n";
302         }
303         if (!gpu.driverVersion.empty())
304         {
305             std::cout << "       Driver Version: " << gpu.driverVersion << "\n";
306         }
307         if (!gpu.driverDate.empty())
308         {
309             std::cout << "       Driver Date: " << gpu.driverDate << "\n";
310         }
311     }
312 
313     std::cout << "\n";
314     std::cout << "Active GPU: " << info.activeGPUIndex << "\n";
315 
316     std::cout << "\n";
317     std::cout << "Optimus: " << (info.isOptimus ? "true" : "false") << "\n";
318     std::cout << "AMD Switchable: " << (info.isAMDSwitchable ? "true" : "false") << "\n";
319 
320     std::cout << "\n";
321     if (!info.machineManufacturer.empty())
322     {
323         std::cout << "Machine Manufacturer: " << info.machineManufacturer << "\n";
324     }
325     if (!info.machineModelName.empty())
326     {
327         std::cout << "Machine Model: " << info.machineModelName << "\n";
328     }
329     if (!info.machineModelVersion.empty())
330     {
331         std::cout << "Machine Model Version: " << info.machineModelVersion << "\n";
332     }
333     std::cout << std::endl;
334 }
335 
ParseNvidiaDriverVersion(uint32_t version)336 VersionInfo ParseNvidiaDriverVersion(uint32_t version)
337 {
338     return {
339         version >> 22,         // major
340         version >> 14 & 0xff,  // minor
341         version >> 6 & 0xff,   // subMinor
342         version & 0x3f         // patch
343     };
344 }
345 }  // namespace angle
346