// Copyright 2019 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #include "GPUTestConfig.h" #include #include #include "common/angleutils.h" #include "common/debug.h" #include "common/platform.h" #include "common/string_utils.h" #include "gpu_info_util/SystemInfo.h" #if defined(ANGLE_PLATFORM_APPLE) # include "GPUTestConfig_mac.h" #endif namespace angle { namespace { // Generic function call to get the OS version information from any platform // defined below. This function will also cache the OS version info in static // variables. inline bool OperatingSystemVersionNumbers(int32_t *majorVersion, int32_t *minorVersion) { static int32_t sSavedMajorVersion = -1; static int32_t sSavedMinorVersion = -1; bool ret = false; if (sSavedMajorVersion == -1 || sSavedMinorVersion == -1) { #if defined(ANGLE_PLATFORM_WINDOWS) OSVERSIONINFOEX version_info = {}; version_info.dwOSVersionInfoSize = sizeof(version_info); ::GetVersionEx(reinterpret_cast(&version_info)); sSavedMajorVersion = version_info.dwMajorVersion; *majorVersion = sSavedMajorVersion; sSavedMinorVersion = version_info.dwMinorVersion; *minorVersion = sSavedMinorVersion; ret = true; #elif defined(ANGLE_PLATFORM_APPLE) GetOperatingSystemVersionNumbers(&sSavedMajorVersion, &sSavedMinorVersion); *majorVersion = sSavedMajorVersion; *minorVersion = sSavedMinorVersion; ret = true; #else ret = false; #endif } else { ret = true; } *majorVersion = sSavedMajorVersion; *minorVersion = sSavedMinorVersion; return ret; } // Check if the OS is any version of Windows inline bool IsWin() { #if defined(ANGLE_PLATFORM_WINDOWS) return true; #else return false; #endif } // Check if the OS is a specific major version of windows. inline bool IsWinVersion(const int32_t majorVersion) { if (IsWin()) { int32_t currentMajorVersion = 0; int32_t currentMinorVersion = 0; if (OperatingSystemVersionNumbers(¤tMajorVersion, ¤tMinorVersion)) { if (currentMajorVersion == majorVersion) { return true; } } } return false; } // Check if the OS is a specific major and minor version of windows. inline bool IsWinVersion(const int32_t majorVersion, const int32_t minorVersion) { if (IsWin()) { int32_t currentMajorVersion = 0; int32_t currentMinorVersion = 0; if (OperatingSystemVersionNumbers(¤tMajorVersion, ¤tMinorVersion)) { if (currentMajorVersion == majorVersion && currentMinorVersion == minorVersion) { return true; } } } return false; } // Check if the OS is Windows XP inline bool IsWinXP() { if (IsWinVersion(5)) { return true; } return false; } // Check if the OS is Windows Vista inline bool IsWinVista() { if (IsWinVersion(6, 0)) { return true; } return false; } // Check if the OS is Windows 7 inline bool IsWin7() { if (IsWinVersion(6, 1)) { return true; } return false; } // Check if the OS is Windows 8 inline bool IsWin8() { if (IsWinVersion(6, 2) || IsWinVersion(6, 3)) { return true; } return false; } // Check if the OS is Windows 10 inline bool IsWin10() { if (IsWinVersion(10)) { return true; } return false; } // Check if the OS is any version of OSX inline bool IsMac() { #if defined(ANGLE_PLATFORM_APPLE) return true; #else return false; #endif } // Check if the OS is a specific major and minor version of OSX inline bool IsMacVersion(const int32_t majorVersion, const int32_t minorVersion) { if (IsMac()) { int32_t currentMajorVersion = 0; int32_t currentMinorVersion = 0; if (OperatingSystemVersionNumbers(¤tMajorVersion, ¤tMinorVersion)) { if (currentMajorVersion == majorVersion && currentMinorVersion == minorVersion) { return true; } } } return false; } // Check if the OS is OSX Leopard inline bool IsMacLeopard() { if (IsMacVersion(10, 5)) { return true; } return false; } // Check if the OS is OSX Snow Leopard inline bool IsMacSnowLeopard() { if (IsMacVersion(10, 6)) { return true; } return false; } // Check if the OS is OSX Lion inline bool IsMacLion() { if (IsMacVersion(10, 7)) { return true; } return false; } // Check if the OS is OSX Mountain Lion inline bool IsMacMountainLion() { if (IsMacVersion(10, 8)) { return true; } return false; } // Check if the OS is OSX Mavericks inline bool IsMacMavericks() { if (IsMacVersion(10, 9)) { return true; } return false; } // Check if the OS is OSX Yosemite inline bool IsMacYosemite() { if (IsMacVersion(10, 10)) { return true; } return false; } // Check if the OS is OSX El Capitan inline bool IsMacElCapitan() { if (IsMacVersion(10, 11)) { return true; } return false; } // Check if the OS is OSX Sierra inline bool IsMacSierra() { if (IsMacVersion(10, 12)) { return true; } return false; } // Check if the OS is OSX High Sierra inline bool IsMacHighSierra() { if (IsMacVersion(10, 13)) { return true; } return false; } // Check if the OS is OSX Mojave inline bool IsMacMojave() { if (IsMacVersion(10, 14)) { return true; } return false; } // Check if the OS is any version of Linux inline bool IsLinux() { #if defined(ANGLE_PLATFORM_LINUX) return true; #else return false; #endif } // Check if the OS is any version of Android inline bool IsAndroid() { #if defined(ANGLE_PLATFORM_ANDROID) return true; #else return false; #endif } // Generic function call to populate the SystemInfo struct. This function will // also cache the SystemInfo struct for future calls. Returns false if the // struct was not fully populated. Guaranteed to set sysInfo to a valid pointer inline bool GetGPUTestSystemInfo(SystemInfo **sysInfo) { static SystemInfo *sSystemInfo = nullptr; static bool sPopulated = false; if (sSystemInfo == nullptr) { sSystemInfo = new SystemInfo; if (!GetSystemInfo(sSystemInfo)) { std::cout << "Error populating SystemInfo for dEQP tests." << std::endl; } else { // On dual-GPU Macs we want the active GPU to always appear to be the // high-performance GPU for tests. // We can call the generic GPU info collector which selects the // non-Intel GPU as the active one on dual-GPU machines. // See https://anglebug.com/3701. if (IsMac()) { GetDualGPUInfo(sSystemInfo); } sPopulated = true; } } *sysInfo = sSystemInfo; ASSERT(*sysInfo != nullptr); return sPopulated; } // Get the active GPUDeviceInfo from the SystemInfo struct. // Returns false if devInfo is not guaranteed to be set to the active device. inline bool GetActiveGPU(GPUDeviceInfo **devInfo) { SystemInfo *systemInfo = nullptr; GetGPUTestSystemInfo(&systemInfo); if (systemInfo->gpus.size() <= 0) { return false; } uint32_t index = systemInfo->activeGPUIndex; ASSERT(index < systemInfo->gpus.size()); *devInfo = &(systemInfo->gpus[index]); return true; } // Get the vendor ID of the active GPU from the SystemInfo struct. // Returns 0 if there is an error. inline VendorID GetActiveGPUVendorID() { GPUDeviceInfo *activeGPU = nullptr; if (GetActiveGPU(&activeGPU)) { return activeGPU->vendorId; } else { return static_cast(0); } } // Get the device ID of the active GPU from the SystemInfo struct. // Returns 0 if there is an error. inline DeviceID GetActiveGPUDeviceID() { GPUDeviceInfo *activeGPU = nullptr; if (GetActiveGPU(&activeGPU)) { return activeGPU->deviceId; } else { return static_cast(0); } } // Check whether the active GPU is NVIDIA. inline bool IsNVIDIA() { return angle::IsNVIDIA(GetActiveGPUVendorID()); } // Check whether the active GPU is AMD. inline bool IsAMD() { return angle::IsAMD(GetActiveGPUVendorID()); } // Check whether the active GPU is Intel. inline bool IsIntel() { return angle::IsIntel(GetActiveGPUVendorID()); } // Check whether the active GPU is VMWare. inline bool IsVMWare() { return angle::IsVMWare(GetActiveGPUVendorID()); } // Check whether this is a debug build. inline bool IsDebug() { #if !defined(NDEBUG) return true; #else return false; #endif } // Check whether this is a release build. inline bool IsRelease() { return !IsDebug(); } // Check whether the system is a specific Android device based on the name. inline bool IsAndroidDevice(const std::string &deviceName) { if (!IsAndroid()) { return false; } SystemInfo *systemInfo = nullptr; GetGPUTestSystemInfo(&systemInfo); if (systemInfo->machineModelName == deviceName) { return true; } return false; } // Check whether the system is a Nexus 5X device. inline bool IsNexus5X() { return IsAndroidDevice("Nexus 5X"); } // Check whether the system is a Pixel 2 device. inline bool IsPixel2() { return IsAndroidDevice("Pixel 2"); } // Check whether the system is a Pixel 2XL device. inline bool IsPixel2XL() { return IsAndroidDevice("Pixel 2 XL"); } // Check whether the active GPU is a specific device based on the string device ID. inline bool IsDeviceIdGPU(const std::string &gpuDeviceId) { uint32_t deviceId = 0; if (!HexStringToUInt(gpuDeviceId, &deviceId) || deviceId == 0) { // PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts], line_number); return false; } return (deviceId == GetActiveGPUDeviceID()); } // Check whether the active GPU is a NVIDIA Quadro P400 inline bool IsNVIDIAQuadroP400() { if (!IsNVIDIA()) { return false; } return IsDeviceIdGPU("0x1CB3"); } // Check whether the backend API has been set to D3D9 in the constructor inline bool IsD3D9(const GPUTestConfig::API &api) { return (api == GPUTestConfig::kAPID3D9); } // Check whether the backend API has been set to D3D11 in the constructor inline bool IsD3D11(const GPUTestConfig::API &api) { return (api == GPUTestConfig::kAPID3D11); } // Check whether the backend API has been set to OpenGL in the constructor inline bool IsGLDesktop(const GPUTestConfig::API &api) { return (api == GPUTestConfig::kAPIGLDesktop); } // Check whether the backend API has been set to OpenGLES in the constructor inline bool IsGLES(const GPUTestConfig::API &api) { return (api == GPUTestConfig::kAPIGLES); } // Check whether the backend API has been set to Vulkan in the constructor inline bool IsVulkan(const GPUTestConfig::API &api) { return (api == GPUTestConfig::kAPIVulkan) || (api == GPUTestConfig::kAPISwiftShader); } inline bool IsSwiftShader(const GPUTestConfig::API &api) { return (api == GPUTestConfig::kAPISwiftShader); } // Check whether the backend API has been set to Metal in the constructor inline bool IsMetal(const GPUTestConfig::API &api) { return (api == GPUTestConfig::kAPIMetal); } } // anonymous namespace // Load all conditions in the constructor since this data will not change during a test set. GPUTestConfig::GPUTestConfig() { mConditions[kConditionNone] = false; mConditions[kConditionWinXP] = IsWinXP(); mConditions[kConditionWinVista] = IsWinVista(); mConditions[kConditionWin7] = IsWin7(); mConditions[kConditionWin8] = IsWin8(); mConditions[kConditionWin10] = IsWin10(); mConditions[kConditionWin] = IsWin(); mConditions[kConditionMacLeopard] = IsMacLeopard(); mConditions[kConditionMacSnowLeopard] = IsMacSnowLeopard(); mConditions[kConditionMacLion] = IsMacLion(); mConditions[kConditionMacMountainLion] = IsMacMountainLion(); mConditions[kConditionMacMavericks] = IsMacMavericks(); mConditions[kConditionMacYosemite] = IsMacYosemite(); mConditions[kConditionMacElCapitan] = IsMacElCapitan(); mConditions[kConditionMacSierra] = IsMacSierra(); mConditions[kConditionMacHighSierra] = IsMacHighSierra(); mConditions[kConditionMacMojave] = IsMacMojave(); mConditions[kConditionMac] = IsMac(); mConditions[kConditionLinux] = IsLinux(); mConditions[kConditionAndroid] = IsAndroid(); mConditions[kConditionNVIDIA] = IsNVIDIA(); mConditions[kConditionAMD] = IsAMD(); mConditions[kConditionIntel] = IsIntel(); mConditions[kConditionVMWare] = IsVMWare(); mConditions[kConditionRelease] = IsRelease(); mConditions[kConditionDebug] = IsDebug(); // If no API provided, pass these conditions by default mConditions[kConditionD3D9] = true; mConditions[kConditionD3D11] = true; mConditions[kConditionGLDesktop] = true; mConditions[kConditionGLES] = true; mConditions[kConditionVulkan] = true; mConditions[kConditionSwiftShader] = true; mConditions[kConditionMetal] = true; mConditions[kConditionNexus5X] = IsNexus5X(); mConditions[kConditionPixel2OrXL] = IsPixel2() || IsPixel2XL(); mConditions[kConditionNVIDIAQuadroP400] = IsNVIDIAQuadroP400(); } // If the constructor is passed an API, load those conditions as well GPUTestConfig::GPUTestConfig(const API &api) : GPUTestConfig() { mConditions[kConditionD3D9] = IsD3D9(api); mConditions[kConditionD3D11] = IsD3D11(api); mConditions[kConditionGLDesktop] = IsGLDesktop(api); mConditions[kConditionGLES] = IsGLES(api); mConditions[kConditionVulkan] = IsVulkan(api); mConditions[kConditionSwiftShader] = IsSwiftShader(api); mConditions[kConditionMetal] = IsMetal(api); } // Return a const reference to the list of all pre-calculated conditions. const GPUTestConfig::ConditionArray &GPUTestConfig::getConditions() const { return mConditions; } } // namespace angle