From a9311bb5788a204928cd915e780c4d834e368f81 Mon Sep 17 00:00:00 2001 From: jackun Date: Sat, 11 Apr 2020 00:30:24 +0300 Subject: [PATCH] Allow to specify gpu with pci bus id by setting env var `MANGOHUD_PCI_DEV=xxxx:xx:xx:x` where x's are "domain:bus:slot.function" --- src/file_utils.cpp | 9 +++-- src/file_utils.h | 1 + src/nvidia_info.h | 6 ++-- src/nvml.cpp | 21 ++++++++---- src/overlay.cpp | 83 +++++++++++++++++++++++++++++++--------------- 5 files changed, 82 insertions(+), 38 deletions(-) diff --git a/src/file_utils.cpp b/src/file_utils.cpp index 5953aad0..827be605 100644 --- a/src/file_utils.cpp +++ b/src/file_utils.cpp @@ -100,13 +100,18 @@ bool dir_exists(const std::string& path) return !stat(path.c_str(), &s) && S_ISDIR(s.st_mode); } -std::string get_exe_path() +std::string readlink(const char * link) { char result[PATH_MAX] {}; - ssize_t count = readlink("/proc/self/exe", result, PATH_MAX); + ssize_t count = readlink(link, result, PATH_MAX); return std::string(result, (count > 0) ? count : 0); } +std::string get_exe_path() +{ + return readlink("/proc/self/exe"); +} + bool get_wine_exe_name(std::string& name, bool keep_ext) { std::string line; diff --git a/src/file_utils.h b/src/file_utils.h index 9b845d8c..67e05e03 100644 --- a/src/file_utils.h +++ b/src/file_utils.h @@ -15,6 +15,7 @@ bool find_folder(const std::string& root, const std::string& prefix, std::string std::vector ls(const char* root, const char* prefix = nullptr, LS_FLAGS flags = LS_DIRS); bool file_exists(const std::string& path); bool dir_exists(const std::string& path); +std::string readlink(const char * link); std::string get_exe_path(); bool get_wine_exe_name(std::string& name, bool keep_ext = false); std::string get_home_dir(); diff --git a/src/nvidia_info.h b/src/nvidia_info.h index 2da55fd1..66a5b906 100644 --- a/src/nvidia_info.h +++ b/src/nvidia_info.h @@ -1,5 +1,3 @@ -#include -#include #include extern nvmlReturn_t result; @@ -9,5 +7,5 @@ extern struct nvmlUtilization_st nvidiaUtilization; extern struct nvmlMemory_st nvidiaMemory; extern bool nvmlSuccess; -bool checkNVML(void); -bool getNVMLInfo(void); \ No newline at end of file +bool checkNVML(const char* pciBusId); +bool getNVMLInfo(void); diff --git a/src/nvml.cpp b/src/nvml.cpp index df41a219..95170bef 100644 --- a/src/nvml.cpp +++ b/src/nvml.cpp @@ -1,5 +1,6 @@ #include "loaders/loader_nvml.h" #include "nvidia_info.h" +#include libnvml_loader nvml("libnvidia-ml.so.1"); @@ -10,24 +11,32 @@ unsigned int nvidiaTemp, nvidiaCoreClock, nvidiaMemClock; struct nvmlUtilization_st nvidiaUtilization; struct nvmlMemory_st nvidiaMemory {}; -bool checkNVML(){ +bool checkNVML(const char* pciBusId){ if (nvml.IsLoaded()){ result = nvml.nvmlInit(); if (NVML_SUCCESS != result) { - printf("MANGOHUD: Nvidia module not loaded\n"); + std::cerr << "MANGOHUD: Nvidia module not loaded\n"; } else { - nvmlSuccess = true; - return true; + nvmlReturn_t ret = NVML_ERROR_UNKNOWN; + if (pciBusId) + ret = nvml.nvmlDeviceGetHandleByPciBusId(pciBusId, &nvidiaDevice); + + if (ret != NVML_SUCCESS) { + std::cerr << "MANGOHUD: Getting handle by PCI bus ID failed! Using index 0.\n"; + ret = nvml.nvmlDeviceGetHandleByIndex(0, &nvidiaDevice); + } + + nvmlSuccess = (ret == NVML_SUCCESS); + return nvmlSuccess; } } else { - printf("Failed to load NVML!\n"); + std::cerr << "MANGOHUD: Failed to load NVML\n"; } return false; } bool getNVMLInfo(){ nvmlReturn_t response; - nvml.nvmlDeviceGetHandleByIndex(0, &nvidiaDevice); response = nvml.nvmlDeviceGetUtilizationRates(nvidiaDevice, &nvidiaUtilization); nvml.nvmlDeviceGetTemperature(nvidiaDevice, NVML_TEMPERATURE_GPU, &nvidiaTemp); nvml.nvmlDeviceGetMemoryInfo(nvidiaDevice, &nvidiaMemory); diff --git a/src/overlay.cpp b/src/overlay.cpp index be6899a1..a52a45c0 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -706,16 +706,39 @@ void init_cpu_stats(overlay_params& params) && enabled[OVERLAY_PARAM_ENABLED_cpu_temp]; } +struct PCI_BUS { + int domain; + int bus; + int slot; + int func; +}; + void init_gpu_stats(uint32_t& vendorID, overlay_params& params) { if (!params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats]) return; + PCI_BUS pci; + bool pci_bus_parsed = false; + const char* env_pci_dev = getenv("MANGOHUD_PCI_DEV"); + + // for now just checks if pci bus parses correctly, if at all necessary + if (env_pci_dev) { + if (sscanf(env_pci_dev, "%04x:%02x:%02x.%x", + &pci.domain, &pci.bus, + &pci.slot, &pci.func) == 4) { + pci_bus_parsed = true; + } else { + std::cerr << "MANGOHUD: Failed to parse PCI device ID: " << env_pci_dev << "\n"; + std::cerr << "MANGOHUD: It has to be formatted as 'xxxx:xx:xx.x' (domain:bus:slot.func)\n"; + } + } + // NVIDIA or Intel but maybe has Optimus if (vendorID == 0x8086 || vendorID == 0x10de) { - bool nvSuccess = (checkNVML() && getNVMLInfo()); + bool nvSuccess = (checkNVML(env_pci_dev) && getNVMLInfo()); #ifdef HAVE_XNVCTRL if (!nvSuccess) @@ -743,37 +766,45 @@ void init_gpu_stats(uint32_t& vendorID, overlay_params& params) string line = read_line(path + "/device/vendor"); trim(line); - if (line != "0x1002") + if (line != "0x1002" || !file_exists(path + "/device/gpu_busy_percent")) continue; + path += "/device"; + if (pci_bus_parsed && env_pci_dev) { + string pci_device = readlink(path.c_str()); +#ifndef NDEBUG + std::cerr << "PCI device symlink: " << pci_device << "\n"; +#endif + if (!ends_with(pci_device, env_pci_dev)) { + std::cerr << "MANGOHUD: skipping GPU, no PCI ID match\n"; + continue; + } + } + #ifndef NDEBUG std::cerr << "using amdgpu path: " << path << std::endl; #endif - if (file_exists(path + "/device/gpu_busy_percent")) { - if (!amdGpuFile) - amdGpuFile = fopen((path + "/device/gpu_busy_percent").c_str(), "r"); - if (!amdGpuVramTotalFile) - amdGpuVramTotalFile = fopen((path + "/device/mem_info_vram_total").c_str(), "r"); - if (!amdGpuVramUsedFile) - amdGpuVramUsedFile = fopen((path + "/device/mem_info_vram_used").c_str(), "r"); - - path = path + "/device/hwmon/"; - string tempFolder; - if (find_folder(path, "hwmon", tempFolder)) { - if (!amdGpuCoreClockFile) - amdGpuCoreClockFile = fopen((path + tempFolder + "/freq1_input").c_str(), "r"); - if (!amdGpuMemoryClockFile) - amdGpuMemoryClockFile = fopen((path + tempFolder + "/freq2_input").c_str(), "r"); - path = path + tempFolder + "/temp1_input"; - - if (!amdTempFile) - amdTempFile = fopen(path.c_str(), "r"); - - params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = true; - vendorID = 0x1002; - break; - } + if (!amdGpuFile) + amdGpuFile = fopen((path + "/gpu_busy_percent").c_str(), "r"); + if (!amdGpuVramTotalFile) + amdGpuVramTotalFile = fopen((path + "/mem_info_vram_total").c_str(), "r"); + if (!amdGpuVramUsedFile) + amdGpuVramUsedFile = fopen((path + "/mem_info_vram_used").c_str(), "r"); + + path += "/hwmon/"; + string tempFolder; + if (find_folder(path, "hwmon", tempFolder)) { + if (!amdGpuCoreClockFile) + amdGpuCoreClockFile = fopen((path + tempFolder + "/freq1_input").c_str(), "r"); + if (!amdGpuMemoryClockFile) + amdGpuMemoryClockFile = fopen((path + tempFolder + "/freq2_input").c_str(), "r"); + if (!amdTempFile) + amdTempFile = fopen((path + tempFolder + "/temp1_input").c_str(), "r"); + + params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = true; + vendorID = 0x1002; + break; } }