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