Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -644,8 +644,8 @@ Example output:
<td>Total VRAM</td>
<td>🟢</td>
<td>🟢</td>
<td>🔴</td>
<td>🔴</td>
<td>🟢</td>
<td>🟢</td>
<td>🔴</td>
<td>🔴</td>
<td>🔴</td>
Expand Down
28 changes: 28 additions & 0 deletions mangohud-next/legacy_gpu_wrapper/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
mangohud_legacy_gpu_wrapper = static_library(
'MangoHud_LegacyGPUWrapper',
files(
'wrapper.cpp',
'../server/common/helpers.cpp',
'../server/metrics/fdinfo.cpp',
'../server/metrics/hwmon.cpp',
'../server/metrics/gpu/gpu.cpp',
'../server/metrics/gpu/intel/i915/i915.cpp',
'../server/metrics/gpu/intel/i915/i915_drm.cpp',
'../server/metrics/gpu/intel/xe/xe.cpp',
'../server/metrics/gpu/intel/xe/xe_drm.cpp',
'../server/metrics/gpu/amdgpu/amdgpu.cpp',
'../server/metrics/gpu/amdgpu/gpu_metrics.cpp',
'../server/metrics/gpu/nvidia/nvidia.cpp',
'../server/metrics/gpu/nvidia/nvml_loader.cpp',
'../server/metrics/gpu/msm/dpu.cpp',
'../server/metrics/gpu/msm/kgsl.cpp',
'../server/metrics/gpu/panfrost.cpp',
'../server/metrics/gpu/panthor.cpp'
),
cpp_args: '-DMANGOHUD_LEGACY -DSPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_TRACE',
include_directories: [
'../server/metrics',
'../server/metrics/gpu'
],
dependencies: [spdlog_dep, libcap_dep, libdrm_dep]
)
128 changes: 128 additions & 0 deletions mangohud-next/legacy_gpu_wrapper/wrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include "gpu/intel/i915/i915.hpp"
#include "gpu/intel/xe/xe.hpp"
#include "gpu/msm/dpu.hpp"
#include "gpu/msm/kgsl.hpp"
#include "gpu/panfrost.hpp"
#include "gpu/panthor.hpp"

#include "wrapper.hpp"

struct LegacyGPUWrapper::Impl {
Impl(
const std::string& driver, const std::string& drm_node, const std::string& pci_dev,
uint16_t vendor_id, uint16_t device_id
) {
if (driver == "i915") {
gpu = std::make_unique<Intel_i915>(drm_node, pci_dev, vendor_id, device_id);
} else if (driver == "xe") {
gpu = std::make_unique<Intel_xe>(drm_node, pci_dev, vendor_id, device_id);
} else if (driver == "msm_dpu") {
gpu = std::make_unique<MSM_DPU>(drm_node, pci_dev, vendor_id, device_id);
} else if (driver == "msm_drm") {
gpu = std::make_unique<MSM_KGSL>(drm_node, pci_dev, vendor_id, device_id);
} else if (driver == "panfrost") {
gpu = std::make_unique<Panfrost>(drm_node, pci_dev, vendor_id, device_id);
} else if (driver == "panthor") {
gpu = std::make_unique<Panthor>(drm_node, pci_dev, vendor_id, device_id);
}

if (gpu) {
gpu->start_thread_worker();
} else {
SPDLOG_WARN("Failed to construct gpu with driver {} on node {}", driver, drm_node);
}
}

~Impl() {}

std::unique_ptr<GPU> gpu;

std::map<pid_t, gpu_metrics_process_t> process_metrics;
gpu_metrics_system_t system_metrics;
};

LegacyGPUWrapper::LegacyGPUWrapper(
const std::string& driver, const std::string& drm_node, const std::string& pci_dev,
uint16_t vendor_id, uint16_t device_id
) {
m_impl = std::make_unique<Impl>(driver, drm_node, pci_dev, vendor_id, device_id);
}

LegacyGPUWrapper::~LegacyGPUWrapper() {

}

void LegacyGPUWrapper::poll() {
m_impl->process_metrics = m_impl->gpu->get_process_metrics();
m_impl->system_metrics = m_impl->gpu->get_system_metrics();
}

void LegacyGPUWrapper::add_pid(pid_t pid) {
m_impl->gpu->add_pid(pid);

if (auto* ptr = dynamic_cast<FDInfo*>(m_impl->gpu.get())) {
ptr->fdinfo.add_pid(pid);
}
}

#define GENERATE_SYS_METRIC_GETTER(name) \
decltype(std::declval<LegacyGPUWrapper>().get_##name()) LegacyGPUWrapper::get_##name() { \
return m_impl->system_metrics.name; \
}

#define GENERATE_PROC_METRIC_GETTER(name) \
decltype(std::declval<LegacyGPUWrapper>().get_process_##name(0)) \
LegacyGPUWrapper::get_process_##name(pid_t pid) { \
return m_impl->process_metrics[pid].name; \
}

