mirror of
https://github.com/Lurkki14/tuxclocker.git
synced 2025-02-25 18:55:24 -06:00
AMD: code for checking available readables
This commit is contained in:
parent
15fa1332f8
commit
9054680f09
@ -31,7 +31,7 @@ struct Enumeration {
|
|||||||
};
|
};
|
||||||
|
|
||||||
using AssignmentArgument = std::variant<int, double, uint>;
|
using AssignmentArgument = std::variant<int, double, uint>;
|
||||||
using ReadableValue = std::variant<int, double>;
|
using ReadableValue = std::variant<int, uint, double>;
|
||||||
using RangeInfo = std::variant<Range<int>, Range<double>>;
|
using RangeInfo = std::variant<Range<int>, Range<double>>;
|
||||||
using AssignableInfo = std::variant<RangeInfo, std::vector<Enumeration>>;
|
using AssignableInfo = std::variant<RangeInfo, std::vector<Enumeration>>;
|
||||||
|
|
||||||
@ -49,6 +49,7 @@ private:
|
|||||||
|
|
||||||
class DynamicReadable {
|
class DynamicReadable {
|
||||||
public:
|
public:
|
||||||
|
DynamicReadable() {}
|
||||||
DynamicReadable(const std::function<std::variant<ReadError, ReadableValue>()> readFunc) {
|
DynamicReadable(const std::function<std::variant<ReadError, ReadableValue>()> readFunc) {
|
||||||
m_readFunc = readFunc;
|
m_readFunc = readFunc;
|
||||||
}
|
}
|
||||||
@ -57,6 +58,7 @@ public:
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::function<std::variant<ReadError, ReadableValue>()> m_readFunc;
|
std::function<std::variant<ReadError, ReadableValue>()> m_readFunc;
|
||||||
|
std::optional<std::string> m_unit;
|
||||||
};
|
};
|
||||||
|
|
||||||
// DeviceNode has a name, and optionally implements one of [Assignable, DynamicReadable]
|
// DeviceNode has a name, and optionally implements one of [Assignable, DynamicReadable]
|
||||||
|
32
src/include/Functional.hpp
Normal file
32
src/include/Functional.hpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
namespace TuxClocker {
|
||||||
|
|
||||||
|
// Creates a function with no arguments from a function that takes some from inputs to the function and the function
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
auto specializeFunction(Args... args, std::function<T(Args...)> func) {
|
||||||
|
return [args = std::make_tuple(std::move(args)...), &func]() {
|
||||||
|
return std::apply([&func](auto ...args) {
|
||||||
|
func(args...);
|
||||||
|
}, std::move(args));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<template<typename> typename List, typename In, typename Out>
|
||||||
|
List<Out> map(List<In> list, std::function<Out(In)> func) {
|
||||||
|
List<Out> retval;
|
||||||
|
std::transform(list.begin(), list.end(), std::back_inserter(retval), func);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename List, typename T>
|
||||||
|
List filter(List list, std::function<bool(T)> func) {
|
||||||
|
List retval;
|
||||||
|
std::copy_if(list.begin(), list.end(), std::back_inserter(retval), func);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
@ -1,3 +1,5 @@
|
|||||||
|
#include <Functional.hpp>
|
||||||
|
#include <patterns.hpp>
|
||||||
#include <Plugin.hpp>
|
#include <Plugin.hpp>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -21,13 +23,14 @@ extern int errno;
|
|||||||
#define DEVICE_FILE_PREFIX DRM_DIR_NAME "/" DRM_RENDER_MINOR_NAME
|
#define DEVICE_FILE_PREFIX DRM_DIR_NAME "/" DRM_RENDER_MINOR_NAME
|
||||||
#define RENDERD_OFFSET 128
|
#define RENDERD_OFFSET 128
|
||||||
|
|
||||||
|
using namespace mpark::patterns;
|
||||||
using namespace TuxClocker::Plugin;
|
using namespace TuxClocker::Plugin;
|
||||||
using namespace TuxClocker::Device;
|
using namespace TuxClocker::Device;
|
||||||
using namespace TuxClocker;
|
using namespace TuxClocker;
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
struct AMDAssignableInfo {
|
struct AMDGPUInfo {
|
||||||
// Thus is Linux only
|
// Thus is Linux only
|
||||||
std::optional<std::string> hwmonPath;
|
std::optional<std::string> hwmonPath;
|
||||||
amdgpu_device_handle devHandle;
|
amdgpu_device_handle devHandle;
|
||||||
@ -42,15 +45,32 @@ public:
|
|||||||
~AMDPlugin();
|
~AMDPlugin();
|
||||||
private:
|
private:
|
||||||
TreeNode<DeviceNode> m_rootNode;
|
TreeNode<DeviceNode> m_rootNode;
|
||||||
std::vector<AMDAssignableInfo> m_assignableInfoVec;
|
std::vector<AMDGPUInfo> m_GPUInfoVec;
|
||||||
|
template <typename T>
|
||||||
|
static std::variant<ReadError, ReadableValue> libdrmRead(amdgpu_device_handle dev,
|
||||||
|
uint query,
|
||||||
|
std::optional<std::function<T(T)>> transformFunc = std::nullopt);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
AMDPlugin::~AMDPlugin() {
|
AMDPlugin::~AMDPlugin() {
|
||||||
for (auto info : m_assignableInfoVec) {
|
for (auto info : m_GPUInfoVec) {
|
||||||
amdgpu_device_deinitialize(info.devHandle);
|
amdgpu_device_deinitialize(info.devHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::variant<ReadError, ReadableValue>AMDPlugin::libdrmRead(amdgpu_device_handle dev,
|
||||||
|
uint query,
|
||||||
|
std::optional<std::function<T(T)>> transformFunc) {
|
||||||
|
T value;
|
||||||
|
auto retval = amdgpu_query_sensor_info(dev, query, sizeof(T), &value);
|
||||||
|
if (retval != 0) return ReadError::UnknownError;
|
||||||
|
|
||||||
|
if (!transformFunc.has_value()) return value;
|
||||||
|
return transformFunc.value()(value);
|
||||||
|
}
|
||||||
|
|
||||||
AMDPlugin::AMDPlugin() {
|
AMDPlugin::AMDPlugin() {
|
||||||
/*Assignable a([](auto arg) {
|
/*Assignable a([](auto arg) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@ -78,9 +98,10 @@ AMDPlugin::AMDPlugin() {
|
|||||||
auto v_ptr = drmGetVersion(fd);
|
auto v_ptr = drmGetVersion(fd);
|
||||||
amdgpu_device_handle dev;
|
amdgpu_device_handle dev;
|
||||||
uint32_t m, n;
|
uint32_t m, n;
|
||||||
|
int devInitRetval;
|
||||||
if (fd > 0 &&
|
if (fd > 0 &&
|
||||||
v_ptr &&
|
v_ptr &&
|
||||||
amdgpu_device_initialize(fd, &m, &n, &dev) == 0 &&
|
(devInitRetval = amdgpu_device_initialize(fd, &m, &n, &dev)) == 0 &&
|
||||||
std::string(v_ptr->name).find(_AMDGPU_NAME) != std::string::npos) {
|
std::string(v_ptr->name).find(_AMDGPU_NAME) != std::string::npos) {
|
||||||
// Device uses amdgpu
|
// Device uses amdgpu
|
||||||
// Find hwmon path if available
|
// Find hwmon path if available
|
||||||
@ -98,11 +119,53 @@ AMDPlugin::AMDPlugin() {
|
|||||||
}
|
}
|
||||||
// This exception is only abnormal to get on Linux
|
// This exception is only abnormal to get on Linux
|
||||||
catch (fs::filesystem_error &e) {}
|
catch (fs::filesystem_error &e) {}
|
||||||
m_assignableInfoVec.push_back(AMDAssignableInfo{hwmonPath, dev});
|
m_GPUInfoVec.push_back(AMDGPUInfo{hwmonPath, dev});
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
if (devInitRetval == 0) amdgpu_device_deinitialize(dev);
|
||||||
close(fd);
|
close(fd);
|
||||||
drmFreeVersion(v_ptr);
|
drmFreeVersion(v_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add nodes with successful queries to device node
|
||||||
|
|
||||||
|
// Data structure for mapping to DynamicReadables
|
||||||
|
struct UnspecializedReadable {
|
||||||
|
std::function<std::variant<ReadError, ReadableValue>(AMDGPUInfo)> func;
|
||||||
|
std::optional<std::string> unit;
|
||||||
|
};
|
||||||
|
|
||||||
|
// List of query functions for DynamicReadables
|
||||||
|
std::vector<UnspecializedReadable> rawNodes = {
|
||||||
|
{
|
||||||
|
[&](AMDGPUInfo info) {
|
||||||
|
return libdrmRead<uint>(info.devHandle,
|
||||||
|
AMDGPU_INFO_SENSOR_GPU_TEMP,
|
||||||
|
std::function<uint(uint)>([](uint val) {return val / 1000;}));
|
||||||
|
},
|
||||||
|
std::nullopt
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto info : m_GPUInfoVec) {
|
||||||
|
auto availableReadables = filter(rawNodes,
|
||||||
|
std::function<bool(UnspecializedReadable)>([info](UnspecializedReadable ur) {
|
||||||
|
auto result = ur.func(info);
|
||||||
|
// Check if this node returns an error or not
|
||||||
|
match(result)(pattern(as<ReadError>(_)) = []{return false;},
|
||||||
|
pattern(_) = []{return true;});
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
auto specializedNodes = map(availableReadables,
|
||||||
|
std::function<DynamicReadable(UnspecializedReadable)>(
|
||||||
|
[info] (UnspecializedReadable ur) {
|
||||||
|
//auto specializedFunc = specializeFunction<std::variant<ReadError,
|
||||||
|
//ReadableValue>, AMDGPUInfo>(info, ur.func);
|
||||||
|
return DynamicReadable([info, ur]() {
|
||||||
|
return ur.func(info);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeNode<DeviceNode> AMDPlugin::deviceRootNode() {
|
TreeNode<DeviceNode> AMDPlugin::deviceRootNode() {
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
libdrm_amdgpu = cppc.find_library('libdrm_amdgpu', required : false)
|
libdrm_amdgpu = cppc.find_library('libdrm_amdgpu', required : false)
|
||||||
libdrm_dep = dependency('libdrm', required : false)
|
libdrm_dep = dependency('libdrm', required : false)
|
||||||
|
|
||||||
|
patterns_inc = include_directories('../include/deps/patterns/include/mpark')
|
||||||
|
|
||||||
if libdrm_dep.found() and libdrm_amdgpu.found()
|
if libdrm_dep.found() and libdrm_amdgpu.found()
|
||||||
shared_library('amd', 'AMD.cpp',
|
shared_library('amd', 'AMD.cpp',
|
||||||
override_options : ['cpp_std=c++17'],
|
override_options : ['cpp_std=c++17'],
|
||||||
include_directories : incdir,
|
include_directories : [incdir, patterns_inc],
|
||||||
dependencies : [libdrm_amdgpu, libdrm_dep],
|
dependencies : [libdrm_amdgpu, libdrm_dep, boost_dep],
|
||||||
install_dir : get_option('libdir') / 'tuxclocker' / 'plugins',
|
install_dir : get_option('libdir') / 'tuxclocker' / 'plugins',
|
||||||
install : true)
|
install : true)
|
||||||
endif
|
endif
|
||||||
|
Loading…
Reference in New Issue
Block a user