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/3701.
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 this is a debug build.
IsDebug()281 inline bool IsDebug()
282 {
283 #if !defined(NDEBUG)
284 return true;
285 #else
286 return false;
287 #endif
288 }
289
290 // Check whether this is a release build.
IsRelease()291 inline bool IsRelease()
292 {
293 return !IsDebug();
294 }
295
296 // Check whether the system is a specific Android device based on the name.
IsAndroidDevice(const std::string & deviceName)297 inline bool IsAndroidDevice(const std::string &deviceName)
298 {
299 if (!IsAndroid())
300 {
301 return false;
302 }
303 SystemInfo *systemInfo = nullptr;
304 GetGPUTestSystemInfo(&systemInfo);
305 if (systemInfo->machineModelName == deviceName)
306 {
307 return true;
308 }
309 return false;
310 }
311
312 // Check whether the system is a Nexus 5X device.
IsNexus5X()313 inline bool IsNexus5X()
314 {
315 return IsAndroidDevice("Nexus 5X");
316 }
317
318 // Check whether the system is a Pixel 2 device.
IsPixel2()319 inline bool IsPixel2()
320 {
321 return IsAndroidDevice("Pixel 2");
322 }
323
324 // Check whether the system is a Pixel 2XL device.
IsPixel2XL()325 inline bool IsPixel2XL()
326 {
327 return IsAndroidDevice("Pixel 2 XL");
328 }
329
IsPixel4()330 inline bool IsPixel4()
331 {
332 return IsAndroidDevice("Pixel 4");
333 }
334
IsPixel4XL()335 inline bool IsPixel4XL()
336 {
337 return IsAndroidDevice("Pixel 4 XL");
338 }
339
IsPixel6()340 inline bool IsPixel6()
341 {
342 return IsAndroidDevice("Pixel 6");
343 }
344
IsPixel7()345 inline bool IsPixel7()
346 {
347 return IsAndroidDevice("Pixel 7");
348 }
349
IsOppoFlipN2()350 inline bool IsOppoFlipN2()
351 {
352 return IsAndroidDevice("CPH2437");
353 }
354
IsMaliG710()355 inline bool IsMaliG710()
356 {
357 return IsPixel7() || IsOppoFlipN2();
358 }
359
IsGalaxyA23()360 inline bool IsGalaxyA23()
361 {
362 return IsAndroidDevice("SM-A236U1");
363 }
364
IsGalaxyA34()365 inline bool IsGalaxyA34()
366 {
367 return IsAndroidDevice("SM-A346M");
368 }
369
IsGalaxyA54()370 inline bool IsGalaxyA54()
371 {
372 return IsAndroidDevice("SM-A546E");
373 }
374
IsGalaxyS23()375 inline bool IsGalaxyS23()
376 {
377 return IsAndroidDevice("SM-S911U1");
378 }
379
IsGalaxyQualcomm()380 inline bool IsGalaxyQualcomm()
381 {
382 return IsGalaxyA23() || IsGalaxyS23();
383 }
384
IsFindX6()385 inline bool IsFindX6()
386 {
387 return IsAndroidDevice("PGFM10");
388 }
389
390 // Check whether the active GPU is a specific device based on the string device ID.
IsDeviceIdGPU(const std::string & gpuDeviceId)391 inline bool IsDeviceIdGPU(const std::string &gpuDeviceId)
392 {
393 uint32_t deviceId = 0;
394 if (!HexStringToUInt(gpuDeviceId, &deviceId) || deviceId == 0)
395 {
396 // PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts], line_number);
397 return false;
398 }
399 return (deviceId == GetActiveGPUDeviceID());
400 }
401
402 // Check whether the active GPU is a NVIDIA Quadro P400
IsNVIDIAQuadroP400()403 inline bool IsNVIDIAQuadroP400()
404 {
405 return (IsNVIDIA() && IsDeviceIdGPU("0x1CB3"));
406 }
407
408 // Check whether the active GPU is a NVIDIA GTX 1660
IsNVIDIAGTX1660()409 inline bool IsNVIDIAGTX1660()
410 {
411 return (IsNVIDIA() && IsDeviceIdGPU("0x2184"));
412 }
413
414 // Check whether the backend API has been set to D3D9 in the constructor
IsD3D9(const GPUTestConfig::API & api)415 inline bool IsD3D9(const GPUTestConfig::API &api)
416 {
417 return (api == GPUTestConfig::kAPID3D9);
418 }
419
420 // Check whether the backend API has been set to D3D11 in the constructor
IsD3D11(const GPUTestConfig::API & api)421 inline bool IsD3D11(const GPUTestConfig::API &api)
422 {
423 return (api == GPUTestConfig::kAPID3D11);
424 }
425
426 // Check whether the backend API has been set to OpenGL in the constructor
IsGLDesktop(const GPUTestConfig::API & api)427 inline bool IsGLDesktop(const GPUTestConfig::API &api)
428 {
429 return (api == GPUTestConfig::kAPIGLDesktop);
430 }
431
432 // Check whether the backend API has been set to OpenGLES in the constructor
IsGLES(const GPUTestConfig::API & api)433 inline bool IsGLES(const GPUTestConfig::API &api)
434 {
435 return (api == GPUTestConfig::kAPIGLES);
436 }
437
438 // Check whether the backend API has been set to Vulkan in the constructor
IsVulkan(const GPUTestConfig::API & api)439 inline bool IsVulkan(const GPUTestConfig::API &api)
440 {
441 return (api == GPUTestConfig::kAPIVulkan) || (api == GPUTestConfig::kAPISwiftShader);
442 }
443
IsSwiftShader(const GPUTestConfig::API & api)444 inline bool IsSwiftShader(const GPUTestConfig::API &api)
445 {
446 return (api == GPUTestConfig::kAPISwiftShader);
447 }
448
449 // Check whether the backend API has been set to Metal in the constructor
IsMetal(const GPUTestConfig::API & api)450 inline bool IsMetal(const GPUTestConfig::API &api)
451 {
452 return (api == GPUTestConfig::kAPIMetal);
453 }
454
455 } // anonymous namespace
456
457 // Load all conditions in the constructor since this data will not change during a test set.
GPUTestConfig()458 GPUTestConfig::GPUTestConfig() : GPUTestConfig(false) {}
459
GPUTestConfig(bool isSwiftShader)460 GPUTestConfig::GPUTestConfig(bool isSwiftShader)
461 {
462 mConditions[kConditionNone] = false;
463 mConditions[kConditionWinXP] = IsWindowsXP();
464 mConditions[kConditionWinVista] = IsWindowsVista();
465 mConditions[kConditionWin7] = IsWindows7();
466 mConditions[kConditionWin8] = IsWindows8();
467 mConditions[kConditionWin10] = IsWindows10OrLater();
468 mConditions[kConditionWin] = IsWindows();
469 mConditions[kConditionMacLeopard] = IsMacLeopard();
470 mConditions[kConditionMacSnowLeopard] = IsMacSnowLeopard();
471 mConditions[kConditionMacLion] = IsMacLion();
472 mConditions[kConditionMacMountainLion] = IsMacMountainLion();
473 mConditions[kConditionMacMavericks] = IsMacMavericks();
474 mConditions[kConditionMacYosemite] = IsMacYosemite();
475 mConditions[kConditionMacElCapitan] = IsMacElCapitan();
476 mConditions[kConditionMacSierra] = IsMacSierra();
477 mConditions[kConditionMacHighSierra] = IsMacHighSierra();
478 mConditions[kConditionMacMojave] = IsMacMojave();
479 mConditions[kConditionMac] = IsMac();
480 mConditions[kConditionIOS] = IsIOS();
481 mConditions[kConditionLinux] = IsLinux();
482 mConditions[kConditionAndroid] = IsAndroid();
483 // HW vendors are irrelevant if we are running on SW
484 mConditions[kConditionNVIDIA] = !isSwiftShader && IsNVIDIA();
485 mConditions[kConditionAMD] = !isSwiftShader && IsAMD();
486 mConditions[kConditionIntel] = !isSwiftShader && IsIntel();
487 mConditions[kConditionVMWare] = !isSwiftShader && IsVMWare();
488 mConditions[kConditionApple] = !isSwiftShader && IsAppleGPU();
489 mConditions[kConditionSwiftShader] = isSwiftShader;
490
491 mConditions[kConditionRelease] = IsRelease();
492 mConditions[kConditionDebug] = IsDebug();
493 // If no API provided, pass these conditions by default
494 mConditions[kConditionD3D9] = true;
495 mConditions[kConditionD3D11] = true;
496 mConditions[kConditionGLDesktop] = true;
497 mConditions[kConditionGLES] = true;
498 mConditions[kConditionVulkan] = true;
499 mConditions[kConditionMetal] = true;
500
501 // Devices are irrelevant if we are running on SW
502 mConditions[kConditionNexus5X] = !isSwiftShader && IsNexus5X();
503 mConditions[kConditionPixel2OrXL] = !isSwiftShader && (IsPixel2() || IsPixel2XL());
504 mConditions[kConditionPixel4OrXL] = !isSwiftShader && (IsPixel4() || IsPixel4XL());
505 mConditions[kConditionPixel6] = !isSwiftShader && (IsPixel6());
506 mConditions[kConditionPixel7] = !isSwiftShader && (IsPixel7());
507 mConditions[kConditionFlipN2] = !isSwiftShader && (IsOppoFlipN2());
508 mConditions[kConditionMaliG710] = !isSwiftShader && (IsMaliG710());
509 mConditions[kConditionGalaxyA23] = !isSwiftShader && (IsGalaxyA23());
510 mConditions[kConditionGalaxyA34] = !isSwiftShader && (IsGalaxyA34());
511 mConditions[kConditionGalaxyA54] = !isSwiftShader && (IsGalaxyA54());
512 mConditions[kConditionGalaxyS23] = !isSwiftShader && (IsGalaxyS23());
513 mConditions[kConditionGalaxyQualcomm] = !isSwiftShader && (IsGalaxyQualcomm());
514 mConditions[kConditionFindX6] = !isSwiftShader && (IsFindX6());
515 mConditions[kConditionNVIDIAQuadroP400] = !isSwiftShader && IsNVIDIAQuadroP400();
516 mConditions[kConditionNVIDIAGTX1660] = !isSwiftShader && IsNVIDIAGTX1660();
517
518 mConditions[kConditionPreRotation] = false;
519 mConditions[kConditionPreRotation90] = false;
520 mConditions[kConditionPreRotation180] = false;
521 mConditions[kConditionPreRotation270] = false;
522
523 mConditions[kConditionNoSan] = !IsASan() && !IsTSan() && !IsUBSan();
524 mConditions[kConditionASan] = IsASan();
525 mConditions[kConditionTSan] = IsTSan();
526 mConditions[kConditionUBSan] = IsUBSan();
527 }
528
529 // If the constructor is passed an API, load those conditions as well
GPUTestConfig(const API & api,uint32_t preRotation)530 GPUTestConfig::GPUTestConfig(const API &api, uint32_t preRotation)
531 : GPUTestConfig(IsSwiftShader(api))
532 {
533 mConditions[kConditionD3D9] = IsD3D9(api);
534 mConditions[kConditionD3D11] = IsD3D11(api);
535 mConditions[kConditionGLDesktop] = IsGLDesktop(api);
536 mConditions[kConditionGLES] = IsGLES(api);
537 mConditions[kConditionVulkan] = IsVulkan(api);
538 mConditions[kConditionMetal] = IsMetal(api);
539
540 switch (preRotation)
541 {
542 case 90:
543 mConditions[kConditionPreRotation] = true;
544 mConditions[kConditionPreRotation90] = true;
545 break;
546 case 180:
547 mConditions[kConditionPreRotation] = true;
548 mConditions[kConditionPreRotation180] = true;
549 break;
550 case 270:
551 mConditions[kConditionPreRotation] = true;
552 mConditions[kConditionPreRotation270] = true;
553 break;
554 default:
555 break;
556 }
557 }
558
559 // Return a const reference to the list of all pre-calculated conditions.
getConditions() const560 const GPUTestConfig::ConditionArray &GPUTestConfig::getConditions() const
561 {
562 return mConditions;
563 }
564
565 } // namespace angle
566