GENERATE_SYS_METRIC_GETTER(load)
GENERATE_SYS_METRIC_GETTER(vram_used)
GENERATE_SYS_METRIC_GETTER(gtt_used)
GENERATE_SYS_METRIC_GETTER(memory_total)
GENERATE_SYS_METRIC_GETTER(memory_clock)
GENERATE_SYS_METRIC_GETTER(memory_temp)
GENERATE_SYS_METRIC_GETTER(temperature)
GENERATE_SYS_METRIC_GETTER(junction_temperature)
GENERATE_SYS_METRIC_GETTER(core_clock)
GENERATE_SYS_METRIC_GETTER(voltage)
GENERATE_SYS_METRIC_GETTER(power_usage)
GENERATE_SYS_METRIC_GETTER(power_limit)
GENERATE_SYS_METRIC_GETTER(is_apu)
GENERATE_SYS_METRIC_GETTER(apu_cpu_power)
GENERATE_SYS_METRIC_GETTER(apu_cpu_temp)
GENERATE_SYS_METRIC_GETTER(is_power_throttled)
GENERATE_SYS_METRIC_GETTER(is_current_throttled)
GENERATE_SYS_METRIC_GETTER(is_temp_throttled)
GENERATE_SYS_METRIC_GETTER(is_other_throttled)
GENERATE_SYS_METRIC_GETTER(fan_speed)
GENERATE_SYS_METRIC_GETTER(fan_rpm)

GENERATE_PROC_METRIC_GETTER(load)
GENERATE_PROC_METRIC_GETTER(vram_used)
GENERATE_PROC_METRIC_GETTER(gtt_used)

struct LegacyFDInfoWrapper::Impl {
Impl(const std::string& drm_node) : fdinfo(drm_node) {}
~Impl() {}

FDInfoWrapper fdinfo;
};

LegacyFDInfoWrapper::LegacyFDInfoWrapper(const std::string& drm_node) {
m_impl = std::make_unique<Impl>(drm_node);
}

LegacyFDInfoWrapper::~LegacyFDInfoWrapper() {}

void LegacyFDInfoWrapper::add_pid(pid_t pid) {
m_impl->fdinfo.add_pid(pid);
}

void LegacyFDInfoWrapper::poll_all() {
m_impl->fdinfo.poll_all();
}

float LegacyFDInfoWrapper::get_memory_used(pid_t pid, const std::string& key) {
return m_impl->fdinfo.get_memory_used(pid, key);
}
73 changes: 73 additions & 0 deletions mangohud-next/legacy_gpu_wrapper/wrapper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#pragma once

#include <unistd.h>
#include <cstdint>
#include <string>
#include <memory>

class LegacyGPUWrapper {
public:
LegacyGPUWrapper(
const std::string& driver, const std::string& drm_node, const std::string& pci_dev,
uint16_t vendor_id, uint16_t device_id
);

~LegacyGPUWrapper();

void poll();
void add_pid(pid_t pid);

// System-related functions
int get_load();

float get_vram_used();
float get_gtt_used();
float get_memory_total();
int get_memory_clock();
int get_memory_temp();

int get_temperature();
int get_junction_temperature();

int get_core_clock();
int get_voltage();

float get_power_usage();
float get_power_limit();

bool get_is_apu();
float get_apu_cpu_power();
int get_apu_cpu_temp();

bool get_is_power_throttled();
bool get_is_current_throttled();
bool get_is_temp_throttled();
bool get_is_other_throttled();

int get_fan_speed();
bool get_fan_rpm();

// Process-related functions
int get_process_load(pid_t pid);
float get_process_vram_used(pid_t pid);
float get_process_gtt_used(pid_t pid);

private:
struct Impl;
std::unique_ptr<Impl> m_impl;
};


class LegacyFDInfoWrapper {
public:
LegacyFDInfoWrapper(const std::string& drm_node);
~LegacyFDInfoWrapper();

void add_pid(pid_t pid);
void poll_all();
float get_memory_used(pid_t pid, const std::string& key);

private:
struct Impl;
std::unique_ptr<Impl> m_impl;
};
28 changes: 26 additions & 2 deletions mangohud-next/server/metrics/fdinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace fs = std::filesystem;
using namespace std::chrono_literals;

FDInfoBase::FDInfoBase(const std::string& drm_node, const pid_t pid) : drm_node(drm_node), pid(pid) {
card_node = get_card_node();
init();
}

Expand Down Expand Up @@ -72,10 +73,10 @@ std::vector<std::string> FDInfoBase::find_fds() {
continue;
}

// comparison to both renderD* and card* is required because
// for some reason supertuxkart opens /dev/dri/card and not renderD
// inside podman container.
// this is only for testing, so remove it later
if (link.filename() != drm_node && link.string().substr(0, 13) != "/dev/dri/card")
if (link.filename() != drm_node && link.filename() != card_node)
continue;

fds.push_back(entry.path().filename());
Expand Down Expand Up @@ -121,6 +122,29 @@ void FDInfoBase::open_fds(const std::vector<std::string>& fds) {
SPDLOG_DEBUG("Received {} ids, opened {} unique ids", fds.size(), total);
}

std::string FDInfoBase::get_card_node() {
const std::string device = "/sys/class/drm/" + drm_node + "/device/drm";

if (!std::filesystem::exists(device)) {
SPDLOG_DEBUG("drm dir doesn't exist for {}", drm_node);
return "";
}

// Find first dir which starts with name "card"
for (const auto& entry : fs::directory_iterator(device)) {
std::filesystem::path path = entry.path();

if (path.filename().string().substr(0, 4) == "card") {
const std::string filename = path.filename();
SPDLOG_DEBUG("found card node for {}: {}", drm_node, filename);
return filename;
}
}

SPDLOG_DEBUG("didn't find card node for {}", drm_node);
return "";
}

void FDInfoWrapper::add_pid(pid_t pid) {
std::unique_lock lock(pids_mutex);

Expand Down
2 changes: 2 additions & 0 deletions mangohud-next/server/metrics/fdinfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ class FDInfoBase {
private:
std::vector<std::ifstream> fds_streams;
chrono_timer last_init;
std::string card_node;

std::vector<std::string> find_fds();
void open_fds(const std::vector<std::string>& fds);
std::string get_card_node();

public:
const std::string drm_node;
Expand Down
Loading
Loading