Use gpu_metrics instead of libdrm when available

gpu_metrics
FlightlessMango 2 years ago
parent 8e2c7e8524
commit 6dc8f53ab2

@ -1,10 +1,37 @@
#include "amdgpu.h"
#include "overlay.h"
struct gpu_metrics_v2_2 amdgpu_metrics;
std::string metrics_path = "";
void amdgpu_get_metrics()
{
std::ifstream in("/sys/class/drm/renderD128/device/gpu_metrics", std::ios_base::in | std::ios_base::binary);
in.read((char*)&amdgpu_metrics, sizeof(amdgpu_metrics));
if (!metrics_path.empty()){
struct metrics_table_header header;
std::ifstream in(metrics_path, std::ios_base::in | std::ios_base::binary);
in.read((char*)&header, sizeof(header));
if (header.format_revision == 1){
// Desktop GPUs
struct gpu_metrics_v1_3 amdgpu_metrics;
in.clear();
in.seekg(0);
in.read((char*)&amdgpu_metrics, sizeof(amdgpu_metrics));
gpu_info.load = amdgpu_metrics.average_gfx_activity;
gpu_info.CoreClock = amdgpu_metrics.average_gfxclk_frequency;
gpu_info.powerUsage = amdgpu_metrics.average_socket_power;
gpu_info.temp = amdgpu_metrics.temperature_edge;
gpu_info.MemClock = amdgpu_metrics.current_uclk;
} else if (header.format_revision == 2){
// APUs
struct gpu_metrics_v2_2 amdgpu_metrics;
in.clear();
in.seekg(0);
in.read((char*)&amdgpu_metrics, sizeof(amdgpu_metrics));
gpu_info.load = amdgpu_metrics.average_gfx_activity;
gpu_info.CoreClock = amdgpu_metrics.average_gfxclk_frequency;
gpu_info.powerUsage = amdgpu_metrics.average_gfx_power;
gpu_info.temp = amdgpu_metrics.temperature_gfx / 100;
gpu_info.MemClock = amdgpu_metrics.current_uclk;
gpu_info.apu_cpu_power = amdgpu_metrics.average_cpu_power;
}
}
}

