mirror of
https://github.com/flightlessmango/MangoHud.git
synced 2024-11-13 13:10:27 +00:00
Add some radeon
support. Link with libdrm etc. directly.
This commit is contained in:
parent
14507c402d
commit
365c4bef97
10
meson.build
10
meson.build
@ -88,14 +88,18 @@ if is_unixy
|
||||
dep_wayland_client = dependency('wayland-client',
|
||||
required: get_option('with_wayland'), version : '>=1.11')
|
||||
dbus_dep = dependency('dbus-1', required: get_option('with_dbus')).partial_dependency(compile_args : true, includes : true)
|
||||
dep_libdrm = dependency('libdrm', required: get_option('with_libdrm_amdgpu')).partial_dependency(compile_args : true, includes : true)
|
||||
# dep_libdrm_amdgpu = dependency('libdrm_amdgpu', version : '>=2.4.79', required: get_option('with_libdrm_amdgpu')).partial_dependency(compile_args : true, includes : true)
|
||||
dep_libdrm = dependency('libdrm', required: get_option('with_libdrm'))
|
||||
dep_libdrm_amdgpu = dependency('libdrm_amdgpu', version : '>=2.4.79', required: get_option('with_libdrm_amdgpu'))
|
||||
dep_xcb = dependency('xcb', required: get_option('with_libdrm'))
|
||||
dep_xcb_dri2 = dependency('xcb-dri2', required: get_option('with_libdrm'))
|
||||
else
|
||||
dep_x11 = null_dep
|
||||
dep_wayland_client = null_dep
|
||||
dbus_dep = null_dep
|
||||
dep_libdrm = null_dep
|
||||
# dep_libdrm_amdgpu = null_dep
|
||||
dep_libdrm_amdgpu = null_dep
|
||||
dep_xcb = null_dep
|
||||
dep_xcb_dri2 = null_dep
|
||||
endif
|
||||
|
||||
if dep_x11.found()
|
||||
|
@ -13,5 +13,6 @@ option('with_x11', type : 'feature', value : 'enabled')
|
||||
option('with_wayland', type : 'feature', value : 'disabled')
|
||||
option('with_dbus', type : 'feature', value : 'enabled')
|
||||
option('with_dlsym', type : 'feature', value : 'disabled')
|
||||
option('with_libdrm', type : 'feature', value : 'enabled', description: 'Enable libdrm support')
|
||||
option('with_libdrm_amdgpu', type : 'feature', value : 'enabled', description: 'Get amdgpu sensor info through libdrm_amdgpu')
|
||||
option('loglevel', type: 'combo', choices : ['trace', 'debug', 'info', 'warn', 'err', 'critical', 'off'], value : 'info', description: 'Max log level in non-debug build')
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
Inspired by radeontop
|
||||
*/
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "auth.h"
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/dri2.h>
|
||||
@ -46,7 +47,7 @@ bool authenticate_drm(int fd) {
|
||||
/* Try self-authenticate (if we are somehow the master). */
|
||||
if (drmAuthMagic(fd, magic) == 0) {
|
||||
if (drmDropMaster(fd)) {
|
||||
perror("MANGOHUD: Failed to drop DRM master");
|
||||
SPDLOG_ERROR("MANGOHUD: Failed to drop DRM master: {}", strerror(errno));
|
||||
fprintf(stderr, "\n\tWARNING: other DRM clients will crash on VT switch\n");
|
||||
}
|
||||
return true;
|
||||
|
42
src/gpu.cpp
42
src/gpu.cpp
@ -18,7 +18,6 @@
|
||||
#include <libdrm/amdgpu.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "loaders/loader_libdrm.h"
|
||||
#endif
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
@ -144,14 +143,8 @@ void getAmdGpuInfo(){
|
||||
#define DRM_ATLEAST_VERSION(ver, maj, min) \
|
||||
(ver->version_major > maj || (ver->version_major == maj && ver->version_minor >= min))
|
||||
|
||||
enum {
|
||||
GRBM_STATUS = 0x8010,
|
||||
};
|
||||
|
||||
static std::unique_ptr<libdrm_amdgpu_loader> libdrm_amdgpu_ptr;
|
||||
|
||||
static int getgrbm_amdgpu(amdgpu_device_handle dev, uint32_t *out) {
|
||||
return libdrm_amdgpu_ptr->amdgpu_read_mm_registers(dev, GRBM_STATUS / 4, 1,
|
||||
return amdgpu_read_mm_registers(dev, GRBM_STATUS / 4, 1,
|
||||
0xffffffff, 0, out);
|
||||
}
|
||||
|
||||
@ -181,7 +174,7 @@ struct amdgpu_handles
|
||||
quit = true;
|
||||
if (collector.joinable())
|
||||
collector.join();
|
||||
libdrm_amdgpu_ptr->amdgpu_device_deinitialize(dev);
|
||||
amdgpu_device_deinitialize(dev);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
@ -225,15 +218,6 @@ void amdgpu_set_sampling_period(uint32_t period)
|
||||
}
|
||||
|
||||
bool amdgpu_open(const char *path) {
|
||||
if (!g_libdrm.IsLoaded())
|
||||
return false;
|
||||
|
||||
if (!libdrm_amdgpu_ptr)
|
||||
libdrm_amdgpu_ptr = std::make_unique<libdrm_amdgpu_loader>();
|
||||
|
||||
if (!libdrm_amdgpu_ptr->IsLoaded())
|
||||
return false;
|
||||
|
||||
int fd = open(path, O_RDWR | O_CLOEXEC);
|
||||
|
||||
if (fd < 0) {
|
||||
@ -241,7 +225,7 @@ bool amdgpu_open(const char *path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
drmVersionPtr ver = g_libdrm.drmGetVersion(fd);
|
||||
drmVersionPtr ver = drmGetVersion(fd);
|
||||
|
||||
if (!ver) {
|
||||
SPDLOG_ERROR("Failed to query driver version: {}", strerror(errno));
|
||||
@ -252,10 +236,10 @@ bool amdgpu_open(const char *path) {
|
||||
if (strcmp(ver->name, "amdgpu") || !DRM_ATLEAST_VERSION(ver, 3, 11)) {
|
||||
SPDLOG_ERROR("Unsupported driver/version: {} {}.{}.{}", ver->name, ver->version_major, ver->version_minor, ver->version_patchlevel);
|
||||
close(fd);
|
||||
g_libdrm.drmFreeVersion(ver);
|
||||
drmFreeVersion(ver);
|
||||
return false;
|
||||
}
|
||||
g_libdrm.drmFreeVersion(ver);
|
||||
drmFreeVersion(ver);
|
||||
|
||||
/*
|
||||
if (!authenticate_drm(fd)) {
|
||||
@ -266,7 +250,7 @@ bool amdgpu_open(const char *path) {
|
||||
|
||||
uint32_t drm_major, drm_minor;
|
||||
amdgpu_device_handle dev;
|
||||
if (libdrm_amdgpu_ptr->amdgpu_device_initialize(fd, &drm_major, &drm_minor, &dev)){
|
||||
if (amdgpu_device_initialize(fd, &drm_major, &drm_minor, &dev)){
|
||||
SPDLOG_ERROR("Failed to initialize amdgpu device: {}", strerror(errno));
|
||||
close(fd);
|
||||
return false;
|
||||
@ -288,27 +272,27 @@ void getAmdGpuInfo_libdrm()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!libdrm_amdgpu_ptr->amdgpu_query_info(amdgpu_dev->dev, AMDGPU_INFO_VRAM_USAGE, sizeof(uint64_t), &value))
|
||||
if (!amdgpu_query_info(amdgpu_dev->dev, AMDGPU_INFO_VRAM_USAGE, sizeof(uint64_t), &value))
|
||||
gpu_info.memoryUsed = float(value) / (1024 * 1024 * 1024);
|
||||
|
||||
// FIXME probably not correct sensor
|
||||
if (!libdrm_amdgpu_ptr->amdgpu_query_info(amdgpu_dev->dev, AMDGPU_INFO_MEMORY, sizeof(uint64_t), &value))
|
||||
if (!amdgpu_query_info(amdgpu_dev->dev, AMDGPU_INFO_MEMORY, sizeof(uint64_t), &value))
|
||||
gpu_info.memoryTotal = float(value) / (1024 * 1024 * 1024);
|
||||
|
||||
if (!libdrm_amdgpu_ptr->amdgpu_query_sensor_info(amdgpu_dev->dev, AMDGPU_INFO_SENSOR_GFX_SCLK, sizeof(uint32_t), &value32))
|
||||
if (!amdgpu_query_sensor_info(amdgpu_dev->dev, AMDGPU_INFO_SENSOR_GFX_SCLK, sizeof(uint32_t), &value32))
|
||||
gpu_info.CoreClock = value32;
|
||||
|
||||
if (!libdrm_amdgpu_ptr->amdgpu_query_sensor_info(amdgpu_dev->dev, AMDGPU_INFO_SENSOR_GFX_MCLK, sizeof(uint32_t), &value32)) // XXX Doesn't work on APUs
|
||||
if (!amdgpu_query_sensor_info(amdgpu_dev->dev, AMDGPU_INFO_SENSOR_GFX_MCLK, sizeof(uint32_t), &value32)) // XXX Doesn't work on APUs
|
||||
gpu_info.MemClock = value32;
|
||||
|
||||
//if (!libdrm_amdgpu_ptr->amdgpu_query_sensor_info(amdgpu_dev->dev, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(uint32_t), &value32))
|
||||
//if (!amdgpu_query_sensor_info(amdgpu_dev->dev, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(uint32_t), &value32))
|
||||
// gpu_info.load = value32;
|
||||
gpu_info.load = amdgpu_dev->gui_percent;
|
||||
|
||||
if (!libdrm_amdgpu_ptr->amdgpu_query_sensor_info(amdgpu_dev->dev, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(uint32_t), &value32))
|
||||
if (!amdgpu_query_sensor_info(amdgpu_dev->dev, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(uint32_t), &value32))
|
||||
gpu_info.temp = value32 / 1000;
|
||||
|
||||
if (!libdrm_amdgpu_ptr->amdgpu_query_sensor_info(amdgpu_dev->dev, AMDGPU_INFO_SENSOR_GPU_AVG_POWER, sizeof(uint32_t), &value32))
|
||||
if (!amdgpu_query_sensor_info(amdgpu_dev->dev, AMDGPU_INFO_SENSOR_GPU_AVG_POWER, sizeof(uint32_t), &value32))
|
||||
gpu_info.powerUsage = value32;
|
||||
}
|
||||
#endif
|
||||
|
@ -5,6 +5,10 @@
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
|
||||
enum {
|
||||
GRBM_STATUS = 0x8010,
|
||||
};
|
||||
|
||||
struct amdgpu_files
|
||||
{
|
||||
FILE *busy;
|
||||
@ -32,6 +36,11 @@ extern struct gpuInfo gpu_info;
|
||||
|
||||
void getNvidiaGpuInfo(void);
|
||||
void getAmdGpuInfo(void);
|
||||
#ifdef HAVE_LIBDRM
|
||||
void getRadeonInfo_libdrm();
|
||||
bool radeon_open(const char *path);
|
||||
void radeon_set_sampling_period(uint32_t period);
|
||||
#endif
|
||||
#ifdef HAVE_LIBDRM_AMDGPU
|
||||
void getAmdGpuInfo_libdrm();
|
||||
bool amdgpu_open(const char *path);
|
||||
|
202
src/gpu_radeon.cpp
Normal file
202
src/gpu_radeon.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "gpu.h"
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <radeon_drm.h>
|
||||
#include <xf86drm.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "auth.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
#ifndef RADEON_INFO_VRAM_USAGE
|
||||
#define RADEON_INFO_VRAM_USAGE 0x1e
|
||||
#endif
|
||||
#ifndef RADEON_INFO_READ_REG
|
||||
#define RADEON_INFO_READ_REG 0x24
|
||||
#endif
|
||||
#ifndef RADEON_INFO_CURRENT_GPU_SCLK
|
||||
#define RADEON_INFO_CURRENT_GPU_SCLK 0x22
|
||||
#endif
|
||||
#ifndef RADEON_INFO_CURRENT_GPU_MCLK
|
||||
#define RADEON_INFO_CURRENT_GPU_MCLK 0x23
|
||||
#endif
|
||||
|
||||
static const char* get_enum_str(uint32_t request)
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
case RADEON_INFO_READ_REG: return "RADEON_INFO_READ_REG";
|
||||
case RADEON_INFO_VRAM_USAGE: return "RADEON_INFO_VRAM_USAGE";
|
||||
case RADEON_INFO_CURRENT_GPU_SCLK: return "RADEON_INFO_CURRENT_GPU_SCLK";
|
||||
case RADEON_INFO_CURRENT_GPU_MCLK: return "RADEON_INFO_CURRENT_GPU_MCLK";
|
||||
default: break;
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
#define DRM_ATLEAST_VERSION(ver, maj, min) \
|
||||
(ver->version_major > maj || (ver->version_major == maj && ver->version_minor >= min))
|
||||
|
||||
static int get_radeon_drm_value(int fd, uint32_t request, void *out)
|
||||
{
|
||||
struct drm_radeon_info info {};
|
||||
info.value = reinterpret_cast<uint64_t>(out);
|
||||
info.request = request;
|
||||
|
||||
// Or ioctl(fd, DRM_IOCTL_RADEON_INFO, &info);
|
||||
int ret = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
|
||||
if (ret)
|
||||
SPDLOG_ERROR("radeon drm error: {}", get_enum_str(request));
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct radeon_handles
|
||||
{
|
||||
int fd;
|
||||
uint32_t version_major, version_minor, gui_percent {0};
|
||||
uint32_t ticks = 60, ticks_per_sec = 120;
|
||||
std::chrono::nanoseconds sleep_interval {};
|
||||
|
||||
bool quit = false;
|
||||
std::thread collector;
|
||||
|
||||
radeon_handles(int fd_, uint32_t major, uint32_t minor)
|
||||
: fd(fd_)
|
||||
, version_major(major)
|
||||
, version_minor(minor)
|
||||
{
|
||||
set_sampling_period(500000000 /* 500ms */);
|
||||
collector = std::thread(&radeon_handles::poll, this);
|
||||
}
|
||||
|
||||
~radeon_handles()
|
||||
{
|
||||
quit = true;
|
||||
if (collector.joinable())
|
||||
collector.join();
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void set_sampling_period(uint32_t period)
|
||||
{
|
||||
if (period < 10000000)
|
||||
period = 10000000; /* 10ms */
|
||||
ticks = ticks_per_sec * std::chrono::nanoseconds(period) / 1s;
|
||||
sleep_interval = std::chrono::nanoseconds(period) / ticks;
|
||||
SPDLOG_DEBUG("ticks: {}, {}ns", ticks, sleep_interval.count());
|
||||
}
|
||||
|
||||
void poll()
|
||||
{
|
||||
uint32_t stat = 0, gui = 0, curr = 0;
|
||||
while (!quit)
|
||||
{
|
||||
stat = GRBM_STATUS;
|
||||
if (get_radeon_drm_value(fd, RADEON_INFO_READ_REG, &stat))
|
||||
{
|
||||
gui_percent = 0;
|
||||
curr = 0;
|
||||
gui = 0;
|
||||
std::this_thread::sleep_for(sleep_interval * ticks);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stat & (1U << 31)) // gui
|
||||
gui++;
|
||||
|
||||
std::this_thread::sleep_for(sleep_interval);
|
||||
curr++;
|
||||
curr %= ticks;
|
||||
if (!curr)
|
||||
{
|
||||
gui_percent = gui * 100 / ticks;
|
||||
gui = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<radeon_handles> radeon_ptr;
|
||||
static radeon_ptr radeon_dev;
|
||||
|
||||
void radeon_set_sampling_period(uint32_t period)
|
||||
{
|
||||
if (radeon_dev)
|
||||
radeon_dev->set_sampling_period(period);
|
||||
}
|
||||
|
||||
bool radeon_open(const char *path)
|
||||
{
|
||||
uint32_t drm_major = 0, drm_minor = 0;
|
||||
|
||||
int fd = open(path, O_RDWR | O_CLOEXEC);
|
||||
|
||||
if (fd < 0) {
|
||||
SPDLOG_ERROR("Failed to open DRM device: {}", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
drmVersionPtr ver = drmGetVersion(fd);
|
||||
|
||||
if (!ver) {
|
||||
SPDLOG_ERROR("Failed to query driver version: {}", strerror(errno));
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcmp(ver->name, "radeon") || !DRM_ATLEAST_VERSION(ver, 2, 42)) {
|
||||
SPDLOG_ERROR("Unsupported driver/version: {} {}.{}.{}",
|
||||
ver->name, ver->version_major, ver->version_minor, ver->version_patchlevel);
|
||||
close(fd);
|
||||
drmFreeVersion(ver);
|
||||
return false;
|
||||
}
|
||||
|
||||
drm_major = ver->version_major;
|
||||
drm_minor = ver->version_minor;
|
||||
drmFreeVersion(ver);
|
||||
|
||||
if (!authenticate_drm(fd)) {
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
radeon_dev = std::make_unique<radeon_handles>(fd, drm_major, drm_minor);
|
||||
return true;
|
||||
}
|
||||
|
||||
void getRadeonInfo_libdrm()
|
||||
{
|
||||
uint64_t value = 0;
|
||||
uint32_t value32 = 0;
|
||||
|
||||
if (!radeon_dev)
|
||||
return;
|
||||
|
||||
gpu_info.load = radeon_dev->gui_percent;
|
||||
|
||||
// TODO one shot?
|
||||
struct drm_radeon_gem_info buffer {};
|
||||
int ret = 0;
|
||||
if (!(ret = ioctl(radeon_dev->fd, DRM_IOCTL_RADEON_GEM_INFO, &buffer)))
|
||||
gpu_info.memoryTotal = buffer.vram_size / (1024.f * 1024.f * 1024.f);
|
||||
else
|
||||
SPDLOG_ERROR("DRM_IOCTL_RADEON_GEM_INFO failed: {}", ret);
|
||||
|
||||
if (!get_radeon_drm_value(radeon_dev->fd, RADEON_INFO_VRAM_USAGE, &value))
|
||||
gpu_info.memoryUsed = value / (1024.f * 1024.f * 1024.f);
|
||||
|
||||
if (!get_radeon_drm_value(radeon_dev->fd, RADEON_INFO_CURRENT_GPU_SCLK, &value32))
|
||||
gpu_info.CoreClock = value32;
|
||||
|
||||
if (!get_radeon_drm_value(radeon_dev->fd, RADEON_INFO_CURRENT_GPU_MCLK, &value32))
|
||||
gpu_info.MemClock = value32;
|
||||
|
||||
if (!get_radeon_drm_value(radeon_dev->fd, RADEON_INFO_CURRENT_GPU_TEMP, &value32))
|
||||
gpu_info.temp = value32 / 1000;
|
||||
|
||||
gpu_info.powerUsage = 0;
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
|
||||
#include "loaders/loader_libdrm.h"
|
||||
#include <iostream>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
// Put these sanity checks here so that they fire at most once
|
||||
// (to avoid cluttering the build output).
|
||||
#if !defined(LIBRARY_LOADER_LIBDRM_H_DLOPEN) && !defined(LIBRARY_LOADER_LIBDRM_H_DT_NEEDED)
|
||||
#error neither LIBRARY_LOADER_LIBDRM_H_DLOPEN nor LIBRARY_LOADER_LIBDRM_H_DT_NEEDED defined
|
||||
#endif
|
||||
#if defined(LIBRARY_LOADER_LIBDRM_H_DLOPEN) && defined(LIBRARY_LOADER_LIBDRM_H_DT_NEEDED)
|
||||
#error both LIBRARY_LOADER_LIBDRM_H_DLOPEN and LIBRARY_LOADER_LIBDRM_H_DT_NEEDED defined
|
||||
#endif
|
||||
|
||||
libdrm_loader::libdrm_loader() : loaded_(false) {
|
||||
Load();
|
||||
}
|
||||
|
||||
libdrm_loader::~libdrm_loader() {
|
||||
CleanUp(loaded_);
|
||||
}
|
||||
|
||||
bool libdrm_loader::Load() {
|
||||
if (loaded_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(LIBRARY_LOADER_LIBDRM_H_DLOPEN)
|
||||
library = dlopen("libdrm.so.2", RTLD_LAZY);
|
||||
if (!library) {
|
||||
SPDLOG_ERROR("Failed to open " MANGOHUD_ARCH " libdrm.so.2: {}", dlerror());
|
||||
return false;
|
||||
}
|
||||
|
||||
drmGetVersion =
|
||||
reinterpret_cast<decltype(this->drmGetVersion)>(
|
||||
dlsym(library, "drmGetVersion"));
|
||||
if (!drmGetVersion) {
|
||||
CleanUp(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
drmFreeVersion =
|
||||
reinterpret_cast<decltype(this->drmFreeVersion)>(
|
||||
dlsym(library, "drmFreeVersion"));
|
||||
if (!drmFreeVersion) {
|
||||
CleanUp(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
drmCommandWriteRead =
|
||||
reinterpret_cast<decltype(this->drmCommandWriteRead)>(
|
||||
dlsym(library, "drmCommandWriteRead"));
|
||||
if (!drmCommandWriteRead) {
|
||||
CleanUp(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(LIBRARY_LOADER_LIBDRM_H_DT_NEEDED)
|
||||
drmGetVersion = &::drmGetVersion;
|
||||
drmFreeVersion = &::drmFreeVersion;
|
||||
drmCommandWriteRead = &::drmCommandWriteRead;
|
||||
#endif
|
||||
|
||||
loaded_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void libdrm_loader::CleanUp(bool unload) {
|
||||
#if defined(LIBRARY_LOADER_LIBDRM_H_DLOPEN)
|
||||
if (unload) {
|
||||
dlclose(library);
|
||||
library = nullptr;
|
||||
}
|
||||
#endif
|
||||
loaded_ = false;
|
||||
drmGetVersion = nullptr;
|
||||
drmFreeVersion = nullptr;
|
||||
drmCommandWriteRead = nullptr;
|
||||
|
||||
}
|
||||
|
||||
libdrm_amdgpu_loader::libdrm_amdgpu_loader() : loaded_(false) {
|
||||
Load();
|
||||
}
|
||||
|
||||
libdrm_amdgpu_loader::~libdrm_amdgpu_loader() {
|
||||
CleanUp(loaded_);
|
||||
}
|
||||
|
||||
bool libdrm_amdgpu_loader::Load() {
|
||||
if (loaded_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(LIBRARY_LOADER_LIBDRM_H_DLOPEN)
|
||||
library = dlopen("libdrm_amdgpu.so.1", RTLD_LAZY);
|
||||
if (!library) {
|
||||
SPDLOG_ERROR("Failed to open " MANGOHUD_ARCH " libdrm_amdgpu.so.1: {}", dlerror());
|
||||
CleanUp(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
amdgpu_device_initialize =
|
||||
reinterpret_cast<decltype(this->amdgpu_device_initialize)>(
|
||||
dlsym(library, "amdgpu_device_initialize"));
|
||||
if (!amdgpu_device_initialize) {
|
||||
CleanUp(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
amdgpu_device_deinitialize =
|
||||
reinterpret_cast<decltype(this->amdgpu_device_deinitialize)>(
|
||||
dlsym(library, "amdgpu_device_deinitialize"));
|
||||
if (!amdgpu_device_deinitialize) {
|
||||
CleanUp(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
amdgpu_query_info =
|
||||
reinterpret_cast<decltype(this->amdgpu_query_info)>(
|
||||
dlsym(library, "amdgpu_query_info"));
|
||||
if (!amdgpu_query_info) {
|
||||
CleanUp(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
amdgpu_query_sensor_info =
|
||||
reinterpret_cast<decltype(this->amdgpu_query_sensor_info)>(
|
||||
dlsym(library, "amdgpu_query_sensor_info"));
|
||||
if (!amdgpu_query_sensor_info) {
|
||||
CleanUp(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
amdgpu_read_mm_registers =
|
||||
reinterpret_cast<decltype(this->amdgpu_read_mm_registers)>(
|
||||
dlsym(library, "amdgpu_read_mm_registers"));
|
||||
if (!amdgpu_read_mm_registers) {
|
||||
CleanUp(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(LIBRARY_LOADER_LIBDRM_H_DT_NEEDED)
|
||||
amdgpu_device_initialize = &::amdgpu_device_initialize;
|
||||
amdgpu_device_deinitialize = &::amdgpu_device_deinitialize;
|
||||
amdgpu_query_info = &::amdgpu_query_info;
|
||||
amdgpu_query_sensor_info = &::amdgpu_query_sensor_info;
|
||||
amdgpu_read_mm_registers = &::amdgpu_read_mm_registers;
|
||||
|
||||
#endif
|
||||
|
||||
loaded_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void libdrm_amdgpu_loader::CleanUp(bool unload) {
|
||||
#if defined(LIBRARY_LOADER_LIBDRM_H_DLOPEN)
|
||||
if (unload) {
|
||||
dlclose(library);
|
||||
library = nullptr;
|
||||
}
|
||||
#endif
|
||||
loaded_ = false;
|
||||
amdgpu_device_initialize = nullptr;
|
||||
amdgpu_device_deinitialize = nullptr;
|
||||
amdgpu_query_info = nullptr;
|
||||
amdgpu_query_sensor_info = nullptr;
|
||||
amdgpu_read_mm_registers = nullptr;
|
||||
|
||||
}
|
||||
|
||||
libdrm_loader g_libdrm;
|
@ -1,82 +0,0 @@
|
||||
|
||||
#ifndef LIBRARY_LOADER_LIBDRM_H
|
||||
#define LIBRARY_LOADER_LIBDRM_H
|
||||
|
||||
#define LIBRARY_LOADER_LIBDRM_H_DLOPEN
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <xf86drm.h>
|
||||
//#include <libdrm/amdgpu_drm.h>
|
||||
//#include <libdrm/amdgpu.h>
|
||||
|
||||
typedef struct amdgpu_device *amdgpu_device_handle;
|
||||
int amdgpu_device_initialize(int fd,
|
||||
uint32_t *major_version,
|
||||
uint32_t *minor_version,
|
||||
amdgpu_device_handle *device_handle);
|
||||
int amdgpu_device_deinitialize(amdgpu_device_handle device_handle);
|
||||
int amdgpu_query_info(amdgpu_device_handle dev, unsigned info_id,
|
||||
unsigned size, void *value);
|
||||
int amdgpu_query_sensor_info(amdgpu_device_handle dev, unsigned sensor_type,
|
||||
unsigned size, void *value);
|
||||
int amdgpu_read_mm_registers(amdgpu_device_handle dev, unsigned dword_offset,
|
||||
unsigned count, uint32_t instance, uint32_t flags,
|
||||
uint32_t *values);
|
||||
|
||||
class libdrm_loader {
|
||||
public:
|
||||
libdrm_loader();
|
||||
~libdrm_loader();
|
||||
|
||||
bool Load();
|
||||
bool IsLoaded() { return loaded_; }
|
||||
|
||||
decltype(&::drmGetVersion) drmGetVersion;
|
||||
decltype(&::drmFreeVersion) drmFreeVersion;
|
||||
decltype(&::drmCommandWriteRead) drmCommandWriteRead;
|
||||
|
||||
private:
|
||||
void CleanUp(bool unload);
|
||||
|
||||
#if defined(LIBRARY_LOADER_LIBDRM_H_DLOPEN)
|
||||
void* library;
|
||||
#endif
|
||||
|
||||
bool loaded_;
|
||||
|
||||
// Disallow copy constructor and assignment operator.
|
||||
libdrm_loader(const libdrm_loader&);
|
||||
void operator=(const libdrm_loader&);
|
||||
};
|
||||
|
||||
class libdrm_amdgpu_loader {
|
||||
public:
|
||||
libdrm_amdgpu_loader();
|
||||
~libdrm_amdgpu_loader();
|
||||
|
||||
bool Load();
|
||||
bool IsLoaded() { return loaded_; }
|
||||
|
||||
decltype(&::amdgpu_device_initialize) amdgpu_device_initialize;
|
||||
decltype(&::amdgpu_device_deinitialize) amdgpu_device_deinitialize;
|
||||
decltype(&::amdgpu_query_info) amdgpu_query_info;
|
||||
decltype(&::amdgpu_query_sensor_info) amdgpu_query_sensor_info;
|
||||
decltype(&::amdgpu_read_mm_registers) amdgpu_read_mm_registers;
|
||||
|
||||
private:
|
||||
void CleanUp(bool unload);
|
||||
|
||||
#if defined(LIBRARY_LOADER_LIBDRM_H_DLOPEN)
|
||||
void* library;
|
||||
#endif
|
||||
|
||||
bool loaded_;
|
||||
|
||||
// Disallow copy constructor and assignment operator.
|
||||
libdrm_amdgpu_loader(const libdrm_amdgpu_loader&);
|
||||
void operator=(const libdrm_amdgpu_loader&);
|
||||
};
|
||||
|
||||
extern libdrm_loader g_libdrm;
|
||||
|
||||
#endif // LIBRARY_LOADER_LIBDRM_H
|
@ -150,14 +150,17 @@ if is_unixy
|
||||
)
|
||||
endif
|
||||
|
||||
# if get_option('with_libdrm_amdgpu').enabled() and dep_libdrm.found() and dep_libdrm_amdgpu.found()
|
||||
if get_option('with_libdrm_amdgpu').enabled() and dep_libdrm.found()
|
||||
pre_args += '-DHAVE_LIBDRM_AMDGPU'
|
||||
#if dep_xcb.found() and dep_xcb_dri2.found()
|
||||
vklayer_files += files(
|
||||
'loaders/loader_libdrm.cpp',
|
||||
)
|
||||
#endif
|
||||
if dep_libdrm.found() and get_option('with_libdrm').enabled()
|
||||
pre_args += '-DHAVE_LIBDRM'
|
||||
vklayer_files += files(
|
||||
'gpu_radeon.cpp',
|
||||
'auth.cpp',
|
||||
)
|
||||
if get_option('with_libdrm_amdgpu').enabled()
|
||||
#if dep_xcb.found() and dep_xcb_dri2.found()
|
||||
pre_args += '-DHAVE_LIBDRM_AMDGPU'
|
||||
#endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -188,7 +191,9 @@ vklayer_mesa_overlay = shared_library(
|
||||
dearimgui_dep,
|
||||
spdlog_dep,
|
||||
dep_libdrm,
|
||||
#dep_libdrm_amdgpu,
|
||||
dep_libdrm_amdgpu,
|
||||
dep_xcb,
|
||||
dep_xcb_dri2,
|
||||
dbus_dep,
|
||||
dep_dl,
|
||||
dep_rt,
|
||||
|
@ -550,46 +550,75 @@ void init_gpu_stats(uint32_t& vendorID, uint32_t target_device_id, overlay_param
|
||||
for (auto& dir : dirs) {
|
||||
path = drm + dir;
|
||||
|
||||
SPDLOG_DEBUG("amdgpu path check: {}/device/vendor", path);
|
||||
SPDLOG_DEBUG("device path check: {}/device/vendor", path);
|
||||
|
||||
string device = read_line(path + "/device/device");
|
||||
deviceID = strtol(device.c_str(), NULL, 16);
|
||||
string line = read_line(path + "/device/vendor");
|
||||
trim(line);
|
||||
if (line != "0x1002" || !file_exists(path + "/device/gpu_busy_percent"))
|
||||
deviceID = strtol(device.c_str(), NULL, 16); // OGL might fail so read from sysfs
|
||||
|
||||
string vendor = read_line(path + "/device/vendor");
|
||||
trim(vendor);
|
||||
if (vendor != "0x1002")
|
||||
continue;
|
||||
|
||||
if (pci_bus_parsed && pci_dev) {
|
||||
string pci_device = read_symlink((path + "/device").c_str());
|
||||
SPDLOG_DEBUG("PCI device symlink: '{}'", pci_device);
|
||||
if (!ends_with(pci_device, pci_dev)) {
|
||||
SPDLOG_DEBUG("skipping GPU, no PCI ID match");
|
||||
SPDLOG_WARN("skipping GPU, PCI ID doesn't match: {}", pci_device);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Don't skip if intel, maybe there's a dgpu
|
||||
else if (vendorID != 0x8086 && target_device_id && target_device_id != deviceID)
|
||||
{
|
||||
SPDLOG_WARN("expected device id {:04X}, got {:04X}, skipping", target_device_id, deviceID);
|
||||
continue;
|
||||
}
|
||||
|
||||
SPDLOG_DEBUG("using amdgpu path: {}", path);
|
||||
string module = get_basename(read_symlink(path + "/device/driver/module"));
|
||||
SPDLOG_DEBUG("using device path: '{}', module: '{}'", path, module);
|
||||
|
||||
#ifdef HAVE_LIBDRM_AMDGPU
|
||||
int idx = -1;
|
||||
//TODO make neater
|
||||
int res = sscanf(path.c_str(), "/sys/class/drm/card%d", &idx);
|
||||
int res = sscanf(path.c_str(), "%*[^0-9]%d", &idx);
|
||||
(void)res;
|
||||
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);
|
||||
if (module == "amdgpu")
|
||||
{
|
||||
#ifdef HAVE_LIBDRM_AMDGPU
|
||||
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);
|
||||
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_WARN("Failed to open device '/dev/dri/card{}' with libdrm, falling back to using hwmon sysfs.", idx);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_LIBDRM
|
||||
else if (module == "radeon")
|
||||
{
|
||||
if (res == 1 && radeon_open(dri_path.c_str())) {
|
||||
vendorID = 0x1002;
|
||||
using_libdrm = true;
|
||||
getAmdGpuInfo_actual = getRadeonInfo_libdrm;
|
||||
radeon_set_sampling_period(params.fps_sampling_period);
|
||||
} else {
|
||||
SPDLOG_WARN("Failed to open device '/dev/dri/card{}' with libdrm.", idx);
|
||||
params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!file_exists(path + "/device/gpu_busy_percent"))
|
||||
continue;
|
||||
|
||||
path += "/device";
|
||||
if (!amdgpu.busy)
|
||||
amdgpu.busy = fopen((path + "/gpu_busy_percent").c_str(), "r");
|
||||
|
Loading…
Reference in New Issue
Block a user