1
2 // Copyright 2019 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 #include "GPUTestConfig.h"
8
9 #include <stdint.h>
10 #include <iostream>
11
12 #include "common/angleutils.h"
13 #include "common/debug.h"
14 #include "common/platform.h"
15 #include "common/string_utils.h"
16 #include "gpu_info_util/SystemInfo.h"
17
18 #if defined(ANGLE_PLATFORM_APPLE)
19 # include "GPUTestConfig_mac.h"
20 #endif
21
22 namespace angle
23 {
24
25 namespace
26 {
27
28 // Generic function call to get the OS version information from any platform
29 // defined below. This function will also cache the OS version info in static
30 // variables.
OperatingSystemVersionNumbers(int32_t * majorVersion,int32_t * minorVersion)31 inline bool OperatingSystemVersionNumbers(int32_t *majorVersion, int32_t *minorVersion)
32 {
33 static int32_t sSavedMajorVersion = -1;
34 static int32_t sSavedMinorVersion = -1;
35 bool ret = false;
36 if (sSavedMajorVersion == -1 || sSavedMinorVersion == -1)
37 {
38 #if defined(ANGLE_PLATFORM_WINDOWS)
39 OSVERSIONINFOEX version_info = {};
40 version_info.dwOSVersionInfoSize = sizeof(version_info);
41 ::GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&version_info));
42 sSavedMajorVersion = version_info.dwMajorVersion;
43 *majorVersion = sSavedMajorVersion;
44 sSavedMinorVersion = version_info.dwMinorVersion;
45 *minorVersion = sSavedMinorVersion;
46 ret = true;
47
48 #elif defined(ANGLE_PLATFORM_APPLE)
49 GetOperatingSystemVersionNumbers(&sSavedMajorVersion, &sSavedMinorVersion);
50 *majorVersion = sSavedMajorVersion;
51 *minorVersion = sSavedMinorVersion;
52 ret = true;
53
54 #else
55 ret = false;
56 #endif
57 }
58 else
59 {
60 ret = true;
61 }
62 *majorVersion = sSavedMajorVersion;
63 *minorVersion = sSavedMinorVersion;
64 return ret;
65 }
66
67 // Check if the OS is any version of Windows
IsWin()68 inline bool IsWin()
69 {
70 #if defined(ANGLE_PLATFORM_WINDOWS)
71 return true;
72 #else
73 return false;
74 #endif
75 }
76
77 // Check if the OS is a specific major version of windows.
IsWinVersion(const int32_t majorVersion)78 inline bool IsWinVersion(const int32_t majorVersion)
79 {
80 if (IsWin())
81 {
82 int32_t currentMajorVersion = 0;
83 int32_t currentMinorVersion = 0;
84 if (OperatingSystemVersionNumbers(¤tMajorVersion, ¤tMinorVersion))
85 {
86 if (currentMajorVersion == majorVersion)
87 {
88 return true;
89 }
90 }
91 }
92 return false;
93 }
94
95 // Check if the OS is a specific major and minor version of windows.
IsWinVersion(const int32_t majorVersion,const int32_t minorVersion)96 inline bool IsWinVersion(const int32_t majorVersion, const int32_t minorVersion)
97 {
98 if (IsWin())
99 {
100 int32_t currentMajorVersion = 0;
101 int32_t currentMinorVersion = 0;
102 if (OperatingSystemVersionNumbers(¤tMajorVersion, ¤tMinorVersion))
103 {
104 if (currentMajorVersion == majorVersion && currentMinorVersion == minorVersion)
105 {
106 return true;
107 }
108 }
109 }
110 return false;
111 }
112
113 // Check if the OS is Windows XP
IsWinXP()114 inline bool IsWinXP()
115 {
116 if (IsWinVersion(5))
117 {
118 return true;
119 }
120 return false;
121 }
122
123 // Check if the OS is Windows Vista
IsWinVista()124 inline bool IsWinVista()
125 {
126 if (IsWinVersion(6, 0))
127 {
128 return true;
129 }
130 return false;
131 }
132
133 // Check if the OS is Windows 7
IsWin7()134 inline bool IsWin7()
135 {
136 if (IsWinVersion(6, 1))
137 {
138 return true;
139 }
140 return false;
141 }
142
143 // Check if the OS is Windows 8
IsWin8()144 inline bool IsWin8()
145 {
146 if (IsWinVersion(6, 2) || IsWinVersion(6, 3))
147 {
148 return true;
149 }
150 return false;
151 }
152
153 // Check if the OS is Windows 10
IsWin10()154 inline bool IsWin10()
155 {
156 if (IsWinVersion(10))
157 {
158 return true;
159 }
160 return false;
161 }
162
163 // Check if the OS is any version of OSX
IsMac()164 inline bool IsMac()
165 {
166 #if defined(ANGLE_PLATFORM_APPLE)
167 return true;
168 #else
169 return false;
170 #endif
171 }
172
173 // Check if the OS is a specific major and minor version of OSX
IsMacVersion(const int32_t majorVersion,const int32_t minorVersion)174 inline bool IsMacVersion(const int32_t majorVersion, const int32_t minorVersion)
175 {
176 if (IsMac())
177 {
178 int32_t currentMajorVersion = 0;
179 int32_t currentMinorVersion = 0;
180 if (OperatingSystemVersionNumbers(¤tMajorVersion, ¤tMinorVersion))
181 {
182 if (currentMajorVersion == majorVersion && currentMinorVersion == minorVersion)
183 {
184 return true;
185 }
186 }
187 }
188 return false;
189 }
190
191 // Check if the OS is OSX Leopard
IsMacLeopard()192 inline bool IsMacLeopard()
193 {
194 if (IsMacVersion(10, 5))
195 {
196 return true;
197 }
198 return false;
199 }
200
201 // Check if the OS is OSX Snow Leopard
IsMacSnowLeopard()202 inline bool IsMacSnowLeopard()
203 {
204 if (IsMacVersion(10, 6))
205 {
206 return true;
207 }
208 return false;
209 }
210
211 // Check if the OS is OSX Lion
IsMacLion()212 inline bool IsMacLion()
213 {
214 if (IsMacVersion(10, 7))
215 {
216 return true;
217 }
218 return false;
219 }
220
221 // Check if the OS is OSX Mountain Lion
IsMacMountainLion()222 inline bool IsMacMountainLion()
223 {
224 if (IsMacVersion(10, 8))
225 {
226 return true;
227 }
228 return false;
229 }
230
231 // Check if the OS is OSX Mavericks
IsMacMavericks()232 inline bool IsMacMavericks()
233 {
234 if (IsMacVersion(10, 9))
235 {
236 return true;
237 }
238 return false;
239 }
240
241 // Check if the OS is OSX Yosemite
IsMacYosemite()242 inline bool IsMacYosemite()
243 {
244 if (IsMacVersion(10, 10))
245 {
246 return true;
247 }
248 return false;
249 }
250
251 // Check if the OS is OSX El Capitan
IsMacElCapitan()252 inline bool IsMacElCapitan()
253 {
254 if (IsMacVersion(10, 11))
255 {
256 return true;
257 }
258 return false;
259 }
260
261 // Check if the OS is OSX Sierra
IsMacSierra()262 inline bool IsMacSierra()
263 {
264 if (IsMacVersion(10, 12))
265 {
266 return true;
267 }
268 return false;
269 }
270
271 // Check if the OS is OSX High Sierra
IsMacHighSierra()272 inline bool IsMacHighSierra()
273 {
274 if (IsMacVersion(10, 13))
275 {
276 return true;
277 }
278 return false;
279 }
280
281 // Check if the OS is OSX Mojave
IsMacMojave()282 inline bool IsMacMojave()
283 {
284 if (IsMacVersion(10, 14))
285 {
286 return true;
287 }
288 return false;
289 }
290
291 // Check if the OS is any version of Linux
IsLinux()292 inline bool IsLinux()
293 {
294 #if defined(ANGLE_PLATFORM_LINUX)
295 return true;
296 #else
297 return false;
298 #endif
299 }
300
301 // Check if the OS is any version of Android
IsAndroid()302 inline bool IsAndroid()
303 {
304 #if defined(ANGLE_PLATFORM_ANDROID)
305 return true;
306 #else
307 return false;
308 #endif
309 }
310
311 // Generic function call to populate the SystemInfo struct. This function will
312 // also cache the SystemInfo struct for future calls. Returns false if the
313 // struct was not fully populated. Guaranteed to set sysInfo to a valid pointer
GetGPUTestSystemInfo(SystemInfo ** sysInfo)314 inline bool GetGPUTestSystemInfo(SystemInfo **sysInfo)
315 {
316 static SystemInfo *sSystemInfo = nullptr;
317 static bool sPopulated = false;
318 if (sSystemInfo == nullptr)
319 {
320 sSystemInfo = new SystemInfo;
321 if (!GetSystemInfo(sSystemInfo))
322 {
323 std::cout << "Error populating SystemInfo for dEQP tests." << std::endl;
324 }
325 else
326 {
327 // On dual-GPU Macs we want the active GPU to always appear to be the
328 // high-performance GPU for tests.
329 // We can call the generic GPU info collector which selects the
330 // non-Intel GPU as the active one on dual-GPU machines.
331 // See https://anglebug.com/3701.
332 if (IsMac())
333 {
334 GetDualGPUInfo(sSystemInfo);
335 }
336 sPopulated = true;
337 }
338 }
339 *sysInfo = sSystemInfo;
340 ASSERT(*sysInfo != nullptr);
341 return sPopulated;
342 }
343
344 // Get the active GPUDeviceInfo from the SystemInfo struct.
345 // Returns false if devInfo is not guaranteed to be set to the active device.
GetActiveGPU(GPUDeviceInfo ** devInfo)346 inline bool GetActiveGPU(GPUDeviceInfo **devInfo)
347 {
348 SystemInfo *systemInfo = nullptr;
349 GetGPUTestSystemInfo(&systemInfo);
350 if (systemInfo->gpus.size() <= 0)
351 {
352 return false;
353 }
354 uint32_t index = systemInfo->activeGPUIndex;
355 ASSERT(index < systemInfo->gpus.size());
356 *devInfo = &(systemInfo->gpus[index]);
357 return true;
358 }
359
360 // Get the vendor ID of the active GPU from the SystemInfo struct.
361 // Returns 0 if there is an error.
GetActiveGPUVendorID()362 inline VendorID GetActiveGPUVendorID()
363 {
364 GPUDeviceInfo *activeGPU = nullptr;
365 if (GetActiveGPU(&activeGPU))
366 {
367 return activeGPU->vendorId;
368 }
369 else
370 {
371 return static_cast<VendorID>(0);
372 }
373 }
374
375 // Get the device ID of the active GPU from the SystemInfo struct.
376 // Returns 0 if there is an error.
GetActiveGPUDeviceID()377 inline DeviceID GetActiveGPUDeviceID()
378 {
379 GPUDeviceInfo *activeGPU = nullptr;
380 if (GetActiveGPU(&activeGPU))
381 {
382 return activeGPU->deviceId;
383 }
384 else
385 {
386 return static_cast<DeviceID>(0);
387 }
388 }
389
390 // Check whether the active GPU is NVIDIA.
IsNVIDIA()391 inline bool IsNVIDIA()
392 {
393 return angle::IsNVIDIA(GetActiveGPUVendorID());
394 }
395
396 // Check whether the active GPU is AMD.
IsAMD()397 inline bool IsAMD()
398 {
399 return angle::IsAMD(GetActiveGPUVendorID());
400 }
401
402 // Check whether the active GPU is Intel.
IsIntel()403 inline bool IsIntel()
404 {
405 return angle::IsIntel(GetActiveGPUVendorID());
406 }
407
408 // Check whether the active GPU is VMWare.
IsVMWare()409 inline bool IsVMWare()
410 {
411 return angle::IsVMWare(GetActiveGPUVendorID());
412 }
413
414 // Check whether this is a debug build.
IsDebug()415 inline bool IsDebug()
416 {
417 #if !defined(NDEBUG)
418 return true;
419 #else
420 return false;
421 #endif
422 }
423
424 // Check whether this is a release build.
IsRelease()425 inline bool IsRelease()
426 {
427 return !IsDebug();
428 }
429
430 // Check whether the system is a specific Android device based on the name.
IsAndroidDevice(const std::string & deviceName)431 inline bool IsAndroidDevice(const std::string &deviceName)
432 {
433 if (!IsAndroid())
434 {
435 return false;
436 }
437 SystemInfo *systemInfo = nullptr;
438 GetGPUTestSystemInfo(&systemInfo);
439 if (systemInfo->machineModelName == deviceName)
440 {
441 return true;
442 }
443 return false;
444 }
445
446 // Check whether the system is a Nexus 5X device.
IsNexus5X()447 inline bool IsNexus5X()
448 {
449 return IsAndroidDevice("Nexus 5X");
450 }
451
452 // Check whether the system is a Pixel 2 device.
IsPixel2()453 inline bool IsPixel2()
454 {
455 return IsAndroidDevice("Pixel 2");
456 }
457
458 // Check whether the system is a Pixel 2XL device.
IsPixel2XL()459 inline bool IsPixel2XL()
460 {
461 return IsAndroidDevice("Pixel 2 XL");
462 }
463
464 // Check whether the active GPU is a specific device based on the string device ID.
IsDeviceIdGPU(const std::string & gpuDeviceId)465 inline bool IsDeviceIdGPU(const std::string &gpuDeviceId)
466 {
467 uint32_t deviceId = 0;
468 if (!HexStringToUInt(gpuDeviceId, &deviceId) || deviceId == 0)
469 {
470 // PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts], line_number);
471 return false;
472 }
473 return (deviceId == GetActiveGPUDeviceID());
474 }
475
476 // Check whether the active GPU is a NVIDIA Quadro P400
IsNVIDIAQuadroP400()477 inline bool IsNVIDIAQuadroP400()
478 {
479 if (!IsNVIDIA())
480 {
481 return false;
482 }
483 return IsDeviceIdGPU("0x1CB3");
484 }
485
486 // Check whether the backend API has been set to D3D9 in the constructor
IsD3D9(const GPUTestConfig::API & api)487 inline bool IsD3D9(const GPUTestConfig::API &api)
488 {
489 return (api == GPUTestConfig::kAPID3D9);
490 }
491
492 // Check whether the backend API has been set to D3D11 in the constructor
IsD3D11(const GPUTestConfig::API & api)493 inline bool IsD3D11(const GPUTestConfig::API &api)
494 {
495 return (api == GPUTestConfig::kAPID3D11);
496 }
497
498 // Check whether the backend API has been set to OpenGL in the constructor
IsGLDesktop(const GPUTestConfig::API & api)499 inline bool IsGLDesktop(const GPUTestConfig::API &api)
500 {
501 return (api == GPUTestConfig::kAPIGLDesktop);
502 }
503
504 // Check whether the backend API has been set to OpenGLES in the constructor
IsGLES(const GPUTestConfig::API & api)505 inline bool IsGLES(const GPUTestConfig::API &api)
506 {
507 return (api == GPUTestConfig::kAPIGLES);
508 }
509
510 // Check whether the backend API has been set to Vulkan in the constructor
IsVulkan(const GPUTestConfig::API & api)511 inline bool IsVulkan(const GPUTestConfig::API &api)
512 {
513 return (api == GPUTestConfig::kAPIVulkan) || (api == GPUTestConfig::kAPISwiftShader);
514 }
515
IsSwiftShader(const GPUTestConfig::API & api)516 inline bool IsSwiftShader(const GPUTestConfig::API &api)
517 {
518 return (api == GPUTestConfig::kAPISwiftShader);
519 }
520
521 // Check whether the backend API has been set to Metal in the constructor
IsMetal(const GPUTestConfig::API & api)522 inline bool IsMetal(const GPUTestConfig::API &api)
523 {
524 return (api == GPUTestConfig::kAPIMetal);
525 }
526
527 } // anonymous namespace
528
529 // Load all conditions in the constructor since this data will not change during a test set.
GPUTestConfig()530 GPUTestConfig::GPUTestConfig()
531 {
532 mConditions[kConditionNone] = false;
533 mConditions[kConditionWinXP] = IsWinXP();
534 mConditions[kConditionWinVista] = IsWinVista();
535 mConditions[kConditionWin7] = IsWin7();
536 mConditions[kConditionWin8] = IsWin8();
537 mConditions[kConditionWin10] = IsWin10();
538 mConditions[kConditionWin] = IsWin();
539 mConditions[kConditionMacLeopard] = IsMacLeopard();
540 mConditions[kConditionMacSnowLeopard] = IsMacSnowLeopard();
541 mConditions[kConditionMacLion] = IsMacLion();
542 mConditions[kConditionMacMountainLion] = IsMacMountainLion();
543 mConditions[kConditionMacMavericks] = IsMacMavericks();
544 mConditions[kConditionMacYosemite] = IsMacYosemite();
545 mConditions[kConditionMacElCapitan] = IsMacElCapitan();
546 mConditions[kConditionMacSierra] = IsMacSierra();
547 mConditions[kConditionMacHighSierra] = IsMacHighSierra();
548 mConditions[kConditionMacMojave] = IsMacMojave();
549 mConditions[kConditionMac] = IsMac();
550 mConditions[kConditionLinux] = IsLinux();
551 mConditions[kConditionAndroid] = IsAndroid();
552 mConditions[kConditionNVIDIA] = IsNVIDIA();
553 mConditions[kConditionAMD] = IsAMD();
554 mConditions[kConditionIntel] = IsIntel();
555 mConditions[kConditionVMWare] = IsVMWare();
556 mConditions[kConditionRelease] = IsRelease();
557 mConditions[kConditionDebug] = IsDebug();
558 // If no API provided, pass these conditions by default
559 mConditions[kConditionD3D9] = true;
560 mConditions[kConditionD3D11] = true;
561 mConditions[kConditionGLDesktop] = true;
562 mConditions[kConditionGLES] = true;
563 mConditions[kConditionVulkan] = true;
564 mConditions[kConditionSwiftShader] = true;
565 mConditions[kConditionMetal] = true;
566
567 mConditions[kConditionNexus5X] = IsNexus5X();
568 mConditions[kConditionPixel2OrXL] = IsPixel2() || IsPixel2XL();
569 mConditions[kConditionNVIDIAQuadroP400] = IsNVIDIAQuadroP400();
570 }
571
572 // If the constructor is passed an API, load those conditions as well
GPUTestConfig(const API & api)573 GPUTestConfig::GPUTestConfig(const API &api) : GPUTestConfig()
574 {
575 mConditions[kConditionD3D9] = IsD3D9(api);
576 mConditions[kConditionD3D11] = IsD3D11(api);
577 mConditions[kConditionGLDesktop] = IsGLDesktop(api);
578 mConditions[kConditionGLES] = IsGLES(api);
579 mConditions[kConditionVulkan] = IsVulkan(api);
580 mConditions[kConditionSwiftShader] = IsSwiftShader(api);
581 mConditions[kConditionMetal] = IsMetal(api);
582 }
583
584 // Return a const reference to the list of all pre-calculated conditions.
getConditions() const585 const GPUTestConfig::ConditionArray &GPUTestConfig::getConditions() const
586 {
587 return mConditions;
588 }
589
590 } // namespace angle
591