@ -6,63 +6,138 @@
#include <unistd.h>
#include <vector>
#define NUM_HBM_INSTANCES 4
struct metrics_table_header {
uint16_t structure_size;
uint8_t format_revision;
uint8_t content_revision;
uint16_t structure_size;
uint8_t format_revision;
uint8_t content_revision;
};
struct gpu_metrics_v1_3 {
struct metrics_table_header common_header;
/* Temperature */
uint16_t temperature_edge;
uint16_t temperature_hotspot;
uint16_t temperature_mem;
uint16_t temperature_vrgfx;
uint16_t temperature_vrsoc;
uint16_t temperature_vrmem;
/* Utilization */
uint16_t average_gfx_activity;
uint16_t average_umc_activity; // memory controller
uint16_t average_mm_activity; // UVD or VCN
/* Power/Energy */
uint16_t average_socket_power;
uint64_t energy_accumulator;
/* Driver attached timestamp (in ns) */
uint64_t system_clock_counter;
/* Average clocks */
uint16_t average_gfxclk_frequency;
uint16_t average_socclk_frequency;
uint16_t average_uclk_frequency;
uint16_t average_vclk0_frequency;
uint16_t average_dclk0_frequency;
uint16_t average_vclk1_frequency;
uint16_t average_dclk1_frequency;
/* Current clocks */
uint16_t current_gfxclk;
uint16_t current_socclk;
uint16_t current_uclk;
uint16_t current_vclk0;
uint16_t current_dclk0;
uint16_t current_vclk1;
uint16_t current_dclk1;
/* Throttle status */
uint32_t throttle_status;
/* Fans */
uint16_t current_fan_speed;
/* Link width/speed */
uint16_t pcie_link_width;
uint16_t pcie_link_speed; // in 0.1 GT/s
uint16_t padding;
uint32_t gfx_activity_acc;
uint32_t mem_activity_acc;
uint16_t temperature_hbm[NUM_HBM_INSTANCES];
/* PMFW attached timestamp (10ns resolution) */
uint64_t firmware_timestamp;
/* Voltage (mV) */
uint16_t voltage_soc;
uint16_t voltage_gfx;
uint16_t voltage_mem;
uint16_t padding1;
/* Throttle status (ASIC independent) */
uint64_t indep_throttle_status;
};
struct gpu_metrics_v2_2 {
struct metrics_table_header common_header;
/* Temperature */
uint16_t temperature_gfx; // gfx temperature on APUs
uint16_t temperature_soc; // soc temperature on APUs
uint16_t temperature_core[8]; // CPU core temperature on APUs
uint16_t temperature_l3[2];
/* Utilization */
uint16_t average_gfx_activity;
uint16_t average_mm_activity; // UVD or VCN
/* Driver attached timestamp (in ns) */
uint64_t system_clock_counter;
/* Power/Energy */
uint16_t average_socket_power; // dGPU + APU power on A + A platform
uint16_t average_cpu_power;
uint16_t average_soc_power;
uint16_t average_gfx_power;
uint16_t average_core_power[8]; // CPU core power on APUs
/* Average clocks */
uint16_t average_gfxclk_frequency;
uint16_t average_socclk_frequency;
uint16_t average_uclk_frequency;
uint16_t average_fclk_frequency;
uint16_t average_vclk_frequency;
uint16_t average_dclk_frequency;
/* Current clocks */
uint16_t current_gfxclk;
uint16_t current_socclk;
uint16_t current_uclk;
uint16_t current_fclk;
uint16_t current_vclk;
uint16_t current_dclk;
uint16_t current_coreclk[8]; // CPU core clocks
uint16_t current_l3clk[2];
/* Throttle status (ASIC dependent) */
uint32_t throttle_status;
/* Fans */
uint16_t fan_pwm;
uint16_t padding[3];
/* Throttle status (ASIC independent) */
uint64_t indep_throttle_status;
struct metrics_table_header common_header;
/* Temperature */
uint16_t temperature_gfx; // gfx temperature on APUs
uint16_t temperature_soc; // soc temperature on APUs
uint16_t temperature_core[8]; // CPU core temperature on APUs
uint16_t temperature_l3[2];
/* Utilization */
uint16_t average_gfx_activity;
uint16_t average_mm_activity; // UVD or VCN
/* Driver attached timestamp (in ns) */
uint64_t system_clock_counter;
/* Power/Energy */
uint16_t average_socket_power; // dGPU + APU power on A + A platform
uint16_t average_cpu_power;
uint16_t average_soc_power;
uint16_t average_gfx_power;
uint16_t average_core_power[8]; // CPU core power on APUs
/* Average clocks */
uint16_t average_gfxclk_frequency;
uint16_t average_socclk_frequency;
uint16_t average_uclk_frequency;
uint16_t average_fclk_frequency;
uint16_t average_vclk_frequency;
uint16_t average_dclk_frequency;
/* Current clocks */
uint16_t current_gfxclk;
uint16_t current_socclk;
uint16_t current_uclk;
uint16_t current_fclk;
uint16_t current_vclk;
uint16_t current_dclk;
uint16_t current_coreclk[8]; // CPU core clocks
uint16_t current_l3clk[2];
/* Throttle status (ASIC dependent) */
uint32_t throttle_status;
/* Fans */
uint16_t fan_pwm;
uint16_t padding[3];
/* Throttle status (ASIC independent) */
uint64_t indep_throttle_status;
};
extern void amdgpu_get_metrics();
extern void amdgpu_get_metrics();
extern std::string metrics_path;

