// // Copyright (c) 2013-2017 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_linux.cpp: implementation of the Linux-specific parts of SystemInfo.h #include "gpu_info_util/SystemInfo_internal.h" #include #include #include "common/angleutils.h" #include "common/debug.h" namespace angle { namespace { bool ReadWholeFile(const char *filename, std::string *content) { std::ifstream file(filename); if (!file) { return false; } *content = std::string(std::istreambuf_iterator(file), std::istreambuf_iterator()); return true; } // Scan /sys/module/amdgpu/version. bool GetAMDBrahmaDriverVersion(std::string *version) { *version = ""; std::string content; return ReadWholeFile("/sys/module/amdgpu/version", &content) && ParseAMDBrahmaDriverVersion(content, version); } // Scan /etc/ati/amdpcsdb.default for "ReleaseVersion". bool GetAMDCatalystDriverVersion(std::string *version) { *version = ""; std::string content; return ReadWholeFile("/etc/ati/amdpcsdb.default", &content) && ParseAMDCatalystDriverVersion(content, version); } } // anonymous namespace #if !defined(GPU_INFO_USE_X11) bool GetNvidiaDriverVersionWithXNVCtrl(std::string *version) { return false; } #endif #if !defined(GPU_INFO_USE_LIBPCI) bool GetPCIDevicesWithLibPCI(std::vector *devices) { return false; } #endif bool GetSystemInfo(SystemInfo *info) { if (!GetPCIDevicesWithLibPCI(&(info->gpus))) { return false; } if (info->gpus.size() == 0) { return false; } FindPrimaryGPU(info); for (size_t i = 0; i < info->gpus.size(); ++i) { GPUDeviceInfo *gpu = &info->gpus[i]; // New GPUs might be added inside this loop, don't query for their driver version again if (!gpu->driverVendor.empty()) { continue; } if (IsAMD(gpu->vendorId)) { std::string version; if (GetAMDBrahmaDriverVersion(&version)) { gpu->driverVendor = "AMD (Brahma)"; gpu->driverVersion = std::move(version); } else if (GetAMDCatalystDriverVersion(&version)) { gpu->driverVendor = "AMD (Catalyst)"; gpu->driverVersion = std::move(version); } } if (IsNvidia(gpu->vendorId)) { std::string version; if (GetNvidiaDriverVersionWithXNVCtrl(&version)) { gpu->driverVendor = "Nvidia"; gpu->driverVersion = std::move(version); } } // In dual-GPU cases the PCI scan sometimes only gives us the Intel GPU. // If we are able to query for the Nvidia driver version, it means there // was hidden Nvidia GPU, so we add it to the list and make it primary. if (IsIntel(gpu->vendorId) && info->gpus.size() == 1) { std::string version; if (GetNvidiaDriverVersionWithXNVCtrl(&version)) { GPUDeviceInfo nvidiaInfo; nvidiaInfo.vendorId = kVendorID_Nvidia; nvidiaInfo.deviceId = 0; gpu->driverVendor = "Nvidia"; gpu->driverVersion = std::move(version); info->gpus.emplace_back(std::move(nvidiaInfo)); info->isOptimus = true; } } } return true; } } // namespace angle