| // |
| // 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 <cstring> |
| #include <fstream> |
| |
| #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<char>(file), std::istreambuf_iterator<char>()); |
| 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<GPUDeviceInfo> *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 |