@ -248,7 +248,7 @@ bool CPUStats::UpdateCoreMhz() {
bool CPUStats::UpdateCpuTemp() {
#ifdef MANGOAPP
m_cpuDataTotal.temp = amdgpu_metrics.temperature_soc / 100;
m_cpuDataTotal.temp = gpu_info.temp;
#else
if (!m_cpuTempFile)
return false;
@ -349,7 +349,7 @@ static bool get_cpu_power_rapl(CPUPowerData* cpuPowerData, int& power) {
}
static bool get_cpu_power_amdgpu(int& power) {
power = amdgpu_metrics.average_cpu_power / 1000;
power = gpu_info.apu_cpu_power / 1000;
return true;
}

@ -173,9 +173,7 @@ struct amdgpu_handles
, version_minor(minor)
{
set_sampling_period(500000000 /* 500ms */);
#ifndef MANGOAPP
collector = std::thread(&amdgpu_handles::amdgpu_poll, this);
#endif
}
~amdgpu_handles()

@ -26,6 +26,7 @@ struct gpuInfo{
int MemClock;
int CoreClock;
int powerUsage;
int apu_cpu_power;
};
extern struct gpuInfo gpu_info;

@ -5,6 +5,7 @@
#include <condition_variable>
#include <spdlog/spdlog.h>
#include <filesystem.h>
#include <sys/stat.h>
#include "overlay.h"
#include "logging.h"
#include "cpu.h"
@ -44,6 +45,7 @@ std::deque<logData> graph_data;
const char* engines[] = {"Unknown", "OpenGL", "VULKAN", "DXVK", "VKD3D", "DAMAVAND", "ZINK", "WINED3D", "Feral3D", "ToGL", "GAMESCOPE"};
overlay_params *_params {};
double min_frametime, max_frametime;
bool gpu_metrics_exists = false;
void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID)
{
@ -62,6 +64,9 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par
if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] || logger->is_active()) {
if (vendorID == 0x1002 && getAmdGpuInfo_actual)
getAmdGpuInfo_actual();
if (gpu_metrics_exists)
amdgpu_get_metrics();
if (vendorID == 0x10de)
getNvidiaGpuInfo();
@ -96,9 +101,6 @@ void update_hw_info(struct swapchain_stats& sw_stats, struct overlay_params& par
graph_data.push_back(currentLogData);
logger->notify_data_valid();
HUDElements.update_exec();
#ifdef MANGOAPP
amdgpu_get_metrics();
#endif
}
struct hw_info_updater
@ -624,22 +626,32 @@ void init_gpu_stats(uint32_t& vendorID, uint32_t reported_deviceID, overlay_para
SPDLOG_DEBUG("using amdgpu path: {}", path);
#ifdef HAVE_LIBDRM_AMDGPU
int idx = -1;
//TODO make neater
int res = sscanf(path.c_str(), "/sys/class/drm/card%d", &idx);
std::string dri_path = "/dev/dri/card" + std::to_string(idx);
if (!params.enabled[OVERLAY_PARAM_ENABLED_force_amdgpu_hwmon] && res == 1 && amdgpu_open(dri_path.c_str())) {
vendorID = 0x1002;
using_libdrm = true;
getAmdGpuInfo_actual = getAmdGpuInfo_libdrm;
amdgpu_set_sampling_period(params.fps_sampling_period);
SPDLOG_DEBUG("Using libdrm");
// fall through and open sysfs handles for fallback or check DRM version beforehand
} else if (!params.enabled[OVERLAY_PARAM_ENABLED_force_amdgpu_hwmon]) {
SPDLOG_ERROR("Failed to open device '/dev/dri/card{}' with libdrm, falling back to using hwmon sysfs.", idx);
struct stat buffer;
std::string gpu_metrics_path = path + "/device/gpu_metrics";
if (stat(gpu_metrics_path.c_str(), &buffer) == 0 ){
gpu_metrics_exists = true;
metrics_path = gpu_metrics_path;
SPDLOG_DEBUG("Using gpu_metrics");
} else {
int idx = -1;
//TODO make neater
int res = sscanf(path.c_str(), "/sys/class/drm/card%d", &idx);
std::string dri_path = "/dev/dri/card" + std::to_string(idx);
if (!params.enabled[OVERLAY_PARAM_ENABLED_force_amdgpu_hwmon] && res == 1 && amdgpu_open(dri_path.c_str())) {
vendorID = 0x1002;
using_libdrm = true;
getAmdGpuInfo_actual = getAmdGpuInfo_libdrm;
amdgpu_set_sampling_period(params.fps_sampling_period);
SPDLOG_DEBUG("Using libdrm");
// fall through and open sysfs handles for fallback or check DRM version beforehand
} else if (!params.enabled[OVERLAY_PARAM_ENABLED_force_amdgpu_hwmon]) {
SPDLOG_ERROR("Failed to open device '/dev/dri/card{}' with libdrm, falling back to using hwmon sysfs.", idx);
} else if (params.enabled[OVERLAY_PARAM_ENABLED_force_amdgpu_hwmon]) {
SPDLOG_DEBUG("Using amdgpu hwmon");
}
}
#endif

@ -146,7 +146,6 @@ extern ImVec2 real_font_size;
extern std::string wineVersion;
extern std::deque<logData> graph_data;
extern overlay_params *_params;
extern struct gpu_metrics_v2_2 amdgpu_metrics;
extern double min_frametime, max_frametime;
void position_layer(struct swapchain_stats& data, struct overlay_params& params, ImVec2 window_size);

@ -521,6 +521,7 @@ parse_overlay_env(struct overlay_params *params,
params->enabled[OVERLAY_PARAM_ENABLED_gpu_load_change] = 0;
params->enabled[OVERLAY_PARAM_ENABLED_cpu_load_change] = 0;
params->enabled[OVERLAY_PARAM_ENABLED_fps_only] = 0;
params->enabled[OVERLAY_PARAM_ENABLED_force_amdgpu_hwmon] = 0;
params->enabled[OVERLAY_PARAM_ENABLED_fps_color_change] = 0;
params->enabled[OVERLAY_PARAM_ENABLED_core_load_change] = 0;
params->enabled[OVERLAY_PARAM_ENABLED_read_cfg] = read_cfg;
@ -667,6 +668,7 @@ parse_overlay_config(struct overlay_params *params,
#undef OVERLAY_PARAM_CUSTOM
params->enabled[OVERLAY_PARAM_ENABLED_histogram] = 0;
params->enabled[OVERLAY_PARAM_ENABLED_fps_only] = 0;
params->enabled[OVERLAY_PARAM_ENABLED_force_amdgpu_hwmon] = 0;
params->options.erase("full");
}
for (auto& it : params->options) {

Loading…
Cancel
Save