• 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 {
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         default:
51             return "Unknown (" + std::to_string(vendor) + ")";
52     }
53 }
54 }  // anonymous namespace
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 
ParseAMDBrahmaDriverVersion(const std::string & content,std::string * version)163 bool ParseAMDBrahmaDriverVersion(const std::string &content, std::string *version)
164 {
165     const size_t begin = content.find_first_of("0123456789");
166     if (begin == std::string::npos)
167     {
168         return false;
169     }
170 
171     const size_t end = content.find_first_not_of("0123456789.", begin);
172     if (end == std::string::npos)
173     {
174         *version = content.substr(begin);
175     }
176     else
177     {
178         *version = content.substr(begin, end - begin);
179     }
180     return true;
181 }
182 
ParseAMDCatalystDriverVersion(const std::string & content,std::string * version)183 bool ParseAMDCatalystDriverVersion(const std::string &content, std::string *version)
184 {
185     std::istringstream stream(content);
186 
187     std::string line;
188     while (std::getline(stream, line))
189     {
190         static const char kReleaseVersion[] = "ReleaseVersion=";
191         if (line.compare(0, std::strlen(kReleaseVersion), kReleaseVersion) != 0)
192         {
193             continue;
194         }
195 
196         if (ParseAMDBrahmaDriverVersion(line, version))
197         {
198             return true;
199         }
200     }
201     return false;
202 }
203 
ParseMacMachineModel(const std::string & identifier,std::string * type,int32_t * major,int32_t * minor)204 bool ParseMacMachineModel(const std::string &identifier,
205                           std::string *type,
206                           int32_t *major,
207                           int32_t *minor)
208 {
209     size_t numberLoc = identifier.find_first_of("0123456789");
210     if (numberLoc == std::string::npos)
211     {
212         return false;
213     }
214 
215     size_t commaLoc = identifier.find(',', numberLoc);
216     if (commaLoc == std::string::npos || commaLoc >= identifier.size())
217     {
218         return false;
219     }
220 
221     const char *numberPtr = &identifier[numberLoc];
222     const char *commaPtr  = &identifier[commaLoc + 1];
223     char *endPtr          = nullptr;
224 
225     int32_t majorTmp = static_cast<int32_t>(std::strtol(numberPtr, &endPtr, 10));
226     if (endPtr == numberPtr)
227     {
228         return false;
229     }
230 
231     int32_t minorTmp = static_cast<int32_t>(std::strtol(commaPtr, &endPtr, 10));
232     if (endPtr == commaPtr)
233     {
234         return false;
235     }
236 
237     *major = majorTmp;
238     *minor = minorTmp;
239     *type  = identifier.substr(0, numberLoc);
240 
241     return true;
242 }
243 
CMDeviceIDToDeviceAndVendorID(const std::string & id,uint32_t * vendorId,uint32_t * deviceId)244 bool CMDeviceIDToDeviceAndVendorID(const std::string &id, uint32_t *vendorId, uint32_t *deviceId)
245 {
246     unsigned int vendor = 0;
247     unsigned int device = 0;
248 
249     bool success = id.length() >= 21 && HexStringToUInt(id.substr(8, 4), &vendor) &&
250                    HexStringToUInt(id.substr(17, 4), &device);
251 
252     *vendorId = vendor;
253     *deviceId = device;
254     return success;
255 }
256 
GetDualGPUInfo(SystemInfo * info)257 void GetDualGPUInfo(SystemInfo *info)
258 {
259     ASSERT(!info->gpus.empty());
260 
261     // On dual-GPU systems we assume the non-Intel GPU is the graphics one.
262     int active    = 0;
263     bool hasIntel = false;
264     for (size_t i = 0; i < info->gpus.size(); ++i)
265     {
266         if (IsIntel(info->gpus[i].vendorId))
267         {
268             hasIntel = true;
269         }
270         if (IsIntel(info->gpus[active].vendorId))
271         {
272             active = static_cast<int>(i);
273         }
274     }
275 
276     // Assume that a combination of NVIDIA or AMD with Intel means Optimus or AMD Switchable
277     info->activeGPUIndex  = active;
278     info->isOptimus       = hasIntel && IsNVIDIA(info->gpus[active].vendorId);
279     info->isAMDSwitchable = hasIntel && IsAMD(info->gpus[active].vendorId);
280 }
281 
PrintSystemInfo(const SystemInfo & info)282 void PrintSystemInfo(const SystemInfo &info)
283 {
284     std::cout << info.gpus.size() << " GPUs:\n";
285 
286     for (size_t i = 0; i < info.gpus.size(); i++)
287     {
288         const auto &gpu = info.gpus[i];
289 
290         std::cout << "  " << i << " - " << VendorName(gpu.vendorId) << " device id: 0x" << std::hex
291                   << std::uppercase << gpu.deviceId << std::dec << "\n";
292         if (!gpu.driverVendor.empty())
293         {
294             std::cout << "       Driver Vendor: " << gpu.driverVendor << "\n";
295         }
296         if (!gpu.driverVersion.empty())
297         {
298             std::cout << "       Driver Version: " << gpu.driverVersion << "\n";
299         }
300         if (!gpu.driverDate.empty())
301         {
302             std::cout << "       Driver Date: " << gpu.driverDate << "\n";
303         }
304     }
305 
306     std::cout << "\n";
307     std::cout << "Active GPU: " << info.activeGPUIndex << "\n";
308 
309     std::cout << "\n";
310     std::cout << "Optimus: " << (info.isOptimus ? "true" : "false") << "\n";
311     std::cout << "AMD Switchable: " << (info.isAMDSwitchable ? "true" : "false") << "\n";
312 
313     std::cout << "\n";
314     if (!info.machineManufacturer.empty())
315     {
316         std::cout << "Machine Manufacturer: " << info.machineManufacturer << "\n";
317     }
318     if (!info.machineModelName.empty())
319     {
320         std::cout << "Machine Model: " << info.machineModelName << "\n";
321     }
322     if (!info.machineModelVersion.empty())
323     {
324         std::cout << "Machine Model Version: " << info.machineModelVersion << "\n";
325     }
326     std::cout << std::endl;
327 }
328 
ParseNvidiaDriverVersion(uint32_t version)329 VersionInfo ParseNvidiaDriverVersion(uint32_t version)
330 {
331     return {
332         version >> 22,         // major
333         version >> 14 & 0xff,  // minor
334         version >> 6 & 0xff,   // subMinor
335         version & 0x3f         // patch
336     };
337 }
338 }  // namespace angle
339