mirror of
https://github.com/Lurkki14/tuxclocker.git
synced 2024-07-07 04:02:57 -05: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 ReadableValue = std::variant<int, double>;
|
||||
using ReadableValue = std::variant<int, uint, double>;
|
||||
using RangeInfo = std::variant<Range<int>, Range<double>>;
|
||||
using AssignableInfo = std::variant<RangeInfo, std::vector<Enumeration>>;
|
||||
|
||||
|
@ -49,6 +49,7 @@ private:
|
|||
|
||||
class DynamicReadable {
|
||||
public:
|
||||
DynamicReadable() {}
|
||||
DynamicReadable(const std::function<std::variant<ReadError, ReadableValue>()> readFunc) {
|
||||
m_readFunc = readFunc;
|
||||
}
|
||||
|
@ -57,6 +58,7 @@ public:
|
|||
}
|
||||
private:
|
||||
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]
|
||||
|
|
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 <errno.h>
|
||||
|
@ -21,13 +23,14 @@ extern int errno;
|
|||
#define DEVICE_FILE_PREFIX DRM_DIR_NAME "/" DRM_RENDER_MINOR_NAME
|
||||
#define RENDERD_OFFSET 128
|
||||
|
||||
using namespace mpark::patterns;
|
||||
using namespace TuxClocker::Plugin;
|
||||
using namespace TuxClocker::Device;
|
||||
using namespace TuxClocker;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
struct AMDAssignableInfo {
|
||||
struct AMDGPUInfo {
|
||||
// Thus is Linux only
|
||||
std::optional<std::string> hwmonPath;
|
||||
amdgpu_device_handle devHandle;
|
||||
|
@ -42,15 +45,32 @@ public:
|
|||
~AMDPlugin();
|
||||
private:
|
||||
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() {
|
||||
for (auto info : m_assignableInfoVec) {
|
||||
for (auto info : m_GPUInfoVec) {
|
||||
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() {
|
||||
/*Assignable a([](auto arg) {
|
||||
return std::nullopt;
|
||||
|
@ -78,9 +98,10 @@ AMDPlugin::AMDPlugin() {
|
|||
auto v_ptr = drmGetVersion(fd);
|
||||
amdgpu_device_handle dev;
|
||||
uint32_t m, n;
|
||||
int devInitRetval;
|
||||
if (fd > 0 &&
|
||||
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) {
|
||||
// Device uses amdgpu
|
||||
// Find hwmon path if available
|
||||
|
@ -98,11 +119,53 @@ AMDPlugin::AMDPlugin() {
|
|||
}
|
||||
// This exception is only abnormal to get on Linux
|
||||
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);
|
||||
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() {
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
libdrm_amdgpu = cppc.find_library('libdrm_amdgpu', 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()
|
||||
shared_library('amd', 'AMD.cpp',
|
||||
override_options : ['cpp_std=c++17'],
|
||||
include_directories : incdir,
|
||||
dependencies : [libdrm_amdgpu, libdrm_dep],
|
||||
include_directories : [incdir, patterns_inc],
|
||||
dependencies : [libdrm_amdgpu, libdrm_dep, boost_dep],
|
||||
install_dir : get_option('libdir') / 'tuxclocker' / 'plugins',
|
||||
install : true)
|
||||
endif
|
||||
|
|
Loading…
Reference in New Issue
Block a user