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