diff options
Diffstat (limited to 'gfx/angle/checkout/src/gpu_info_util/SystemInfo.cpp')
-rw-r--r-- | gfx/angle/checkout/src/gpu_info_util/SystemInfo.cpp | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/gpu_info_util/SystemInfo.cpp b/gfx/angle/checkout/src/gpu_info_util/SystemInfo.cpp new file mode 100644 index 0000000000..b2149c9f63 --- /dev/null +++ b/gfx/angle/checkout/src/gpu_info_util/SystemInfo.cpp @@ -0,0 +1,418 @@ +// +// Copyright 2013 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. +// + +// SystemInfo.cpp: implementation of the system-agnostic parts of SystemInfo.h + +#include "gpu_info_util/SystemInfo.h" + +#include <cstring> +#include <iostream> +#include <sstream> + +#include "anglebase/no_destructor.h" +#include "common/debug.h" +#include "common/string_utils.h" +#include "common/system_utils.h" + +namespace angle +{ +namespace +{ +constexpr char kANGLEPreferredDeviceEnv[] = "ANGLE_PREFERRED_DEVICE"; +} + +std::string VendorName(VendorID vendor) +{ + switch (vendor) + { + case kVendorID_AMD: + return "AMD"; + case kVendorID_ARM: + return "ARM"; + case kVendorID_Broadcom: + return "Broadcom"; + case kVendorID_GOOGLE: + return "Google"; + case kVendorID_ImgTec: + return "ImgTec"; + case kVendorID_Intel: + return "Intel"; + case kVendorID_Kazan: + return "Kazan"; + case kVendorID_NVIDIA: + return "NVIDIA"; + case kVendorID_Qualcomm: + return "Qualcomm"; + case kVendorID_VeriSilicon: + return "VeriSilicon"; + case kVendorID_Vivante: + return "Vivante"; + case kVendorID_VMWare: + return "VMWare"; + case kVendorID_Apple: + return "Apple"; + case kVendorID_Microsoft: + return "Microsoft"; + default: + return "Unknown (" + std::to_string(vendor) + ")"; + } +} + +GPUDeviceInfo::GPUDeviceInfo() = default; + +GPUDeviceInfo::~GPUDeviceInfo() = default; + +GPUDeviceInfo::GPUDeviceInfo(const GPUDeviceInfo &other) = default; + +SystemInfo::SystemInfo() = default; + +SystemInfo::~SystemInfo() = default; + +SystemInfo::SystemInfo(const SystemInfo &other) = default; + +bool SystemInfo::hasNVIDIAGPU() const +{ + for (const GPUDeviceInfo &gpu : gpus) + { + if (IsNVIDIA(gpu.vendorId)) + { + return true; + } + } + return false; +} + +bool SystemInfo::hasIntelGPU() const +{ + for (const GPUDeviceInfo &gpu : gpus) + { + if (IsIntel(gpu.vendorId)) + { + return true; + } + } + return false; +} + +bool SystemInfo::hasAMDGPU() const +{ + for (const GPUDeviceInfo &gpu : gpus) + { + if (IsAMD(gpu.vendorId)) + { + return true; + } + } + return false; +} + +std::optional<size_t> SystemInfo::getPreferredGPUIndex() const +{ + std::string device = GetPreferredDeviceString(); + if (!device.empty()) + { + for (size_t i = 0; i < gpus.size(); ++i) + { + std::string vendor = VendorName(gpus[i].vendorId); + ToLower(&vendor); + if (vendor == device) + return i; + } + } + return std::nullopt; +} + +bool IsAMD(VendorID vendorId) +{ + return vendorId == kVendorID_AMD; +} + +bool IsARM(VendorID vendorId) +{ + return vendorId == kVendorID_ARM; +} + +bool IsBroadcom(VendorID vendorId) +{ + return vendorId == kVendorID_Broadcom; +} + +bool IsImgTec(VendorID vendorId) +{ + return vendorId == kVendorID_ImgTec; +} + +bool IsKazan(VendorID vendorId) +{ + return vendorId == kVendorID_Kazan; +} + +bool IsIntel(VendorID vendorId) +{ + return vendorId == kVendorID_Intel; +} + +bool IsNVIDIA(VendorID vendorId) +{ + return vendorId == kVendorID_NVIDIA; +} + +bool IsQualcomm(VendorID vendorId) +{ + return vendorId == kVendorID_Qualcomm; +} + +bool IsGoogle(VendorID vendorId) +{ + return vendorId == kVendorID_GOOGLE; +} + +bool IsVeriSilicon(VendorID vendorId) +{ + return vendorId == kVendorID_VeriSilicon; +} + +bool IsVMWare(VendorID vendorId) +{ + return vendorId == kVendorID_VMWare; +} + +bool IsVivante(VendorID vendorId) +{ + return vendorId == kVendorID_Vivante; +} + +bool IsApple(VendorID vendorId) +{ + return vendorId == kVendorID_Apple; +} + +bool IsMicrosoft(VendorID vendorId) +{ + return vendorId == kVendorID_Microsoft; +} + +bool ParseAMDBrahmaDriverVersion(const std::string &content, std::string *version) +{ + const size_t begin = content.find_first_of("0123456789"); + if (begin == std::string::npos) + { + return false; + } + + const size_t end = content.find_first_not_of("0123456789.", begin); + if (end == std::string::npos) + { + *version = content.substr(begin); + } + else + { + *version = content.substr(begin, end - begin); + } + return true; +} + +bool ParseAMDCatalystDriverVersion(const std::string &content, std::string *version) +{ + std::istringstream stream(content); + + std::string line; + while (std::getline(stream, line)) + { + static const char kReleaseVersion[] = "ReleaseVersion="; + if (line.compare(0, std::strlen(kReleaseVersion), kReleaseVersion) != 0) + { + continue; + } + + if (ParseAMDBrahmaDriverVersion(line, version)) + { + return true; + } + } + return false; +} + +bool ParseMacMachineModel(const std::string &identifier, + std::string *type, + int32_t *major, + int32_t *minor) +{ + size_t numberLoc = identifier.find_first_of("0123456789"); + if (numberLoc == std::string::npos) + { + return false; + } + + size_t commaLoc = identifier.find(',', numberLoc); + if (commaLoc == std::string::npos || commaLoc >= identifier.size()) + { + return false; + } + + const char *numberPtr = &identifier[numberLoc]; + const char *commaPtr = &identifier[commaLoc + 1]; + char *endPtr = nullptr; + + int32_t majorTmp = static_cast<int32_t>(std::strtol(numberPtr, &endPtr, 10)); + if (endPtr == numberPtr) + { + return false; + } + + int32_t minorTmp = static_cast<int32_t>(std::strtol(commaPtr, &endPtr, 10)); + if (endPtr == commaPtr) + { + return false; + } + + *major = majorTmp; + *minor = minorTmp; + *type = identifier.substr(0, numberLoc); + + return true; +} + +bool CMDeviceIDToDeviceAndVendorID(const std::string &id, uint32_t *vendorId, uint32_t *deviceId) +{ + unsigned int vendor = 0; + unsigned int device = 0; + + bool success = id.length() >= 21 && HexStringToUInt(id.substr(8, 4), &vendor) && + HexStringToUInt(id.substr(17, 4), &device); + + *vendorId = vendor; + *deviceId = device; + return success; +} + +void GetDualGPUInfo(SystemInfo *info) +{ + ASSERT(!info->gpus.empty()); + + // On dual-GPU systems we assume the non-Intel GPU is the graphics one. + // TODO: this is incorrect and problematic. activeGPUIndex must be removed if it cannot be + // determined correctly. A potential solution is to create an OpenGL context and parse + // GL_VENDOR. Currently, our test infrastructure is relying on this information and incorrectly + // applies test expectations on dual-GPU systems when the Intel GPU is active. + // http://anglebug.com/6174. + int active = 0; + bool hasIntel = false; + for (size_t i = 0; i < info->gpus.size(); ++i) + { + if (IsIntel(info->gpus[i].vendorId)) + { + hasIntel = true; + } + if (IsIntel(info->gpus[active].vendorId)) + { + active = static_cast<int>(i); + } + } + + // Assume that a combination of NVIDIA or AMD with Intel means Optimus or AMD Switchable + info->activeGPUIndex = active; + info->isOptimus = hasIntel && IsNVIDIA(info->gpus[active].vendorId); + info->isAMDSwitchable = hasIntel && IsAMD(info->gpus[active].vendorId); +} + +void PrintSystemInfo(const SystemInfo &info) +{ + std::cout << info.gpus.size() << " GPUs:\n"; + + for (size_t i = 0; i < info.gpus.size(); i++) + { + const auto &gpu = info.gpus[i]; + + std::cout << " " << i << " - " << VendorName(gpu.vendorId) << " device id: 0x" << std::hex + << std::uppercase << gpu.deviceId << std::dec << ", revision id: 0x" << std::hex + << std::uppercase << gpu.revisionId << std::dec << ", system device id: 0x" + << std::hex << std::uppercase << gpu.systemDeviceId << std::dec << "\n"; + if (!gpu.driverVendor.empty()) + { + std::cout << " Driver Vendor: " << gpu.driverVendor << "\n"; + } + if (!gpu.driverVersion.empty()) + { + std::cout << " Driver Version: " << gpu.driverVersion << "\n"; + } + if (!gpu.driverDate.empty()) + { + std::cout << " Driver Date: " << gpu.driverDate << "\n"; + } + if (gpu.detailedDriverVersion.major != 0 || gpu.detailedDriverVersion.minor != 0 || + gpu.detailedDriverVersion.subMinor != 0 || gpu.detailedDriverVersion.patch != 0) + { + std::cout << " Detailed Driver Version:\n" + << " major: " << gpu.detailedDriverVersion.major + << " minor: " << gpu.detailedDriverVersion.minor + << " subMinor: " << gpu.detailedDriverVersion.subMinor + << " patch: " << gpu.detailedDriverVersion.patch << "\n"; + } + } + + std::cout << "\n"; + std::cout << "Active GPU: " << info.activeGPUIndex << "\n"; + + std::cout << "\n"; + std::cout << "Optimus: " << (info.isOptimus ? "true" : "false") << "\n"; + std::cout << "AMD Switchable: " << (info.isAMDSwitchable ? "true" : "false") << "\n"; + std::cout << "Mac Switchable: " << (info.isMacSwitchable ? "true" : "false") << "\n"; + std::cout << "Needs EAGL on Mac: " << (info.needsEAGLOnMac ? "true" : "false") << "\n"; + + std::cout << "\n"; + if (!info.machineManufacturer.empty()) + { + std::cout << "Machine Manufacturer: " << info.machineManufacturer << "\n"; + } + if (info.androidSdkLevel != 0) + { + std::cout << "Android SDK Level: " << info.androidSdkLevel << "\n"; + } + if (!info.machineModelName.empty()) + { + std::cout << "Machine Model: " << info.machineModelName << "\n"; + } + if (!info.machineModelVersion.empty()) + { + std::cout << "Machine Model Version: " << info.machineModelVersion << "\n"; + } + std::cout << std::endl; +} + +VersionInfo ParseNvidiaDriverVersion(uint32_t version) +{ + return { + version >> 22, // major + version >> 14 & 0xff, // minor + version >> 6 & 0xff, // subMinor + version & 0x3f // patch + }; +} + +uint64_t GetSystemDeviceIdFromParts(uint32_t highPart, uint32_t lowPart) +{ + return (static_cast<uint64_t>(highPart) << 32) | lowPart; +} + +uint32_t GetSystemDeviceIdHighPart(uint64_t systemDeviceId) +{ + return (systemDeviceId >> 32) & 0xffffffff; +} + +uint32_t GetSystemDeviceIdLowPart(uint64_t systemDeviceId) +{ + return systemDeviceId & 0xffffffff; +} + +std::string GetPreferredDeviceString() +{ + std::string device = angle::GetEnvironmentVar(kANGLEPreferredDeviceEnv); + ToLower(&device); + return device; +} + +} // namespace angle |