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