• 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_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