diff --git a/meson.build b/meson.build index 4957fb4..8f4c546 100644 --- a/meson.build +++ b/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() diff --git a/meson_options.txt b/meson_options.txt index 302787c..863eb43 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -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') diff --git a/src/auth.cpp b/src/auth.cpp index 5d0d551..64b094a 100644 --- a/src/auth.cpp +++ b/src/auth.cpp @@ -1,6 +1,7 @@ /* Inspired by radeontop */ +#include #include "auth.h" #include #include @@ -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; diff --git a/src/gpu.cpp b/src/gpu.cpp index ca69b4d..e764685 100644 --- a/src/gpu.cpp +++ b/src/gpu.cpp @@ -18,7 +18,6 @@ #include #include #include -#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_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(); - - 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 diff --git a/src/gpu.h b/src/gpu.h index f60d495..55df774 100644 --- a/src/gpu.h +++ b/src/gpu.h @@ -5,6 +5,10 @@ #include #include +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); diff --git a/src/gpu_radeon.cpp b/src/gpu_radeon.cpp new file mode 100644 index 0000000..4114e3e --- /dev/null +++ b/src/gpu_radeon.cpp @@ -0,0 +1,202 @@ +#include +#include "gpu.h" +#include +#include +#include +#include +#include +#include +#include +#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(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_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(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; +} diff --git a/src/loaders/loader_libdrm.cpp b/src/loaders/loader_libdrm.cpp deleted file mode 100644 index f28525b..0000000 --- a/src/loaders/loader_libdrm.cpp +++ /dev/null @@ -1,177 +0,0 @@ - -#include "loaders/loader_libdrm.h" -#include -#include - -// 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_castdrmGetVersion)>( - dlsym(library, "drmGetVersion")); - if (!drmGetVersion) { - CleanUp(true); - return false; - } - - drmFreeVersion = - reinterpret_castdrmFreeVersion)>( - dlsym(library, "drmFreeVersion")); - if (!drmFreeVersion) { - CleanUp(true); - return false; - } - - drmCommandWriteRead = - reinterpret_castdrmCommandWriteRead)>( - 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_castamdgpu_device_initialize)>( - dlsym(library, "amdgpu_device_initialize")); - if (!amdgpu_device_initialize) { - CleanUp(true); - return false; - } - - amdgpu_device_deinitialize = - reinterpret_castamdgpu_device_deinitialize)>( - dlsym(library, "amdgpu_device_deinitialize")); - if (!amdgpu_device_deinitialize) { - CleanUp(true); - return false; - } - - amdgpu_query_info = - reinterpret_castamdgpu_query_info)>( - dlsym(library, "amdgpu_query_info")); - if (!amdgpu_query_info) { - CleanUp(true); - return false; - } - - amdgpu_query_sensor_info = - reinterpret_castamdgpu_query_sensor_info)>( - dlsym(library, "amdgpu_query_sensor_info")); - if (!amdgpu_query_sensor_info) { - CleanUp(true); - return false; - } - - amdgpu_read_mm_registers = - reinterpret_castamdgpu_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; diff --git a/src/loaders/loader_libdrm.h b/src/loaders/loader_libdrm.h deleted file mode 100644 index 897e571..0000000 --- a/src/loaders/loader_libdrm.h +++ /dev/null @@ -1,82 +0,0 @@ - -#ifndef LIBRARY_LOADER_LIBDRM_H -#define LIBRARY_LOADER_LIBDRM_H - -#define LIBRARY_LOADER_LIBDRM_H_DLOPEN - -#include -#include -//#include -//#include - -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 diff --git a/src/meson.build b/src/meson.build index 46b717d..9d516a0 100644 --- a/src/meson.build +++ b/src/meson.build @@ -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, diff --git a/src/overlay.cpp b/src/overlay.cpp index 9d99ce2..5f86398 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -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); - - 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); + 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_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");