summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/gpu_info_util/SystemInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/gpu_info_util/SystemInfo.cpp')
-rw-r--r--gfx/angle/checkout/src/gpu_info_util/SystemInfo.cpp418
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