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 iOS
IsIOS()164 inline bool IsIOS()
165 {
166 #if defined(ANGLE_PLATFORM_IOS)
167 return true;
168 #else
169 return false;
170 #endif
171 }
172
173 // Check if the OS is any version of OSX
IsMac()174 inline bool IsMac()
175 {
176 #if defined(ANGLE_PLATFORM_MACOS)
177 return true;
178 #else
179 return false;
180 #endif
181 }
182
183 // Check if the OS is a specific major and minor version of OSX
IsMacVersion(const int32_t majorVersion,const int32_t minorVersion)184 inline bool IsMacVersion(const int32_t majorVersion, const int32_t minorVersion)
185 {
186 if (IsMac())
187 {
188 int32_t currentMajorVersion = 0;
189 int32_t currentMinorVersion = 0;
190 if (OperatingSystemVersionNumbers(¤tMajorVersion, ¤tMinorVersion))
191 {
192 if (currentMajorVersion == majorVersion && currentMinorVersion == minorVersion)
193 {
194 return true;
195 }
196 }
197 }
198 return false;
199 }
200
201 // Check if the OS is OSX Leopard
IsMacLeopard()202 inline bool IsMacLeopard()
203 {
204 if (IsMacVersion(10, 5))
205 {
206 return true;
207 }
208 return false;
209 }
210
211 // Check if the OS is OSX Snow Leopard
IsMacSnowLeopard()212 inline bool IsMacSnowLeopard()
213 {
214 if (IsMacVersion(10, 6))
215 {
216 return true;
217 }
218 return false;
219 }
220
221 // Check if the OS is OSX Lion
IsMacLion()222 inline bool IsMacLion()
223 {
224 if (IsMacVersion(10, 7))
225 {
226 return true;
227 }
228 return false;
229 }
230
231 // Check if the OS is OSX Mountain Lion
IsMacMountainLion()232 inline bool IsMacMountainLion()
233 {
234 if (IsMacVersion(10, 8))
235 {
236 return true;
237 }
238 return false;
239 }
240
241 // Check if the OS is OSX Mavericks
IsMacMavericks()242 inline bool IsMacMavericks()
243 {
244 if (IsMacVersion(10, 9))
245 {
246 return true;
247 }
248 return false;
249 }
250
251 // Check if the OS is OSX Yosemite
IsMacYosemite()252 inline bool IsMacYosemite()
253 {
254 if (IsMacVersion(10, 10))
255 {
256 return true;
257 }
258 return false;
259 }
260
261 // Check if the OS is OSX El Capitan
IsMacElCapitan()262 inline bool IsMacElCapitan()
263 {
264 if (IsMacVersion(10, 11))
265 {
266 return true;
267 }
268 return false;
269 }
270
271 // Check if the OS is OSX Sierra
IsMacSierra()272 inline bool IsMacSierra()
273 {
274 if (IsMacVersion(10, 12))
275 {
276 return true;
277 }
278 return false;
279 }
280
281 // Check if the OS is OSX High Sierra
IsMacHighSierra()282 inline bool IsMacHighSierra()
283 {
284 if (IsMacVersion(10, 13))
285 {
286 return true;
287 }
288 return false;
289 }
290
291 // Check if the OS is OSX Mojave
IsMacMojave()292 inline bool IsMacMojave()
293 {
294 if (IsMacVersion(10, 14))
295 {
296 return true;
297 }
298 return false;
299 }
300
301 // Check if the OS is any version of Linux
IsLinux()302 inline bool IsLinux()
303 {
304 #if defined(ANGLE_PLATFORM_LINUX)
305 return true;
306 #else
307 return false;
308 #endif
309 }
310
311 // Check if the OS is any version of Android
IsAndroid()312 inline bool IsAndroid()
313 {
314 #if defined(ANGLE_PLATFORM_ANDROID)
315 return true;
316 #else
317 return false;
318 #endif
319 }
320
321 // Generic function call to populate the SystemInfo struct. This function will
322 // also cache the SystemInfo struct for future calls. Returns false if the
323 // struct was not fully populated. Guaranteed to set sysInfo to a valid pointer
GetGPUTestSystemInfo(SystemInfo ** sysInfo)324 inline bool GetGPUTestSystemInfo(SystemInfo **sysInfo)
325 {
326 static SystemInfo *sSystemInfo = nullptr;
327 static bool sPopulated = false;
328 if (sSystemInfo == nullptr)
329 {
330 sSystemInfo = new SystemInfo;
331 if (!GetSystemInfo(sSystemInfo))
332 {
333 std::cout << "Error populating SystemInfo." << std::endl;
334 }
335 else
336 {
337 // On dual-GPU Macs we want the active GPU to always appear to be the
338 // high-performance GPU for tests.
339 // We can call the generic GPU info collector which selects the
340 // non-Intel GPU as the active one on dual-GPU machines.
341 // See https://anglebug.com/3701.
342 if (IsMac())
343 {
344 GetDualGPUInfo(sSystemInfo);
345 }
346 sPopulated = true;
347 }
348 }
349 *sysInfo = sSystemInfo;
350 ASSERT(*sysInfo != nullptr);
351 return sPopulated;
352 }
353
354 // Get the active GPUDeviceInfo from the SystemInfo struct.
355 // Returns false if devInfo is not guaranteed to be set to the active device.
GetActiveGPU(GPUDeviceInfo ** devInfo)356 inline bool GetActiveGPU(GPUDeviceInfo **devInfo)
357 {
358 SystemInfo *systemInfo = nullptr;
359 GetGPUTestSystemInfo(&systemInfo);
360 if (systemInfo->gpus.size() <= 0)
361 {
362 return false;
363 }
364 uint32_t index = systemInfo->activeGPUIndex;
365 ASSERT(index < systemInfo->gpus.size());
366 *devInfo = &(systemInfo->gpus[index]);
367 return true;
368 }
369
370 // Get the vendor ID of the active GPU from the SystemInfo struct.
371 // Returns 0 if there is an error.
GetActiveGPUVendorID()372 inline VendorID GetActiveGPUVendorID()
373 {
374 GPUDeviceInfo *activeGPU = nullptr;
375 if (GetActiveGPU(&activeGPU))
376 {
377 return activeGPU->vendorId;
378 }
379 else
380 {
381 return static_cast<VendorID>(0);
382 }
383 }
384
385 // Get the device ID of the active GPU from the SystemInfo struct.
386 // Returns 0 if there is an error.
GetActiveGPUDeviceID()387 inline DeviceID GetActiveGPUDeviceID()
388 {
389 GPUDeviceInfo *activeGPU = nullptr;
390 if (GetActiveGPU(&activeGPU))
391 {
392 return activeGPU->deviceId;
393 }
394 else
395 {
396 return static_cast<DeviceID>(0);
397 }
398 }
399
400 // Check whether the active GPU is NVIDIA.
IsNVIDIA()401 inline bool IsNVIDIA()
402 {
403 return angle::IsNVIDIA(GetActiveGPUVendorID());
404 }
405
406 // Check whether the active GPU is AMD.
IsAMD()407 inline bool IsAMD()
408 {
409 return angle::IsAMD(GetActiveGPUVendorID());
410 }
411
412 // Check whether the active GPU is Intel.
IsIntel()413 inline bool IsIntel()
414 {
415 return angle::IsIntel(GetActiveGPUVendorID());
416 }
417
418 // Check whether the active GPU is VMWare.
IsVMWare()419 inline bool IsVMWare()
420 {
421 return angle::IsVMWare(GetActiveGPUVendorID());
422 }
423
424 // Check whether this is a debug build.
IsDebug()425 inline bool IsDebug()
426 {
427 #if !defined(NDEBUG)
428 return true;
429 #else
430 return false;
431 #endif
432 }
433
434 // Check whether this is a release build.
IsRelease()435 inline bool IsRelease()
436 {
437 return !IsDebug();
438 }
439
440 // Check whether the system is a specific Android device based on the name.
IsAndroidDevice(const std::string & deviceName)441 inline bool IsAndroidDevice(const std::string &deviceName)
442 {
443 if (!IsAndroid())
444 {
445 return false;
446 }
447 SystemInfo *systemInfo = nullptr;
448 GetGPUTestSystemInfo(&systemInfo);
449 if (systemInfo->machineModelName == deviceName)
450 {
451 return true;
452 }
453 return false;
454 }
455
456 // Check whether the system is a Nexus 5X device.
IsNexus5X()457 inline bool IsNexus5X()
458 {
459 return IsAndroidDevice("Nexus 5X");
460 }
461
462 // Check whether the system is a Pixel 2 device.
IsPixel2()463 inline bool IsPixel2()
464 {
465 return IsAndroidDevice("Pixel 2");
466 }
467
468 // Check whether the system is a Pixel 2XL device.
IsPixel2XL()469 inline bool IsPixel2XL()
470 {
471 return IsAndroidDevice("Pixel 2 XL");
472 }
473
IsPixel4()474 inline bool IsPixel4()
475 {
476 return IsAndroidDevice("Pixel 4");
477 }
478
IsPixel4XL()479 inline bool IsPixel4XL()
480 {
481 return IsAndroidDevice("Pixel 4 XL");
482 }
483
484 // Check whether the active GPU is a specific device based on the string device ID.
IsDeviceIdGPU(const std::string & gpuDeviceId)485 inline bool IsDeviceIdGPU(const std::string &gpuDeviceId)
486 {
487 uint32_t deviceId = 0;
488 if (!HexStringToUInt(gpuDeviceId, &deviceId) || deviceId == 0)
489 {
490 // PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts], line_number);
491 return false;
492 }
493 return (deviceId == GetActiveGPUDeviceID());
494 }
495
496 // Check whether the active GPU is a NVIDIA Quadro P400
IsNVIDIAQuadroP400()497 inline bool IsNVIDIAQuadroP400()
498 {
499 if (!IsNVIDIA())
500 {
501 return false;
502 }
503 return IsDeviceIdGPU("0x1CB3");
504 }
505
506 // Check whether the backend API has been set to D3D9 in the constructor
IsD3D9(const GPUTestConfig::API & api)507 inline bool IsD3D9(const GPUTestConfig::API &api)
508 {
509 return (api == GPUTestConfig::kAPID3D9);
510 }
511
512 // Check whether the backend API has been set to D3D11 in the constructor
IsD3D11(const GPUTestConfig::API & api)513 inline bool IsD3D11(const GPUTestConfig::API &api)
514 {
515 return (api == GPUTestConfig::kAPID3D11);
516 }
517
518 // Check whether the backend API has been set to OpenGL in the constructor
IsGLDesktop(const GPUTestConfig::API & api)519 inline bool IsGLDesktop(const GPUTestConfig::API &api)
520 {
521 return (api == GPUTestConfig::kAPIGLDesktop);
522 }
523
524 // Check whether the backend API has been set to OpenGLES in the constructor
IsGLES(const GPUTestConfig::API & api)525 inline bool IsGLES(const GPUTestConfig::API &api)
526 {
527 return (api == GPUTestConfig::kAPIGLES);
528 }
529
530 // Check whether the backend API has been set to Vulkan in the constructor
IsVulkan(const GPUTestConfig::API & api)531 inline bool IsVulkan(const GPUTestConfig::API &api)
532 {
533 return (api == GPUTestConfig::kAPIVulkan) || (api == GPUTestConfig::kAPISwiftShader);
534 }
535
IsSwiftShader(const GPUTestConfig::API & api)536 inline bool IsSwiftShader(const GPUTestConfig::API &api)
537 {
538 return (api == GPUTestConfig::kAPISwiftShader);
539 }
540
541 // Check whether the backend API has been set to Metal in the constructor
IsMetal(const GPUTestConfig::API & api)542 inline bool IsMetal(const GPUTestConfig::API &api)
543 {
544 return (api == GPUTestConfig::kAPIMetal);
545 }
546
547 } // anonymous namespace
548
549 // Load all conditions in the constructor since this data will not change during a test set.
GPUTestConfig()550 GPUTestConfig::GPUTestConfig() : GPUTestConfig(false) {}
551
GPUTestConfig(bool isSwiftShader)552 GPUTestConfig::GPUTestConfig(bool isSwiftShader)
553 {
554 mConditions[kConditionNone] = false;
555 mConditions[kConditionWinXP] = IsWinXP();
556 mConditions[kConditionWinVista] = IsWinVista();
557 mConditions[kConditionWin7] = IsWin7();
558 mConditions[kConditionWin8] = IsWin8();
559 mConditions[kConditionWin10] = IsWin10();
560 mConditions[kConditionWin] = IsWin();
561 mConditions[kConditionMacLeopard] = IsMacLeopard();
562 mConditions[kConditionMacSnowLeopard] = IsMacSnowLeopard();
563 mConditions[kConditionMacLion] = IsMacLion();
564 mConditions[kConditionMacMountainLion] = IsMacMountainLion();
565 mConditions[kConditionMacMavericks] = IsMacMavericks();
566 mConditions[kConditionMacYosemite] = IsMacYosemite();
567 mConditions[kConditionMacElCapitan] = IsMacElCapitan();
568 mConditions[kConditionMacSierra] = IsMacSierra();
569 mConditions[kConditionMacHighSierra] = IsMacHighSierra();
570 mConditions[kConditionMacMojave] = IsMacMojave();
571 mConditions[kConditionMac] = IsMac();
572 mConditions[kConditionIOS] = IsIOS();
573 mConditions[kConditionLinux] = IsLinux();
574 mConditions[kConditionAndroid] = IsAndroid();
575 // HW vendors are irrelevant if we are running on SW
576 mConditions[kConditionNVIDIA] = !isSwiftShader && IsNVIDIA();
577 mConditions[kConditionAMD] = !isSwiftShader && IsAMD();
578 mConditions[kConditionIntel] = !isSwiftShader && IsIntel();
579 mConditions[kConditionVMWare] = !isSwiftShader && IsVMWare();
580 mConditions[kConditionSwiftShader] = isSwiftShader;
581
582 mConditions[kConditionRelease] = IsRelease();
583 mConditions[kConditionDebug] = IsDebug();
584 // If no API provided, pass these conditions by default
585 mConditions[kConditionD3D9] = true;
586 mConditions[kConditionD3D11] = true;
587 mConditions[kConditionGLDesktop] = true;
588 mConditions[kConditionGLES] = true;
589 mConditions[kConditionVulkan] = true;
590 mConditions[kConditionMetal] = true;
591
592 // Devices are irrelevent if we are running on SW
593 mConditions[kConditionNexus5X] = !isSwiftShader && IsNexus5X();
594 mConditions[kConditionPixel2OrXL] = !isSwiftShader && (IsPixel2() || IsPixel2XL());
595 mConditions[kConditionPixel4OrXL] = !isSwiftShader && (IsPixel4() || IsPixel4XL());
596 mConditions[kConditionNVIDIAQuadroP400] = !isSwiftShader && IsNVIDIAQuadroP400();
597
598 mConditions[kConditionPreRotation] = false;
599 mConditions[kConditionPreRotation90] = false;
600 mConditions[kConditionPreRotation180] = false;
601 mConditions[kConditionPreRotation270] = false;
602 }
603
604 // If the constructor is passed an API, load those conditions as well
GPUTestConfig(const API & api,uint32_t preRotation)605 GPUTestConfig::GPUTestConfig(const API &api, uint32_t preRotation)
606 : GPUTestConfig(IsSwiftShader(api))
607 {
608 mConditions[kConditionD3D9] = IsD3D9(api);
609 mConditions[kConditionD3D11] = IsD3D11(api);
610 mConditions[kConditionGLDesktop] = IsGLDesktop(api);
611 mConditions[kConditionGLES] = IsGLES(api);
612 mConditions[kConditionVulkan] = IsVulkan(api);
613 mConditions[kConditionMetal] = IsMetal(api);
614
615 switch (preRotation)
616 {
617 case 90:
618 mConditions[kConditionPreRotation] = true;
619 mConditions[kConditionPreRotation90] = true;
620 break;
621 case 180:
622 mConditions[kConditionPreRotation] = true;
623 mConditions[kConditionPreRotation180] = true;
624 break;
625 case 270:
626 mConditions[kConditionPreRotation] = true;
627 mConditions[kConditionPreRotation270] = true;
628 break;
629 default:
630 break;
631 }
632 }
633
634 // Return a const reference to the list of all pre-calculated conditions.
getConditions() const635 const GPUTestConfig::ConditionArray &GPUTestConfig::getConditions() const
636 {
637 return mConditions;
638 }
639
640 } // namespace angle
641