2020-03-10 05:19:18 +00:00
|
|
|
#include "gpu.h"
|
2020-09-09 08:24:24 +00:00
|
|
|
#include <inttypes.h>
|
2020-10-22 18:37:20 +00:00
|
|
|
#include <memory>
|
|
|
|
#include <functional>
|
|
|
|
#include <thread>
|
|
|
|
#include <cstring>
|
2021-07-16 00:28:46 +00:00
|
|
|
#include <spdlog/spdlog.h>
|
2020-09-09 08:24:24 +00:00
|
|
|
#include "nvctrl.h"
|
2020-10-22 18:37:20 +00:00
|
|
|
#include "timing.hpp"
|
2020-09-09 08:24:24 +00:00
|
|
|
#ifdef HAVE_NVML
|
|
|
|
#include "nvidia_info.h"
|
|
|
|
#endif
|
2020-03-10 05:19:18 +00:00
|
|
|
|
2022-02-11 07:53:06 +00:00
|
|
|
#include "amdgpu.h"
|
2020-10-22 18:37:20 +00:00
|
|
|
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
|
|
|
|
struct gpuInfo gpu_info {};
|
2020-05-22 12:44:34 +00:00
|
|
|
amdgpu_files amdgpu {};
|
2020-10-22 18:37:20 +00:00
|
|
|
decltype(&getAmdGpuInfo) getAmdGpuInfo_actual = nullptr;
|
2020-03-10 05:19:18 +00:00
|
|
|
|
2020-09-09 08:24:24 +00:00
|
|
|
bool checkNvidia(const char *pci_dev){
|
|
|
|
bool nvSuccess = false;
|
|
|
|
#ifdef HAVE_NVML
|
2022-05-10 12:02:18 +00:00
|
|
|
nvSuccess = checkNVML(pci_dev) && getNVMLInfo({});
|
2020-09-09 08:24:24 +00:00
|
|
|
#endif
|
|
|
|
#ifdef HAVE_XNVCTRL
|
|
|
|
if (!nvSuccess)
|
|
|
|
nvSuccess = checkXNVCtrl();
|
|
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
|
|
if (!nvSuccess)
|
|
|
|
nvSuccess = checkNVAPI();
|
|
|
|
#endif
|
|
|
|
return nvSuccess;
|
|
|
|
}
|
|
|
|
|
2022-05-10 12:02:18 +00:00
|
|
|
void getNvidiaGpuInfo(const struct overlay_params& params){
|
2020-06-09 10:44:41 +00:00
|
|
|
#ifdef HAVE_NVML
|
2020-03-10 05:19:18 +00:00
|
|
|
if (nvmlSuccess){
|
2022-05-10 12:02:18 +00:00
|
|
|
getNVMLInfo(params);
|
2020-03-10 05:19:18 +00:00
|
|
|
gpu_info.load = nvidiaUtilization.gpu;
|
|
|
|
gpu_info.temp = nvidiaTemp;
|
|
|
|
gpu_info.memoryUsed = nvidiaMemory.used / (1024.f * 1024.f * 1024.f);
|
|
|
|
gpu_info.CoreClock = nvidiaCoreClock;
|
2020-03-20 11:54:54 +00:00
|
|
|
gpu_info.MemClock = nvidiaMemClock;
|
2020-05-22 12:44:34 +00:00
|
|
|
gpu_info.powerUsage = nvidiaPowerUsage / 1000;
|
2020-11-06 21:04:10 +00:00
|
|
|
gpu_info.memoryTotal = nvidiaMemory.total / (1024.f * 1024.f * 1024.f);
|
2022-05-10 12:02:18 +00:00
|
|
|
if (params.enabled[OVERLAY_PARAM_ENABLED_throttling_status]){
|
|
|
|
gpu_info.is_temp_throttled = (nvml_throttle_reasons & 0x0000000000000060LL) != 0;
|
|
|
|
gpu_info.is_power_throttled = (nvml_throttle_reasons & 0x000000000000008CLL) != 0;
|
|
|
|
gpu_info.is_other_throttled = (nvml_throttle_reasons & 0x0000000000000112LL) != 0;
|
|
|
|
}
|
2020-06-09 10:44:41 +00:00
|
|
|
return;
|
2020-03-30 19:48:56 +00:00
|
|
|
}
|
2020-06-09 10:44:41 +00:00
|
|
|
#endif
|
2020-03-30 19:48:56 +00:00
|
|
|
#ifdef HAVE_XNVCTRL
|
2020-06-09 10:44:41 +00:00
|
|
|
if (nvctrlSuccess) {
|
2020-03-20 11:54:54 +00:00
|
|
|
getNvctrlInfo();
|
|
|
|
gpu_info.load = nvctrl_info.load;
|
|
|
|
gpu_info.temp = nvctrl_info.temp;
|
|
|
|
gpu_info.memoryUsed = nvctrl_info.memoryUsed / (1024.f);
|
|
|
|
gpu_info.CoreClock = nvctrl_info.CoreClock;
|
|
|
|
gpu_info.MemClock = nvctrl_info.MemClock;
|
2020-05-22 12:44:34 +00:00
|
|
|
gpu_info.powerUsage = 0;
|
2020-11-06 21:04:10 +00:00
|
|
|
gpu_info.memoryTotal = nvctrl_info.memoryTotal;
|
2020-06-09 10:44:41 +00:00
|
|
|
return;
|
2020-03-10 05:19:18 +00:00
|
|
|
}
|
2020-03-30 19:48:56 +00:00
|
|
|
#endif
|
2020-09-07 02:38:55 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
nvapi_util();
|
|
|
|
#endif
|
2020-03-10 05:19:18 +00:00
|
|
|
}
|
|
|
|
|
2020-05-22 12:44:34 +00:00
|
|
|
void getAmdGpuInfo(){
|
2020-12-01 05:32:37 +00:00
|
|
|
int64_t value = 0;
|
2022-02-11 07:53:06 +00:00
|
|
|
if (metrics_path.empty()){
|
|
|
|
if (amdgpu.busy) {
|
|
|
|
rewind(amdgpu.busy);
|
|
|
|
fflush(amdgpu.busy);
|
|
|
|
int value = 0;
|
|
|
|
if (fscanf(amdgpu.busy, "%d", &value) != 1)
|
|
|
|
value = 0;
|
|
|
|
gpu_info.load = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (amdgpu.core_clock) {
|
|
|
|
rewind(amdgpu.core_clock);
|
|
|
|
fflush(amdgpu.core_clock);
|
|
|
|
if (fscanf(amdgpu.core_clock, "%" PRId64, &value) != 1)
|
|
|
|
value = 0;
|
|
|
|
|
|
|
|
gpu_info.CoreClock = value / 1000000;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (amdgpu.memory_clock) {
|
|
|
|
rewind(amdgpu.memory_clock);
|
|
|
|
fflush(amdgpu.memory_clock);
|
|
|
|
if (fscanf(amdgpu.memory_clock, "%" PRId64, &value) != 1)
|
|
|
|
value = 0;
|
|
|
|
|
|
|
|
gpu_info.MemClock = value / 1000000;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (amdgpu.power_usage) {
|
|
|
|
rewind(amdgpu.power_usage);
|
|
|
|
fflush(amdgpu.power_usage);
|
|
|
|
if (fscanf(amdgpu.power_usage, "%" PRId64, &value) != 1)
|
|
|
|
value = 0;
|
|
|
|
|
|
|
|
gpu_info.powerUsage = value / 1000000;
|
|
|
|
}
|
|
|
|
}
|
2020-12-01 05:32:37 +00:00
|
|
|
|
2020-05-22 12:44:34 +00:00
|
|
|
if (amdgpu.vram_total) {
|
|
|
|
rewind(amdgpu.vram_total);
|
|
|
|
fflush(amdgpu.vram_total);
|
|
|
|
if (fscanf(amdgpu.vram_total, "%" PRId64, &value) != 1)
|
2020-03-10 05:19:18 +00:00
|
|
|
value = 0;
|
2020-05-22 12:44:34 +00:00
|
|
|
gpu_info.memoryTotal = float(value) / (1024 * 1024 * 1024);
|
2020-03-10 05:19:18 +00:00
|
|
|
}
|
|
|
|
|
2020-05-22 12:44:34 +00:00
|
|
|
if (amdgpu.vram_used) {
|
|
|
|
rewind(amdgpu.vram_used);
|
|
|
|
fflush(amdgpu.vram_used);
|
|
|
|
if (fscanf(amdgpu.vram_used, "%" PRId64, &value) != 1)
|
2020-03-10 05:19:18 +00:00
|
|
|
value = 0;
|
2020-05-22 12:44:34 +00:00
|
|
|
gpu_info.memoryUsed = float(value) / (1024 * 1024 * 1024);
|
2020-03-10 05:19:18 +00:00
|
|
|
}
|
2022-05-06 08:21:11 +00:00
|
|
|
// On some GPUs SMU can sometimes return the wrong temperature.
|
|
|
|
// As HWMON is way more visible than the SMU metrics, let's always trust it as it is the most likely to work
|
|
|
|
if (amdgpu.temp){
|
|
|
|
rewind(amdgpu.temp);
|
|
|
|
fflush(amdgpu.temp);
|
|
|
|
int value = 0;
|
|
|
|
if (fscanf(amdgpu.temp, "%d", &value) != 1)
|
|
|
|
value = 0;
|
|
|
|
gpu_info.temp = value / 1000;
|
|
|
|
}
|
2020-05-10 12:11:56 +00:00
|
|
|
}
|