start new branch from scratch

This commit is contained in:
jussi 2019-09-03 16:47:38 +03:00
parent 41a769c674
commit 4411c29aeb
32 changed files with 0 additions and 48372 deletions

View File

@ -1,41 +0,0 @@
TuxClocker - A GUI overclocking utility for GNU/Linux
========================================
TuxClocker is a Qt5 overclocking tool. Currently supported cards are nvidia 600-series cards and newer. Support for AMD GPUs is planned.
# Screenshots
![Imgur](https://i.imgur.com/fn8MoNj.png) ![Imgur](https://i.imgur.com/fuKIVW7.png) ![Imgur](https://i.imgur.com/cZCNzmN.png) ![Imgur](https://i.imgur.com/qkp2p7V.png) ![Imgur](https://i.imgur.com/TpmU8PD.png)
# Current features
- GPU monitoring (list and graph)
- Overclocking
- Overvolting
- Change power limit
- Fan mode selection
- Custom fan curve
- Profiles
# Planned features
- Multi-GPU support
- AMD support
- Rewrite nvidia controlling using libxnvctrl
# Requirements
- nvidia-smi
- nvidia-settings
- Qt libraries
- Coolbits set to the value you want (31 for all functionality)
# Installation
### Compilation
```
git clone https://github.com/Lurkki14/tuxclocker
cd tuxclocker
qmake rojekti.pro
make
make install (installs into /opt/tuxclocker/bin)
```

795
amd.cpp
View File

@ -1,795 +0,0 @@
#ifdef AMD
#include "gputypes.h"
#include <tgmath.h>
#include <string.h>
#include "mainwindow.h"
#include <QThread>
#include <QSettings>
amd::amd() {}
bool amd::setupGPU()
{
bool retb = false;
qDebug("setting up amd gpu");
// Check if the amdgpu driver is present on any of the cards in /dev/dri
QDir devdir("/dev/dri");
QStringList filelist = devdir.entryList();
// First check for /dev/dri/renderD(128 + n)
int fd = 0;
for (int i=0; i<filelist.size(); i++) {
QFileInfo info(devdir, "renderD"+QString::number(128+i));
//qDebug() << info.exists();
if (info.exists()) {
// Get file descriptor for the device
// Convert info.path to char
char *path;
QString abspath = "/dev/dri/renderD"+QString::number(128 + i);
QByteArray arr = abspath.toLocal8Bit();
path = arr.data();
fd = open(path, O_RDONLY);
qDebug() << info.fileName() << fd;
// Attempt to initialize the GPU
uint32_t major = 0;
uint32_t minor = 0;
amdgpu_device_handle *handle = new amdgpu_device_handle;
int ret = amdgpu_device_initialize(fd, &major, &minor, handle);
qDebug() << major;
if (ret == 0) {
// Create a gpu object with the correct paremeters
GPU gpu;
gpu.fsindex = i;
gpu.gputype = Type::AMDGPU;
// Get the hwmon folder name
QString monpath = "/sys/class/drm/card"+QString::number(i)+"/device/hwmon";
QDir mondir(monpath);
qDebug() << mondir.entryList() << "mondir";
QStringList list = mondir.entryList();
for (int i=0; i<list.size(); i++) {
if (list[i].contains("hwmon")) {
qDebug() << list[i];
gpu.hwmonpath = monpath+"/"+list[i];
qDebug() << gpu.hwmonpath;
break;
}
}
const char *name = amdgpu_get_marketing_name(*handle);
char tempname[64];
strcpy(tempname, name);
gpu.name = tempname;
gpu.displayName = QString::fromUtf8(name);
gpu.dev = handle;
qDebug() << gpu.name;
// Get the UUID - vendor id, device id
drmDevicePtr drdev;
drmGetDevice(fd, &drdev);
drmPciDeviceInfo pci_info = *drdev->deviceinfo.pci;
QString pci_id = QString::number(pci_info.vendor_id)+"-"+QString::number(pci_info.device_id);
//QByteArray barr = uuid.toLocal8Bit();
/*char uuid;
char vendor = static_cast<char>(pci_info.vendor_id);
char device = static_cast<char>(pci_info.device_id);
strcat(&uuid, &vendor);
strcat(&uuid, &device);
gpu.uuid = &uuid;*/
gpu.pci_id = pci_id;
qDebug() << "UUID: " << gpu.pci_id;
int reading = 0;
uint size = sizeof (int);
ret = amdgpu_query_sensor_info(*handle, AMDGPU_INFO_SENSOR_GFX_SCLK, size, &reading);
qDebug() << "coreclk" << reading << ret;
GPUList.append(gpu);
//qDebug() << "UUID 2: " << GPUList[0].uuid;
gpuCount++;
retb = true;
}
}
}
if (!retb) {
qDebug("No AMD GPUs using amdgpu found");
} else {
queryGPUTemp(0);
queryGPUPowerLimit(0);
queryGPUFanSpeed(0);
queryGPUPowerLimitLimits(0);
queryGPUFanCtlMode(0);
}
return retb;
}
void amd::calculateUIProperties(int GPUIndex)
{
/*GPUList[GPUIndex].voltageSliderMin = GPUList[GPUIndex].minVoltageLimit;
GPUList[GPUIndex].voltageSliderMax = GPUList[GPUIndex].maxVoltageLimit;
GPUList[GPUIndex].coreClkSliderMin = GPUList[GPUIndex].minCoreClkLimit;
GPUList[GPUIndex].coreClkSliderMax = GPUList[GPUIndex].maxCoreClkLimit;
GPUList[GPUIndex].memClkSliderMin = GPUList[GPUIndex].minMemClkLimit;
GPUList[GPUIndex].memClkSliderMax = GPUList[GPUIndex].maxMemClkLimit;
GPUList[GPUIndex].powerLimSliderMax = static_cast<int>(GPUList[GPUIndex].maxPowerLim);
GPUList[GPUIndex].powerLimSliderMin = static_cast<int>(GPUList[GPUIndex].minPowerLim);
if (GPUList[GPUIndex].overVoltAvailable) {
GPUList[GPUIndex].voltageSliderCur = GPUList[GPUIndex].corevolts[GPUList[GPUIndex].corevolts.size()-1];
}
if (GPUList[GPUIndex].powerLimitAvailable) {
GPUList[GPUIndex].powerLimSliderCur = static_cast<int>(GPUList[GPUIndex].powerLim);
}
if (GPUList[GPUIndex].overClockAvailable) {
GPUList[GPUIndex].memClkSliderCur = GPUList[GPUIndex].memvolts[GPUList[GPUIndex].memclocks.size()-1];
GPUList[GPUIndex].coreClkSliderCur = GPUList[GPUIndex].coreclocks[GPUList[GPUIndex].coreclocks.size()-1];
}*/
if (GPUList[GPUIndex].overVoltAvailable) {
voltageSlider->setEnabled(true);
voltageSpinBox->setEnabled(true);
voltageSlider->setRange(GPUList[GPUIndex].minVoltageLimit, GPUList[GPUIndex].maxVoltageLimit);
voltageSpinBox->setRange(GPUList[GPUIndex].minVoltageLimit, GPUList[GPUIndex].maxVoltageLimit);
voltageSlider->setValue(GPUList[GPUIndex].corevolts.last());
voltageSpinBox->setValue(GPUList[GPUIndex].corevolts.last());
qDebug() << "voltage slider: minimum = " << GPUList[GPUIndex].minVoltageLimit
<< "maximum = " << GPUList[GPUIndex].maxVoltageLimit << "current = " << GPUList[GPUIndex].corevolts.last();
latestVoltageSlider = GPUList[GPUIndex].corevolts.last();
} else {
voltageSlider->setEnabled(false);
voltageSpinBox->setEnabled(false);
}
if (GPUList[GPUIndex].overClockAvailable) {
coreClockSlider->setEnabled(true);
coreClockSpinBox->setEnabled(true);
coreClockSpinBox->setRange(GPUList[GPUIndex].minCoreClkLimit, GPUList[GPUIndex].maxCoreClkLimit);
coreClockSlider->setRange(GPUList[GPUIndex].minCoreClkLimit, GPUList[GPUIndex].maxCoreClkLimit);
coreClockSlider->setValue(GPUList[GPUIndex].coreclocks.last());
coreClockSpinBox->setValue(GPUList[GPUIndex].coreclocks.last());
qDebug() << "core clock slider: minimum = " << GPUList[GPUIndex].minCoreClkLimit
<< "maximum = " << GPUList[GPUIndex].maxCoreClkLimit << "current = " << GPUList[GPUIndex].coreclocks.last();
memClockSlider->setEnabled(true);
memClockSpinBox->setEnabled(true);
memClockSlider->setRange(GPUList[GPUIndex].minMemClkLimit, GPUList[GPUIndex].maxMemClkLimit);
memClockSpinBox->setRange(GPUList[GPUIndex].minMemClkLimit, GPUList[GPUIndex].maxMemClkLimit);
memClockSlider->setValue(GPUList[GPUIndex].memclocks.last());
memClockSpinBox->setValue(GPUList[GPUIndex].memclocks.last());
qDebug() << "mem clock slider: minimum = " << GPUList[GPUIndex].minMemClkLimit
<< "maximum = " << GPUList[GPUIndex].maxMemClkLimit << "current = " << GPUList[GPUIndex].memclocks.last();
latestCoreClkSlider = GPUList[GPUIndex].coreclocks.last();
latestMemClkSlider = GPUList[GPUIndex].memclocks.last();
} else {
coreClockSlider->setEnabled(false);
coreClockSpinBox->setEnabled(false);
memClockSlider->setEnabled(false);
memClockSpinBox->setEnabled(false);
}
if (GPUList[GPUIndex].powerLimitAvailable) {
powerLimSlider->setEnabled(true);
powerLimSpinBox->setEnabled(true);
powerLimSlider->setRange(static_cast<int>(GPUList[GPUIndex].minPowerLim), static_cast<int>(GPUList[GPUIndex].maxPowerLim));
powerLimSpinBox->setRange(static_cast<int>(GPUList[GPUIndex].minPowerLim), static_cast<int>(GPUList[GPUIndex].maxPowerLim));
powerLimSlider->setValue(static_cast<int>(GPUList[GPUIndex].powerLim));
powerLimSpinBox->setValue(static_cast<int>(GPUList[GPUIndex].powerLim));
latestpowerLimSlider = static_cast<int>(GPUList[GPUIndex].powerLim);
} else {
powerLimSlider->setEnabled(false);
powerLimSpinBox->setEnabled(false);
}
latestFanSlider = GPUList[GPUIndex].fanSpeed;
fanSlider->setRange(0, 100);
fanSpinBox->setRange(0, 100);
fanSlider->setValue(GPUList[GPUIndex].fanSpeed);
// Disable the pstate editor button if no pstates were found
if (GPUList[GPUIndex].coreclocks.isEmpty() || GPUList[GPUIndex].memclocks.isEmpty()) {
pstateButton->setDisabled(true);
}
// Change the label names to suit AMD
coreClockLabel->setText("Core Clock (MHz)");
memClockLabel->setText("Memory Clock (MHz)");
voltageLabel->setText("Core Voltage (mV)");
//qDebug() << "setting fan box to" << GPUList[GPUIndex].fanControlMode;
// For some reason it can't set it here, try to do it here for cleanness
//fanModeComboBox->setCurrentIndex(GPUList[GPUIndex].fanControlMode);
}
void amd::calculateDisplayValues(int GPUIndex)
{
GPUList[GPUIndex].displayTemp = GPUList[GPUIndex].temp/1000;
GPUList[GPUIndex].displayPowerDraw = GPUList[GPUIndex].powerDraw;
GPUList[GPUIndex].displayCoreFreq = GPUList[GPUIndex].coreFreq;
GPUList[GPUIndex].displayMemFreq = GPUList[GPUIndex].memFreq;
GPUList[GPUIndex].displayCoreUtil = static_cast <int> (GPUList[GPUIndex].coreUtil);
// Not available on AMD
GPUList[GPUIndex].displayMemUtil = 0;
GPUList[GPUIndex].displayVoltage = GPUList[GPUIndex].voltage;
GPUList[GPUIndex].displayFanSpeed = GPUList[GPUIndex].fanSpeed;
}
QString amd::applySettings(int GPUIndex)
{
currentGPUIndex = GPUIndex;
QSettings settings("tuxclocker");
settings.beginGroup("General");
//settings.setValue("latestUUID", GPUList[GPUIndex].pci_id);
qDebug() << "read uiid " << settings.value("latestUUID").toString();
QString currentProfile = settings.value("currentProfile").toString();
settings.endGroup();
settings.setValue("latestUUID", GPUList[GPUIndex].pci_id);
settings.beginGroup(currentProfile);
settings.beginGroup(GPUList[GPUIndex].pci_id);
QString successStr = "Settings applied";
//QString errStr = "Failed to apply these settings: ";
QString errStr = "Failed to apply settings ";
bool hadChanges = false;
QProcess proc;
QString cmd = "pkexec /bin/sh -c \"";
// To avoid asking for password in pkexec multiple times, apply everything at once and query what succeeded afterwards
int cmdval = 0;
int targetValue = 0;
qDebug() << fanModeComboBox->currentIndex() << GPUList[GPUIndex].fanControlMode << "box index";
// Apply fan settings
// On custom mode, the mode needs to be set again to load the new points
if (fanModeComboBox->currentIndex() == 2 || fanModeComboBox->currentIndex() != GPUList[GPUIndex].fanControlMode) {
hadChanges = true;
switch (fanModeComboBox->currentIndex()) {
case 0:
cmd.append("echo '0' > "+GPUList[GPUIndex].hwmonpath+"/pwm1_enable & ");
// Disconnect fancurve timer
disconnect(fanUpdateTimer, SIGNAL(timeout()), this, SLOT(tempUpdater()));
break;
case 1:
cmd.append("echo '1' > "+GPUList[GPUIndex].hwmonpath+"/pwm1_enable & ");
targetValue = fanSlider->value();
cmdval = static_cast<int>(ceil(targetValue*2.55));
cmd.append("echo '"+QString::number(cmdval)+"' > "+GPUList[GPUIndex].hwmonpath+"/pwm1 & ");
// Disconnect fancurve timer
disconnect(fanUpdateTimer, SIGNAL(timeout()), this, SLOT(tempUpdater()));
break;
case 2:
cmd.append("echo '1' > "+GPUList[GPUIndex].hwmonpath+"/pwm1_enable & ");
// Load the curve points from settings
QSettings settings("tuxclocker");
QString profile = settings.value("currentProfile").toString();
QString UUID = settings.value("latestUUID").toString();
settings.beginGroup(profile);
settings.beginGroup(UUID);
int size = settings.beginReadArray("curvepoints");
// Remove old curve points
yCurvePoints.clear();
xCurvePoints.clear();
for (int i=0; i<size; i++) {
settings.setArrayIndex(i);
xCurvePoints.append(settings.value("xpoints").toInt());
yCurvePoints.append(settings.value("ypoints").toInt());
}
settings.endArray();
disconnect(fanUpdateTimer, SIGNAL(timeout()), this, SLOT(tempUpdater()));
// Activate the fan updater
connect(fanUpdateTimer, SIGNAL(timeout()), this, SLOT(tempUpdater()));
fanUpdateTimer->start(2000);
break;
}
}
// Apply fan speed
if (fanModeComboBox->currentIndex() == 1 && (latestFanSlider != fanSlider->value())) {
hadChanges = true;
int targetValue = fanSlider->value();
cmdval = static_cast<int>(ceil(targetValue*2.55));
cmd.append("echo '"+QString::number(cmdval)+"' > "+GPUList[GPUIndex].hwmonpath+"/pwm1 & ");
}
// Apply power limit
if (GPUList[GPUIndex].powerLimitAvailable) {
if (powerLimSlider->value() != latestpowerLimSlider) {
hadChanges = true;
cmd.append("echo '" + QString::number(powerLimSlider->value() * 1000000) +"' > " + GPUList[GPUIndex].hwmonpath + "/power1_cap & ");
}
}
// Apply voltage/core clock (highest pstate)
if (GPUList[GPUIndex].overClockAvailable) {
if ((coreClockSlider->value() != GPUList[GPUIndex].coreclocks.last()) || (voltageSlider->value() != GPUList[GPUIndex].corevolts.last())) {
hadChanges = true;
QString volt = QString::number(voltageSlider->value());
QString freq = QString::number(coreClockSlider->value());
cmd.append("echo 'm "+ QString::number(GPUList[GPUIndex].corevolts.size()-1) + " "+ freq +" "+ volt +"' "+"> /sys/class/drm/card"+QString::number(GPUList[GPUIndex].fsindex)+"/device/pp_od_clk_voltage & ");
}
}
cmd.append("\"");
qDebug() << "running cmd " << cmd;
if (hadChanges) {
proc.start(cmd);
proc.waitForFinished(-1);
QThread::msleep(200);
} else return "Nothing to apply.";
// If fan mode was changed, check if it was successful
/*if (fanModeComboBox->currentIndex() != GPUList[GPUIndex].fanControlMode) {
queryGPUFanCtlMode(GPUIndex);
qDebug() << "checking combo box" << fanModeComboBox->currentIndex() << GPUList[GPUIndex].fanControlMode;
if (fanModeComboBox->currentIndex() != GPUList[GPUIndex].fanControlMode) {
hadErrors = true;
errStr.append("Fan mode, ");
fanModeComboBox->setCurrentIndex(GPUList[GPUIndex].fanControlMode);
} else {
// Save to settings is applying was successful
settings.setValue("fanControlMode", fanModeComboBox->currentIndex());
}
}
// Fan speed
if (fanModeComboBox->currentIndex() == 1 && (GPUList[GPUIndex].fanSpeed != fanSlider->value())) {
queryGPUFanSpeed(GPUIndex);
qDebug() << "tried to change fan speed to " << cmdval << "speed is " << GPUList[GPUIndex].fanPwm;
if (GPUList[GPUIndex].fanPwm != cmdval) {
hadErrors = true;
errStr.append("Fan speed, ");
} else {
latestFanSlider = fanSlider->value();
}
}
// Power limit
if (powerLimSlider->value() != latestpowerLimSlider) {
queryGPUPowerLimit(GPUIndex);
if (powerLimSlider->value() != static_cast<int>(GPUList[GPUIndex].powerLim)) {
hadErrors = true;
errStr.append("Power Limit, ");
} else {
latestpowerLimSlider = powerLimSlider->value();
settings.setValue("powerLimit", powerLimSlider->value());
}
}
// Core clock/voltage
if (GPUList[GPUIndex].overClockAvailable) {
if ((coreClockSlider->value() != GPUList[GPUIndex].coreclocks.last()) || (voltageSlider->value() != GPUList[GPUIndex].corevolts.last())) {
queryPstates();
if ((coreClockSlider->value() != GPUList[GPUIndex].coreclocks.last()) || (voltageSlider->value() != GPUList[GPUIndex].corevolts.last())) {
hadErrors = true;
errStr.append("Core pstate, ");
} else {
latestVoltageSlider = voltageSlider->value();
latestCoreClkSlider = coreClockSlider->value();
}
}
}*/
if (proc.exitCode() != 0) {
errStr.chop(2);
fanModeComboBox->setCurrentIndex(GPUList[GPUIndex].fanControlMode);
fanSlider->setValue(latestFanSlider);
memClockSlider->setValue(latestMemClkSlider);
coreClockSlider->setValue(latestCoreClkSlider);
voltageSlider->setValue(latestVoltageSlider);
powerLimSlider->setValue(latestpowerLimSlider);
return errStr;
} else {
GPUList[GPUIndex].fanControlMode = fanModeComboBox->currentIndex();
latestFanSlider = fanSlider->value();
latestMemClkSlider = memClockSlider->value();
latestpowerLimSlider = powerLimSlider->value();
latestCoreClkSlider = coreClockSlider->value();
latestVoltageSlider = voltageSlider->value();
return successStr;
}
}
bool amd::setupGPUSecondary(int GPUIndex){return true;}
void amd::queryGPUCount(){}
void amd::queryGPUNames()
{
/*for (int i=0; i<GPUList.size(); i++) {
if (GPUList[i].gputype == Type::AMDGPU) {
const char *name;
name = amdgpu_get_marketing_name(*GPUList[GPUIndex].dev);
//strcpy(GPUList[i].name, name);
qDebug() << name;
}
}*/
}
void amd::queryGPUUIDs(){}
void amd::queryGPUFeatures()
{
// Read the pp_od_clk_voltage file and parse output
QRegularExpression numexp("\\d+\\d");
int type = 0;
int column = 0;
int breakcount = 0;
QString path;
QString line;
queryPstates();
for (int i=0; i<gpuCount; i++) {
if (GPUList[i].gputype == Type::AMDGPU) {
// If the pstate vectors are empty after searching, set the features disabled
if (!GPUList[i].corevolts.isEmpty()) GPUList[i].overVoltAvailable = true;
else GPUList[i].overVoltAvailable = false;
if (!GPUList[i].coreclocks.isEmpty()) {
GPUList[i].overClockAvailable = true;
GPUList[i].memOverClockAvailable = true;
}
// Check if voltage is readable
int reading;
int retval = amdgpu_query_sensor_info(*GPUList[i].dev,
AMDGPU_INFO_SENSOR_VDDGFX,
sizeof (int),
&reading);
if (retval != 0) {
GPUList[i].voltageReadable = false;
qDebug() << "voltage unreadable for GPU" << i;
} else {
GPUList[i].voltageReadable = true;
}
// Core clock
retval = amdgpu_query_sensor_info(*GPUList[i].dev,
AMDGPU_INFO_SENSOR_GFX_SCLK,
sizeof (int),
&reading);
if (retval != 0) {
GPUList[i].coreClkReadable = false;
} else {
GPUList[i].coreClkReadable = true;
}
// Memory clock
retval = amdgpu_query_sensor_info(*GPUList[i].dev,
AMDGPU_INFO_SENSOR_GFX_MCLK,
sizeof (int),
&reading);
if (retval != 0) {
GPUList[i].memClkReadable = false;
} else {
GPUList[i].memClkReadable = true;
}
// GPU Utilization
retval = amdgpu_query_sensor_info(*GPUList[i].dev,
AMDGPU_INFO_SENSOR_GPU_LOAD,
sizeof (int),
&reading);
if (retval != 0) {
GPUList[i].coreUtilReadable= false;
qDebug() << "utilization unreadable for GPU" << i;
} else {
GPUList[i].coreUtilReadable = true;
}
// Power draw
retval = amdgpu_query_sensor_info(*GPUList[i].dev,
AMDGPU_INFO_SENSOR_GPU_AVG_POWER,
sizeof (int),
&reading);
if (retval != 0) {
GPUList[i].powerDrawReadable = false;
} else {
GPUList[i].powerDrawReadable = true;
}
// Check if min/max power limits were readable (does this indicate it's writable though?)
if (GPUList[i].minPowerLim == GPUList[i].maxPowerLim) {
GPUList[i].powerLimitAvailable = false;
} else {
GPUList[i].powerLimitAvailable = true;
}
// Assume manual fan control is always avilable for AMD
GPUList[i].manualFanCtrlAvailable = true;
// Memory utilization isn't available for AMD
GPUList[i].memUtilReadable = false;
// Query the current fan control mode
QFile fanmodefile(GPUList[i].hwmonpath+"/pwm1_enable");
if (fanmodefile.open(QFile::ReadOnly | QFile::Text)) {
QString fanmode = fanmodefile.readLine();
//GPUList[i].fanControlMode = fanmode.toInt();
switch (fanmode.toInt()) {
case 0:
GPUList[i].fanControlMode = 0;
break;
case 1:
GPUList[i].fanControlMode = 1;
break;
case 2:
GPUList[i].fanControlMode = 0;
break;
}
qDebug() << "setting combo box index to" << fanmode.toInt();
//fanModeComboBox->setCurrentIndex(fanmode.toInt());
}
}
}
}
void amd::queryPstates()
{
QString path;
int breakcount = 0;
QString line;
int column = 0;
int type = 0;
QRegularExpression numexp("\\d+\\d");
for (int i=0; i<gpuCount; i++) {
if (GPUList[i].gputype == Type::AMDGPU) {
path = "/sys/class/drm/card"+QString::number(GPUList[i].fsindex)+"/device/pp_od_clk_voltage";
QFile tablefile(path);
bool ret = tablefile.open(QFile::ReadOnly | QFile::Text);
if (ret) {
QTextStream str(&tablefile);
while (!str.atEnd() && breakcount < 30) {
line = str.readLine();
if (line.contains("OD_SCLK")) type = 1;
if (line.contains("OD_MCLK")) type = 2;
if (line.contains("OD_RANGE")) type = 3;
QRegularExpressionMatchIterator iter = numexp.globalMatch(line);
// Read all matches for the line
while (iter.hasNext()) {
QRegularExpressionMatch nummatch = iter.next();
QString capline = nummatch.captured();
int num = capline.toInt();
if (type == 1) {
if (column == 0) {
GPUList[i].coreclocks.append(num);
} else {
GPUList[i].corevolts.append(num);
}
}
if (type == 2) {
if (column == 0) {
GPUList[i].memclocks.append(num);
} else {
GPUList[i].memvolts.append(num);
}
}
if (type == 3) {
if (line.contains("sclk", Qt::CaseInsensitive)) {
if (column == 0) {
GPUList[i].minCoreClkLimit = num;
} else {
GPUList[i].maxCoreClkLimit = num;
}
}
if (line.contains("mclk", Qt::CaseInsensitive)) {
if (column == 0) {
GPUList[i].minMemClkLimit = num;
} else {
GPUList[i].maxMemClkLimit = num;
}
}
if (line.contains("vdd", Qt::CaseInsensitive)) {
if (column == 0) {
GPUList[i].minVoltageLimit = num;
} else {
GPUList[i].maxVoltageLimit = num;
}
}
}
column++;
}
column = 0;
breakcount++;
}
tablefile.close();
}
}
}
}
void amd::queryGPUVoltage(int GPUIndex)
{
int ret = amdgpu_query_sensor_info(*GPUList[GPUIndex].dev,
AMDGPU_INFO_SENSOR_VDDGFX,
sizeof (GPUList[GPUIndex].voltage),
&GPUList[GPUIndex].voltage);
if (ret != 0) qDebug("Failed to query voltage");
}
void amd::queryGPUTemp(int GPUIndex)
{
qDebug() << "querying GPU" << GPUIndex << GPUList[GPUIndex].displayName;
int ret = amdgpu_query_sensor_info(*GPUList[GPUIndex].dev,
AMDGPU_INFO_SENSOR_GPU_TEMP,
sizeof (GPUList[GPUIndex].temp),
&GPUList[GPUIndex].temp);
if (ret != 0) qDebug("Failed to query GPU temperature");
}
void amd::queryGPUFrequencies(int GPUIndex)
{
int reading;
int ret = amdgpu_query_sensor_info(*GPUList[GPUIndex].dev,
AMDGPU_INFO_SENSOR_GFX_SCLK,
sizeof (GPUList[GPUIndex].coreFreq),
&GPUList[GPUIndex].coreFreq);
qDebug() << reading << ret;
if (ret != 0) qDebug("Failed to query GPU core clock");
ret = amdgpu_query_sensor_info(*GPUList[GPUIndex].dev,
AMDGPU_INFO_SENSOR_GFX_MCLK,
sizeof (GPUList[GPUIndex].memFreq),
&GPUList[GPUIndex].memFreq);
if (ret != 0) qDebug("Failed to query GPU memory clock");
}
void amd::queryGPUFanSpeed(int GPUIndex)
{
QFile pwmfile(GPUList[GPUIndex].hwmonpath+"/pwm1");
bool ret = pwmfile.open(QFile::ReadOnly | QFile::Text);
if (ret) {
QString fanspeed = pwmfile.readLine().trimmed();
double percspeed = (fanspeed.toDouble()/2.55);
GPUList[GPUIndex].fanPwm = fanspeed.toInt();
GPUList[GPUIndex].fanSpeed = static_cast<int>(ceil(percspeed));
qDebug() << GPUList[GPUIndex].fanSpeed << "fanspeed";
}
else qDebug("Failed to query fan speed");
}
void amd::queryGPUUsedVRAM(int GPUIndex){}
void amd::queryGPUFreqOffset(int GPUIndex){}
void amd::queryGPUMemClkOffset(int GPUIndex){}
void amd::queryGPUVoltageOffset(int GPUIndex){}
void amd::queryGPUUtils(int GPUIndex)
{
int ret = amdgpu_query_sensor_info(*GPUList[GPUIndex].dev,
AMDGPU_INFO_SENSOR_GPU_LOAD,
sizeof (GPUList[GPUIndex].coreUtil),
&GPUList[GPUIndex].coreUtil);
if (ret != 0) qDebug("Failed to query GPU Utilization");
}
void amd::queryGPUPowerDraw(int GPUIndex)
{
int reading = 0;
int ret = amdgpu_query_sensor_info(*GPUList[GPUIndex].dev,
AMDGPU_INFO_SENSOR_GPU_AVG_POWER,
sizeof (reading),
&reading);
if (ret != 0) qDebug("failed to query GPU power draw");
else {
qDebug() << GPUList[GPUIndex].powerDraw << "power draw";
GPUList[GPUIndex].powerDraw = static_cast<double>(reading);
}
}
void amd::queryGPUPowerLimit(int GPUIndex)
{
QFile pcapfile(GPUList[GPUIndex].hwmonpath+"/power1_cap");
bool ret = pcapfile.open(QFile::ReadOnly | QFile::Text);
if (ret) {
QString pcap = pcapfile.readLine();
GPUList[GPUIndex].powerLim = static_cast<uint>(pcap.toInt()/1000000);
qDebug() << GPUList[GPUIndex].powerLim << "current power limit";
}
else qDebug("Failed to query power limit");
}
void amd::queryGPUPowerLimitLimits(int GPUIndex)
{
QFile maxpcapfile(GPUList[GPUIndex].hwmonpath+"/power1_cap_max");
bool ret = maxpcapfile.open(QFile::ReadOnly | QFile::Text);
if (ret) {
QString maxpcap = maxpcapfile.readLine();
GPUList[GPUIndex].maxPowerLim = static_cast<uint>(maxpcap.toInt()/1000000);
qDebug() << GPUList[GPUIndex].maxPowerLim << "max power limit";
}
QFile mincapfile(GPUList[GPUIndex].hwmonpath+"/power1_cap_min");
ret = mincapfile.open(QFile::ReadOnly | QFile::Text);
if (ret) {
QString minpcap = mincapfile.readLine();
GPUList[GPUIndex].minPowerLim = static_cast<uint>(minpcap.toInt()/1000000);
qDebug() << GPUList[GPUIndex].minPowerLim << "min power limit";
}
}
void amd::queryGPUCurrentMaxClocks(int GPUIndex)
{
/*amdgpu_gpu_info info;
int ret = amdgpu_query_gpu_info(*GPUList[GPUIndex].dev, &info);
if (ret < 0) qDebug("Failed to query GPU maximum clocks");
else {
uint clock = static_cast<uint>(info.max_engine_clk);
GPUList[GPUIndex].maxCoreClk = clock/1000;
clock = static_cast<uint>(info.max_memory_clk);
GPUList[GPUIndex].maxMemClk = clock/1000;
}*/
}
void amd::queryGPUPowerLimitAvailability(int GPUIndex){}
void amd::queryGPUFanCtlMode(int GPUIndex)
{
QFile fanmodefile(GPUList[GPUIndex].hwmonpath+"/pwm1_enable");
if (fanmodefile.open(QFile::ReadOnly | QFile::Text)) {
QString fanmode = fanmodefile.readLine();
//GPUList[GPUIndex].fanControlMode = fanmode.toInt();
//fanModeComboBox->setCurrentIndex(fanmode.toInt());
switch (fanmode.toInt()) {
case 0:
GPUList[GPUIndex].fanControlMode = 0;
break;
case 1:
GPUList[GPUIndex].fanControlMode = 1;
break;
case 2:
GPUList[GPUIndex].fanControlMode = 0;
break;
}
qDebug() << "fan mode is" << fanmode.toInt();
}
else qDebug("Failed to query fan mode");
}
bool amd::assignGPUFanSpeed(int GPUIndex, int targetValue)
{
qDebug() << "assigning fanspeed to" << targetValue;
QProcess proc;
bool ret = false;
int cmdval = static_cast<int>(ceil(targetValue*2.55));
qDebug() << "cmdval: " << cmdval;
proc.start("pkexec /bin/sh -c \"echo '" + QString::number(cmdval) + "' > " + GPUList[GPUIndex].hwmonpath + "/pwm1");
proc.waitForFinished(-1);
if (proc.exitCode() == 0) {
ret = true;
}
return ret;
}
bool amd::assignGPUFanCtlMode(int GPUIndex, bool manual)
{
QProcess proc;
bool ret = false;
if (manual) {
proc.start("pkexec /bin/sh -c \"echo '1' > " + GPUList[GPUIndex].hwmonpath + "/pwm1_enable");
proc.waitForFinished(-1);
if (proc.exitCode() == 0) {
ret = true;
}
} else {
proc.start("pkexec /bin/sh -c \"echo '0' > " + GPUList[GPUIndex].hwmonpath + "/pwm1_enable");
proc.waitForFinished(-1);
if (proc.exitCode() == 0) {
ret = true;
}
}
return ret;
}
bool amd::assignGPUFreqOffset(int GPUIndex, int targetValue){}
bool amd::assignGPUMemClockOffset(int GPUIndex, int targetValue){}
bool amd::assignGPUVoltageOffset(int GPUIndex, int targetValue){}
bool amd::assignGPUPowerLimit(int GPUIndex, uint targetValue)
{
QProcess proc;
proc.start("pkexec /bin/sh -c \"echo '" + QString::number(targetValue) +"' > " + GPUList[GPUIndex].hwmonpath + "/power1_cap");
proc.waitForFinished(-1);
if (proc.exitCode() != 0) {
return true;
}
return false;
}
void amd::tempUpdater() {
queryGPUTemp(currentGPUIndex);
if (!xCurvePoints.isEmpty()) {
int targetFanSpeed = generateFanPoint(GPUList[currentGPUIndex].temp / 1000, xCurvePoints, yCurvePoints);
qDebug() << "fancurve: setting to" << targetFanSpeed << "%";
assignGPUFanSpeed(currentGPUIndex, targetFanSpeed);
}
}
#endif

View File

@ -1,253 +0,0 @@
#include "amdpstateeditor.h"
#include "ui_amdpstateeditor.h"
amdPstateEditor::amdPstateEditor(QWidget *parent) :
QDialog(parent),
ui(new Ui::amdPstateEditor)
{
ui->setupUi(this);
}
amdPstateEditor::~amdPstateEditor()
{
delete ui;
}
void amdPstateEditor::generateUI(gputypes *newtypes, int GPUIndex)
{
types = newtypes;
gpuidx = GPUIndex;
QWidget *lower = new QWidget;
QWidget *upper = new QWidget;
QHBoxLayout *ulo = new QHBoxLayout;
QHBoxLayout *llo = new QHBoxLayout;
for (int i=0; i<newtypes->GPUList[gpuidx].coreclocks.size(); i++) {
corePstate state;
QGridLayout *glo = new QGridLayout;
QLabel *voltlabel = new QLabel;
QLabel *freqlabel = new QLabel;
QLabel *pstatelabel = new QLabel;
voltlabel->setText("mV");
freqlabel->setText("MHz");
pstatelabel->setText("Core pstate "+QString::number(i));
QSlider *freqslider = new QSlider;
QSlider *voltslider = new QSlider;
QSpinBox *freqspinbox = new QSpinBox;
QSpinBox *voltspinbox = new QSpinBox;
connect(freqslider, SIGNAL(valueChanged(int)), freqspinbox, SLOT(setValue(int)));
connect(freqspinbox, SIGNAL(valueChanged(int)), freqslider, SLOT(setValue(int)));
connect(voltspinbox, SIGNAL(valueChanged(int)), voltslider, SLOT(setValue(int)));
connect(voltslider, SIGNAL(valueChanged(int)), voltspinbox, SLOT(setValue(int)));
freqslider->setRange(newtypes->GPUList[gpuidx].minCoreClkLimit, newtypes->GPUList[gpuidx].maxCoreClkLimit);
freqspinbox->setRange(newtypes->GPUList[gpuidx].minCoreClkLimit, newtypes->GPUList[gpuidx].maxCoreClkLimit);
voltslider->setRange(newtypes->GPUList[gpuidx].minVoltageLimit, newtypes->GPUList[gpuidx].maxVoltageLimit);
voltspinbox->setRange(newtypes->GPUList[gpuidx].minVoltageLimit, newtypes->GPUList[gpuidx].maxVoltageLimit);
voltspinbox->setValue(newtypes->GPUList[gpuidx].corevolts[i]);
freqspinbox->setValue(newtypes->GPUList[gpuidx].coreclocks[i]);
glo->addWidget(pstatelabel);
glo->addWidget(freqlabel, 1, 0);
glo->addWidget(voltlabel, 1, 1);
glo->addWidget(freqslider, 2, 0);
glo->addWidget(voltslider, 2, 1);
glo->addWidget(freqspinbox, 3, 0);
glo->addWidget(voltspinbox, 3, 1);
QWidget *freqsliderowdg = new QWidget;
freqsliderowdg->setLayout(glo);
ulo->addWidget(freqsliderowdg);
state.voltspinbox = voltspinbox;
state.freqspinbox = freqspinbox;
corePstates.append(state);
}
for (int i=0; i<newtypes->GPUList[gpuidx].memclocks.size(); i++) {
memPstate state;
QGridLayout *glo = new QGridLayout;
QLabel *voltlabel = new QLabel;
QLabel *freqlabel = new QLabel;
QLabel *pstatelabel = new QLabel;
voltlabel->setText("mV");
freqlabel->setText("MHz");
pstatelabel->setText("Memory pstate "+QString::number(i));
QSlider *freqslider = new QSlider;
QSlider *voltslider = new QSlider;
QSpinBox *freqspinbox = new QSpinBox;
QSpinBox *voltspinbox = new QSpinBox;
connect(freqslider, SIGNAL(valueChanged(int)), freqspinbox, SLOT(setValue(int)));
connect(freqspinbox, SIGNAL(valueChanged(int)), freqslider, SLOT(setValue(int)));
connect(voltspinbox, SIGNAL(valueChanged(int)), voltslider, SLOT(setValue(int)));
connect(voltslider, SIGNAL(valueChanged(int)), voltspinbox, SLOT(setValue(int)));
freqslider->setRange(newtypes->GPUList[gpuidx].minMemClkLimit, newtypes->GPUList[gpuidx].maxMemClkLimit);
freqspinbox->setRange(newtypes->GPUList[gpuidx].minMemClkLimit, newtypes->GPUList[gpuidx].maxMemClkLimit);
voltslider->setRange(newtypes->GPUList[gpuidx].minVoltageLimit, newtypes->GPUList[gpuidx].maxVoltageLimit);
voltspinbox->setRange(newtypes->GPUList[gpuidx].minVoltageLimit, newtypes->GPUList[gpuidx].maxVoltageLimit);
voltspinbox->setValue(newtypes->GPUList[gpuidx].memvolts[i]);
freqspinbox->setValue(newtypes->GPUList[gpuidx].memclocks[i]);
glo->addWidget(pstatelabel);
glo->addWidget(freqlabel, 1, 0);
glo->addWidget(voltlabel, 1, 1);
glo->addWidget(freqslider, 2, 0);
glo->addWidget(voltslider, 2, 1);
glo->addWidget(freqspinbox, 3, 0);
glo->addWidget(voltspinbox, 3, 1);
QWidget *freqsliderowdg = new QWidget;
freqsliderowdg->setLayout(glo);
llo->addWidget(freqsliderowdg);
state.voltspinbox = voltspinbox;
state.freqspinbox = freqspinbox;
memPstates.append(state);
}
// Load the existing changes from settings
QSettings settings("tuxclocker");
QString profile = settings.value("currentProfile").toString();
QString UUID = settings.value("latestUUID").toString();
settings.beginGroup(profile);
settings.beginGroup(UUID);
// Read memory pstates
settings.beginGroup("memPstates");
// Get the indices of pstates
QStringList memPstateIndices = settings.childGroups();
for (int i=0; i<memPstateIndices.size(); i++) {
settings.beginGroup(memPstateIndices[i]);
// Set the appropriate slider values for the pstate
int frequency = settings.value("frequency").toInt();
int voltage = settings.value("voltage").toInt();
memPstates[memPstateIndices[i].toInt() - 1].freqspinbox->setValue(frequency);
memPstates[memPstateIndices[i].toInt() - 1].voltspinbox->setValue(voltage);
settings.endGroup();
}
settings.endGroup();
// Read core pstates
settings.beginGroup("corePstates");
QStringList corePstateIndices = settings.childGroups();
for (int i=0; i<corePstateIndices.size(); i++) {
settings.beginGroup(corePstateIndices[i]);
int frequency = settings.value("frequency").toInt();
int voltage = settings.value("voltage").toInt();
corePstates[corePstateIndices[i].toInt() - 1].freqspinbox->setValue(frequency);
corePstates[corePstateIndices[i].toInt() - 1].voltspinbox->setValue(voltage);
settings.endGroup();
}
settings.endGroup();
QWidget *buttonwidget = new QWidget;
QVBoxLayout *buttonlo = new QVBoxLayout;
// Add an apply button
QPushButton *applyButton = new QPushButton;
connect(applyButton, SIGNAL(clicked()), SLOT(applyValues()));
applyButton->setText("Apply values");
buttonlo->addWidget(applyButton);
// Add a reset button
QPushButton *resetButton = new QPushButton;
connect(resetButton, SIGNAL(clicked()), SLOT(resetPstates()));
resetButton->setText("Reset to defaults");
buttonlo->addWidget(resetButton);
buttonwidget->setLayout(buttonlo);
llo->addWidget(buttonwidget);
QStatusBar *statusbar = new QStatusBar;
statusBar = statusbar;
QWidget *barwdg = new QWidget;
QVBoxLayout *barlo = new QVBoxLayout;
barlo->addWidget(statusbar);
barwdg->setLayout(barlo);
lower->setLayout(llo);
upper->setLayout(ulo);
QVBoxLayout *mainlo = new QVBoxLayout;
mainlo->addWidget(upper);
mainlo->addWidget(lower);
mainlo->addWidget(barwdg);
ui->centralWidget->setLayout(mainlo);
//statusbar->showMessage("test");
}
bool amdPstateEditor::applyValues()
{
qDebug("Applying values");
QProcess proc;
QString volt;
QString freq;
QString cmd = "pkexec /bin/sh -c \"";
// Vector for saving what got applied
QVector <int> changedMemPstates, changedCorePstates;
// Apply core pstates
for (int i=0; i<corePstates.size(); i++) {
if ((corePstates[i].freqspinbox->value() != types->GPUList[gpuidx].coreclocks[i]) || (corePstates[i].voltspinbox->value() != types->GPUList[gpuidx].corevolts[i])) {
changedCorePstates.append(i);
volt = QString::number(corePstates[i].voltspinbox->value());
freq = QString::number(corePstates[i].freqspinbox->value());
cmd.append("echo 's "+ QString::number(i) + " "+ freq +" "+ volt +"' "+"> /sys/class/drm/card"+QString::number(types->GPUList[gpuidx].fsindex)+"/device/pp_od_clk_voltage & ");
qDebug() << cmd;
}
}
// Apply memory pstates
for (int i=0; i<memPstates.size(); i++) {
if ((memPstates[i].freqspinbox->value() != types->GPUList[gpuidx].memclocks[i]) || (memPstates[i].voltspinbox->value() != types->GPUList[gpuidx].memvolts[i])) {
changedMemPstates.append(i);
volt = QString::number(memPstates[i].voltspinbox->value());
freq = QString::number(memPstates[i].freqspinbox->value());
cmd.append("echo 'm "+ QString::number(i) + " "+ freq +" "+ volt +"' "+"> /sys/class/drm/card"+QString::number(types->GPUList[gpuidx].fsindex)+"/device/pp_od_clk_voltage & ");
qDebug() << cmd;
}
}
if (!changedMemPstates.isEmpty() || !changedCorePstates.isEmpty()) {
cmd.append("echo 'c' > /sys/class/drm/card" + QString::number(types->GPUList[gpuidx].fsindex) + "/device/pp_od_clk_voltage\"");
proc.start(cmd);
proc.waitForFinished(-1);
if (proc.exitCode() != 0) {
statusBar->showMessage("Failed to apply changes.");
return false;
}
}
// Save the values if it was successful
QSettings settings("tuxclocker");
QString currentProfile = settings.value("currentProfile").toString();
settings.beginGroup(currentProfile);
settings.beginGroup(types->GPUList[gpuidx].pci_id);
settings.beginWriteArray("memPstates");
for (int i=0; i<changedMemPstates.size(); i++) {
settings.setArrayIndex(changedMemPstates[i]);
types->GPUList[gpuidx].memclocks[changedMemPstates[i]] = memPstates[changedMemPstates[i]].freqspinbox->value();
types->GPUList[gpuidx].memvolts[changedMemPstates[i]] = memPstates[changedMemPstates[i]].voltspinbox->value();
settings.setValue("voltage", memPstates[changedMemPstates[i]].voltspinbox->value());
settings.setValue("frequency", memPstates[changedMemPstates[i]].freqspinbox->value());
}
settings.endArray();
settings.beginWriteArray("corePstates");
for (int i=0; i<changedCorePstates.size(); i++) {
settings.setArrayIndex(changedCorePstates[i]);
types->GPUList[gpuidx].coreclocks[changedCorePstates[i]] = corePstates[changedCorePstates[i]].freqspinbox->value();
types->GPUList[gpuidx].corevolts[changedCorePstates[i]] = corePstates[changedCorePstates[i]].voltspinbox->value();
settings.setValue("voltage", corePstates[changedCorePstates[i]].voltspinbox->value());
settings.setValue("frequency", corePstates[changedCorePstates[i]].freqspinbox->value());
}
settings.endArray();
statusBar->showMessage("Changes applied.");
return true;
}
bool amdPstateEditor::resetPstates()
{
bool ret = false;
QProcess proc;
proc.start("pkexec /bin/sh -c \"echo 'r' > /sys/class/drm/card" + QString::number(types->GPUList[gpuidx].fsindex)+"/device/pp_od_clk_voltage\"");
proc.waitForFinished(-1);
if (proc.exitCode() == 0) {
ret = true;
}
return ret;
}

View File

@ -1,52 +0,0 @@
#ifndef AMDPSTATEEDITOR_H
#define AMDPSTATEEDITOR_H
#include <QDialog>
#include <QWidget>
#include <QSlider>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QSpinBox>
#include <QLabel>
#include <QPushButton>
#include <QProcess>
#include <QStatusBar>
#include <QSettings>
#include "gputypes.h"
namespace Ui {
class amdPstateEditor;
}
class amdPstateEditor : public QDialog
{
Q_OBJECT
public:
explicit amdPstateEditor(QWidget *parent = nullptr);
~amdPstateEditor();
void generateUI(gputypes *newtypes, int GPUIndex);
private:
Ui::amdPstateEditor *ui;
/* These are used for getting the values out of the sliders when applying,
only a slider or spinbox is required, since they are synced */
struct memPstate {
QSpinBox *voltspinbox;
QSpinBox *freqspinbox;
};
struct corePstate {
QSpinBox *voltspinbox;
QSpinBox *freqspinbox;
};
QVector <corePstate> corePstates;
QVector <memPstate> memPstates;
QStatusBar *statusBar;
gputypes *types;
int gpuidx;
private slots:
bool applyValues();
bool resetPstates();
};
#endif // AMDPSTATEEDITOR_H

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>amdPstateEditor</class>
<widget class="QDialog" name="amdPstateEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>617</width>
<height>458</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QWidget" name="centralWidget" native="true"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

BIN
cog.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

View File

@ -1,370 +0,0 @@
#include "editprofile.h"
#include "ui_editprofile.h"
#include "mainwindow.h"
editProfile::editProfile(QWidget *parent, int GPUIndex, gputypes *types) :
QDialog(parent),
ui(new Ui::editProfile)
{
ui->setupUi(this);
GPUId = GPUIndex;
type = types;
// Get the main widget backgorund palette and use the colors for the plots
QPalette palette;
palette.setCurrentColorGroup(QPalette::Active);
QColor color = palette.color(QPalette::Background);
QColor textColor = palette.color(QPalette::Text);
QColor graphColor = palette.color(QPalette::Highlight);
QPen graphPen;
graphPen.setWidth(2);
graphPen.setColor(graphColor);
QPen tickPen;
tickPen.setWidthF(0.5);
tickPen.setColor(textColor);
// Define the filler line vectors and graphs so they don't need to be recreated every update
leftLineX.append(x_lower);
leftLineX.append(0);
leftLineY.append(0);
leftLineY.append(0);
rightLineX.append(0);
rightLineX.append(x_upper);
rightLineY.append(0);
rightLineY.append(0);
ui->curvePlot->addGraph();
ui->curvePlot->addGraph();
ui->curvePlot->addGraph();
ui->curvePlot->graph(0)->setScatterStyle(QCPScatterStyle::ssCircle);
ui->curvePlot->graph(0)->setLineStyle(QCPGraph::lsLine);
ui->curvePlot->setBackground(color);
ui->curvePlot->xAxis->setLabelColor(textColor);
ui->curvePlot->yAxis->setLabelColor(textColor);
ui->curvePlot->xAxis->setTickLabelColor(textColor);
ui->curvePlot->yAxis->setTickLabelColor(textColor);
ui->curvePlot->graph(0)->setPen(graphPen);
ui->curvePlot->graph(1)->setPen(graphPen);
ui->curvePlot->graph(2)->setPen(graphPen);
ui->curvePlot->xAxis->setTickPen(tickPen);
ui->curvePlot->yAxis->setTickPen(tickPen);
ui->curvePlot->xAxis->setSubTickPen(tickPen);
ui->curvePlot->yAxis->setSubTickPen(tickPen);
ui->curvePlot->xAxis->setBasePen(tickPen);
ui->curvePlot->yAxis->setBasePen(tickPen);
ui->curvePlot->xAxis->setLabel("Temperature (°C)");
ui->curvePlot->yAxis->setLabel("Fan speed (%)");
ui->curvePlot->xAxis->setRange(x_lower, (x_upper+5));
ui->curvePlot->yAxis->setRange(y_lower, (y_upper+5));
connect(ui->curvePlot, SIGNAL(mouseDoubleClick(QMouseEvent*)), SLOT(clickedGraph(QMouseEvent*)));
connect(ui->curvePlot, SIGNAL(plottableClick(QCPAbstractPlottable*,int,QMouseEvent*)), SLOT(clickedPoint(QCPAbstractPlottable*,int,QMouseEvent*)));
connect(ui->curvePlot, SIGNAL(mousePress(QMouseEvent*)), SLOT(detectPress(QMouseEvent*)));
connect(ui->curvePlot, SIGNAL(mouseMove(QMouseEvent*)), SLOT(detectMove(QMouseEvent*)));
connect(ui->curvePlot, SIGNAL(mouseRelease(QMouseEvent*)), SLOT(detectRelease(QMouseEvent*)));
connect(ui->curvePlot, SIGNAL(mouseMove(QMouseEvent*)), SLOT(getClosestCoords(QMouseEvent*)));
connect(ui->curvePlot, SIGNAL(mouseMove(QMouseEvent*)), SLOT(drawPointHoveredText(QMouseEvent*)));
// Load the existing points to the graph
/*MainWindow mw;
for (int i=0; i<mw.xCurvePoints.length(); i++) {
qv_x.append(mw.xCurvePoints[i]);
qv_y.append(mw.yCurvePoints[i]);
}*/
QSettings settings("tuxclocker");
QString profile = settings.value("currentProfile").toString();
QString UUID = settings.value("latestUUID").toString();
settings.beginGroup(profile);
settings.beginGroup(UUID);
int size = settings.beginReadArray("curvepoints");
for (int i=0; i<size; i++) {
settings.setArrayIndex(i);
qv_x.append(settings.value("xpoints").toInt());
qv_y.append(settings.value("ypoints").toInt());
}
settings.endArray();
ui->curvePlot->graph(0)->setData(qv_x, qv_y);
drawFillerLines();
QCPItemText *text = new QCPItemText(ui->curvePlot);
coordText = text;
coordText->setColor(textColor);
}
editProfile::~editProfile()
{
delete ui;
}
void editProfile::addPoint(double x, double y)
{
y = round(y);
x = round(x);
if (qv_x.length() != 0) {
checkForDuplicatePoint(x, y);
}
if ((x_lower<=x) && (x<=x_upper) && (y_lower<=y) && (y<=y_upper) && !duplicatePoint) {
qv_x.append(x);
qv_y.append(y);
index_y = qv_y.size()-1;
index_x = qv_x.size()-1;
}
}
void editProfile::rePlot()
{
ui->curvePlot->replot();
ui->curvePlot->update();
}
void editProfile::clickedGraph(QMouseEvent *event)
{
QPoint point = event->pos();
addPoint(ui->curvePlot->xAxis->pixelToCoord(point.x()), ui->curvePlot->yAxis->pixelToCoord(point.y()));
ui->curvePlot->graph(0)->setData(qv_x, qv_y);
drawFillerLines();
}
void editProfile::clickedPoint(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event)
{
checkForNearbyPoints(event);
ycoord = round(ycoord);
xcoord = round(xcoord);
if (isNearbyPoint && qv_x.length() != 0) {
for (int i=0; i<qv_y.length(); i++ ) {
qv_y[i] = round(qv_y[i]);
qv_x[i] = round(qv_x[i]);
if ((qv_x[i] == xcoord) && (qv_y[i] == ycoord)) {
qv_x.remove(i);
qv_y.remove(i);
break;
}
}
ui->curvePlot->graph(0)->setData(qv_x, qv_y);
rePlot();
drawFillerLines();
}
}
bool editProfile::checkForNearbyPoints(QMouseEvent *event)
{
if (qv_x.length() != 0) {
QPoint point = event->pos();
double pointerxcoord = ui->curvePlot->xAxis->pixelToCoord(point.x());
double pointerycoord = ui->curvePlot->yAxis->pixelToCoord(point.y());
for (int i=0; i<qv_x.length(); i++) {
if ((abs(pointerxcoord - qv_x[i]) < selectionPrecision) && abs(pointerycoord - qv_y[i]) < selectionPrecision) {
isNearbyPoint = true;
break;
} else {
isNearbyPoint = false;
}
}
return isNearbyPoint;
}
}
void editProfile::drawPointHoveredText(QMouseEvent *event)
{
checkForNearbyPoints(event);
if (isNearbyPoint && !draggingPoint) {
if (xcoord < x_upper*0.1) {
coordText->position->setCoords(x_upper*0.1, xcoord + 4);
} else if (xcoord > x_upper*0.9) {
coordText->position->setCoords(x_upper*0.9, xcoord + 4);
} else {
coordText->position->setCoords(xcoord, ycoord + 4);
}
coordText->setText(QString::number(xcoord) + ", " + QString::number(ycoord));
rePlot();
}
if (!isNearbyPoint && !draggingPoint) {
coordText->setText("");
rePlot();
}
}
int editProfile::getDataIndex(QCPAbstractPlottable *plottable, int dataIndex)
{
dataIndex = pointIndex;
return pointIndex;
}
bool editProfile::checkForDuplicatePoint(int x, int y)
// Return true if there is a duplicate point
{
for (int i=0; i<qv_x.length(); i++) {
qv_x[i] = round(qv_x[i]);
qv_y[i] = round(qv_y[i]);
if ((x == qv_x[i]) && (y == qv_y[i])) {
duplicatePoint = true;
}
}
return duplicatePoint;
}
void editProfile::getClosestCoords(QMouseEvent *event)
{
// Get the coordinates of the point that the mouse is over
if (qv_y.size() > 0) {
QPoint cursor = event->pos();
double pointerycoord = ui->curvePlot->yAxis->pixelToCoord(cursor.y());
double pointerxcoord = ui->curvePlot->xAxis->pixelToCoord(cursor.x());
for (int i=0; i<qv_y.size(); i++) {
if (sqrt(abs(pointerxcoord - qv_x[i]) * (abs(pointerxcoord - qv_x[i])) + abs(pointerycoord - qv_y[i]) * abs(pointerycoord - qv_y[i])) < selectionPrecision) {
xcoord = qv_x[i];
ycoord = qv_y[i];
break;
}
}
}
getPointIndices();
}
bool editProfile::detectMove(QMouseEvent *event)
{
mouseMoving = true;
if (mouseMoving && mousePressed) {
initializeDragging(event);
}
return mouseMoving;
}
bool editProfile::detectPress(QMouseEvent *event)
{
mousePressed = true;
if (mouseMoving && mousePressed) {
initializeDragging(event);
}
return mousePressed;
}
bool editProfile::initializeDragging(QMouseEvent *event)
{
// Decides whether to start dragging the point
if (!pressTimer->isActive() && !mouseDragging) {
pressTimer->start(20);
pressTimer->setSingleShot(true);
}
mouseDragging = true;
checkForNearbyPoints(event);
if ((isNearbyPoint || draggingPoint) && pressTimer->remainingTime() <= 0) {
dragPoint(index_x, index_y, event);
draggingPoint = true;
}
return mouseDragging;
}
void editProfile::getPointIndices()
{
if (qv_y.size() > 0) {
for (int i=0; i<qv_y.size(); i++) {
if ((qv_x[i] == xcoord) && (qv_y[i] == ycoord)) {
index_x = i;
index_y = i;
break;
}
}
}
}
void editProfile::dragPoint(int index_x, int index_y, QMouseEvent* event)
{
// Moves the selected point by index
// Sleep here so we don't take up so much CPU time
QThread::msleep(10);
QPoint point = event->pos();
qv_y[index_y] = round(ui->curvePlot->yAxis->pixelToCoord(point.y()));
qv_x[index_x] = round(ui->curvePlot->xAxis->pixelToCoord(point.x()));
if (qv_x[index_x] > x_upper) {
qv_x[index_x] = x_upper;
}
if (qv_x[index_x] < x_lower) {
qv_x[index_x] = x_lower;
}
if (qv_y[index_y] > y_upper) {
qv_y[index_y] = y_upper;
}
if (qv_y[index_y] < y_lower) {
qv_y[index_y] = y_lower;
}
// Display the coordinates
if (ui->curvePlot->xAxis->pixelToCoord(point.x()) < x_upper*0.1) {
coordText->position->setCoords(x_upper*0.1, qv_y[index_y] + 4);
} else if (ui->curvePlot->xAxis->pixelToCoord(point.x()) > x_upper*0.9) {
coordText->position->setCoords(x_upper*0.9, qv_y[index_y] + 4);
} else {
coordText->position->setCoords(qv_x[index_x], qv_y[index_y] + 4);
}
QString xString = QString::number(qv_x[index_x]);
QString yString = QString::number(qv_y[index_y]);
coordText->setText(xString + ", " + yString);
ui->curvePlot->graph(0)->setData(qv_x, qv_y);
drawFillerLines();
}
void editProfile::drawFillerLines()
{
// Draw the filler lines separately so they don't interfere with the main data. graph(1) = leftward line, graph(2) = rightward line
leftLineX[1] = ui->curvePlot->graph(0)->dataSortKey(0);
leftLineY[0] = ui->curvePlot->graph(0)->dataMainValue(0);
leftLineY[1] = ui->curvePlot->graph(0)->dataMainValue(0);
ui->curvePlot->graph(1)->setData(leftLineX, leftLineY);
rightLineX[0] = ui->curvePlot->graph(0)->dataSortKey(qv_x.length() -1);
rightLineY[0] = ui->curvePlot->graph(0)->dataMainValue(qv_x.length() -1);
rightLineY[1] = ui->curvePlot->graph(0)->dataMainValue(qv_x.length() -1);
ui->curvePlot->graph(2)->setData(rightLineX, rightLineY);
rePlot();
}
void editProfile::detectRelease(QMouseEvent *event)
{
mousePressed = false;
mouseMoving = false;
mouseDragging = false;
draggingPoint = false;
coordText->setText("");
rePlot();
}
void editProfile::on_saveButton_clicked()
{
QSettings settings("tuxclocker");
QString currentProfile = settings.value("currentProfile").toString();
settings.setValue("latestUUID", type->GPUList[GPUId].pci_id);
settings.beginGroup(currentProfile);
settings.beginGroup(type->GPUList[GPUId].pci_id);
QString xString;
QString yString;
settings.beginWriteArray("curvepoints");
for (int i=0; i<qv_x.length(); i++) {
settings.setArrayIndex(i);
settings.setValue("xpoints", ui->curvePlot->graph(0)->dataSortKey(i));
settings.setValue("ypoints", ui->curvePlot->graph(0)->dataMainValue(i));
}
settings.endArray();
close();
}
void editProfile::on_clearButton_clicked()
{
qv_x.clear();
qv_y.clear();
ui->curvePlot->graph(0)->setData(qv_x, qv_y);
drawFillerLines();
}
void editProfile::on_cancelButton_pressed()
{
close();
}

View File

@ -1,89 +0,0 @@
#ifndef EDITPROFILE_H
#define EDITPROFILE_H
#include <QDialog>
#include <QVector>
#include "qcustomplot.h"
#include "gputypes.h"
#include <QString>
namespace Ui {
class editProfile;
}
class editProfile : public QDialog
{
Q_OBJECT
public:
explicit editProfile(QWidget *parent = nullptr, int GPUIndex = 0, gputypes *types = nullptr);
~editProfile();
QVector<double> qv_x, qv_y;
QVector<int> cpoints_x, cpoints_y;
signals:
void on_clickedPoint(QMouseEvent *event);
void on_dragPoint(bool);
void on_clickedGraph(bool);
private slots:
void clickedGraph(QMouseEvent *event);
void rePlot();
void addPoint(double x, double y);
void clickedPoint(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event);
void on_saveButton_clicked();
bool initializeDragging(QMouseEvent *event);
bool detectMove(QMouseEvent *event);
bool detectPress(QMouseEvent *event);
void detectRelease(QMouseEvent *event);
bool checkForDuplicatePoint(int x, int y);
int getDataIndex(QCPAbstractPlottable *plottable, int dataIndex);
void getClosestCoords(QMouseEvent *event);
void getPointIndices();
bool checkForNearbyPoints(QMouseEvent *event);
void dragPoint(int index_x, int index_y, QMouseEvent *event);
void drawFillerLines();
void on_clearButton_clicked();
void drawPointHoveredText(QMouseEvent *event);
void on_cancelButton_pressed();
private:
Ui::editProfile *ui;
//QVector<double> qv_x, qv_y;
QVector<double> leftLineX;
QVector<double> leftLineY;
QVector<double> rightLineX;
QVector<double> rightLineY;
QVector<int> curvepoints;
QPair<int, int> curvepoint;
QCPItemText *coordText;
int x_lower = 0;
int x_upper = 100;
int y_lower = 0;
int y_upper = 100;
double pixelLength;
double selectionPrecision = 2;
bool mouseMoving = false;
bool mousePressed = false;
bool mouseDragging = false;
bool duplicatePoint = false;
bool isNearbyPoint = false;
bool coordTextCreated = false;
int pointIndex;
int y_length;
int x_length;
int xcoord;
int ycoord;
int index_x = 0;
int index_y = 0;
int GPUId = 0;
gputypes *type;
bool indicesSet = false;
bool draggingPoint = false;
QTimer *pressTimer = new QTimer(this);
int timerTime = 1000;
};
#endif // EDITPROFILE_H

View File

@ -1,69 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>editProfile</class>
<widget class="QDialog" name="editProfile">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>642</width>
<height>557</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>599</width>
<height>523</height>
</size>
</property>
<property name="windowTitle">
<string>Edit fan curve</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="3">
<widget class="QCustomPlot" name="curvePlot" native="true">
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This graph defines the relation of fan speed to the GPU temperature.&lt;/p&gt;&lt;p&gt;To add a point, double click on the area.&lt;/p&gt;&lt;p&gt;To remove a point, click on it.&lt;/p&gt;&lt;p&gt;To move a point, drag it.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="clearButton">
<property name="text">
<string>Clear curve points</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="saveButton">
<property name="maximumSize">
<size>
<width>794</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="cancelButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QCustomPlot</class>
<extends>QWidget</extends>
<header>qcustomplot.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -1,378 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
id="svg8"
version="1.1"
viewBox="0 0 64 64"
height="64"
width="64">
<defs
id="defs2">
<linearGradient
id="linearGradient907">
<stop
style="stop-color:#fdbc4b;stop-opacity:1;"
offset="0"
id="stop903" />
<stop
style="stop-color:#fda815;stop-opacity:1"
offset="1"
id="stop905" />
</linearGradient>
<linearGradient
id="linearGradient889">
<stop
style="stop-color:#232627;stop-opacity:1;"
offset="0"
id="stop885" />
<stop
style="stop-color:#4d4d4d;stop-opacity:1"
offset="1"
id="stop887" />
</linearGradient>
<linearGradient
id="linearGradient881">
<stop
style="stop-color:#bdc3c7;stop-opacity:1;"
offset="0"
id="stop877" />
<stop
style="stop-color:#eff0f1;stop-opacity:1"
offset="1"
id="stop879" />
</linearGradient>
<linearGradient
id="linearGradient1538">
<stop
id="stop1534"
offset="0"
style="stop-color:#f67400;stop-opacity:1;" />
<stop
id="stop1536"
offset="1"
style="stop-color:#fdbc4b;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient1509">
<stop
style="stop-color:#000000;stop-opacity:0.3"
offset="0"
id="stop1505" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop1507" />
</linearGradient>
<linearGradient
id="linearGradient1467">
<stop
style="stop-color:#000000;stop-opacity:0.3"
offset="0"
id="stop1463" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop1465" />
</linearGradient>
<linearGradient
id="linearGradient1461">
<stop
style="stop-color:#000000;stop-opacity:0.3"
offset="0"
id="stop1457" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop1459" />
</linearGradient>
<linearGradient
id="linearGradient1455">
<stop
style="stop-color:#000000;stop-opacity:0.3"
offset="0"
id="stop1451" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop1453" />
</linearGradient>
<linearGradient
id="linearGradient1339">
<stop
id="stop1335"
offset="0"
style="stop-color:#000000;stop-opacity:0.3" />
<stop
id="stop1337"
offset="1"
style="stop-color:#000000;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient1299">
<stop
id="stop1295"
offset="0"
style="stop-color:#232627;stop-opacity:0.2" />
<stop
id="stop1297"
offset="1"
style="stop-color:#232627;stop-opacity:0;" />
</linearGradient>
<linearGradient
gradientUnits="userSpaceOnUse"
y2="44"
x2="32"
y1="28"
x1="16"
id="linearGradient1301"
xlink:href="#linearGradient1299" />
<linearGradient
gradientTransform="translate(3.0075813,288.06681)"
gradientUnits="userSpaceOnUse"
y2="44"
x2="32"
y1="28"
x1="16"
id="linearGradient1341"
xlink:href="#linearGradient1455" />
<linearGradient
gradientTransform="translate(3.0075813,288.06681)"
gradientUnits="userSpaceOnUse"
y2="38"
x2="22"
y1="32"
x1="16"
id="linearGradient1373"
xlink:href="#linearGradient1339" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="38"
x2="22"
y1="32"
x1="16"
id="linearGradient1373-5"
xlink:href="#linearGradient1509"
gradientTransform="translate(32.999403,288.06681)" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="44"
x2="32"
y1="28"
x1="16"
id="linearGradient1341-6"
xlink:href="#linearGradient1461"
gradientTransform="translate(32.999403,288.06681)" />
<linearGradient
gradientTransform="translate(3.9999924,8.0001763)"
gradientUnits="userSpaceOnUse"
y2="322.06668"
x2="56"
y1="300.06668"
x1="34"
id="linearGradient1449"
xlink:href="#linearGradient1467" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="28"
x2="32"
y1="8"
x1="32"
id="linearGradient1540"
xlink:href="#linearGradient1538" />
<linearGradient
xlink:href="#linearGradient881"
id="linearGradient883"
x1="-7.9999924"
y1="332.06693"
x2="-7.9999924"
y2="308.06693"
gradientUnits="userSpaceOnUse" />
<linearGradient
xlink:href="#linearGradient889"
id="linearGradient891"
x1="-29.999992"
y1="332.06693"
x2="-29.999992"
y2="308.06693"
gradientUnits="userSpaceOnUse" />
<linearGradient
xlink:href="#linearGradient907"
id="linearGradient909"
x1="14"
y1="55"
x2="14"
y2="53"
gradientUnits="userSpaceOnUse" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="28"
x2="32"
y1="8"
x1="32"
id="linearGradient1540-3"
xlink:href="#linearGradient1538"
gradientTransform="translate(6.0000002e-8,280.06667)" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="288.71875"
x2="32"
y1="309.71875"
x1="32"
id="linearGradient912"
xlink:href="#linearGradient907" />
</defs>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-280.06667)"
id="layer1">
<rect
transform="scale(-1,1)"
y="308.06693"
x="-59.999992"
height="23.999989"
width="52"
id="rect1181"
style="opacity:1;fill:url(#linearGradient883);fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
transform="scale(-1,1)"
y="307.06693"
x="-7.9999924"
height="27"
width="1"
id="rect1183"
style="opacity:1;fill:#7f8c8d;fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
transform="scale(-1,1)"
y="306.06693"
x="-7.9999924"
height="0.99998909"
width="4"
id="rect1185"
style="opacity:1;fill:#7f8c8d;fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="rect1311"
d="m 25.372815,313.70353 -12.728515,12.72656 5.636719,5.63672 h 25.455078 z"
style="opacity:1;fill:url(#linearGradient1341);fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
transform="rotate(-45)"
ry="9"
y="230.76207"
x="-221.88042"
height="18"
width="18"
id="rect1309"
style="opacity:1;fill:#232627;fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1193"
d="m 13.290485,314.47299 a 8,8 0 0 0 -1.95283,3.33114 c 1.466416,0.87058 4.372572,2.23921 5.667903,2.35886 a 2,2 0 0 0 0.03867,0.31489 c -1.521969,0.14516 -4.442339,-0.17676 -6.036647,-0.32732 a 8,8 0 0 0 0.966748,3.73717 c 1.651541,-0.41983 4.679068,-1.50599 5.680331,-2.33814 a 2,2 0 0 0 0.248591,0.19335 c -0.974582,1.18012 -3.269428,3.02062 -4.50228,4.041 a 8,8 0 0 0 3.331136,1.95283 c 0.870583,-1.46642 2.239215,-4.37257 2.358864,-5.6679 a 2,2 0 0 0 0.314884,-0.0387 c 0.14516,1.52197 -0.176756,4.44234 -0.327314,6.03664 a 8,8 0 0 0 3.737171,-0.96674 c -0.419831,-1.65154 -1.505992,-4.67907 -2.338148,-5.68033 a 2,2 0 0 0 0.193351,-0.2486 c 1.180123,0.97459 3.020626,3.26943 4.041005,4.50229 a 8,8 0 0 0 1.95283,-3.33114 c -1.466416,-0.87058 -4.372572,-2.23921 -5.667904,-2.35886 a 2,2 0 0 0 -0.03867,-0.31489 c 1.52197,-0.14516 4.44234,0.17676 6.036648,0.32732 a 8,8 0 0 0 -0.966748,-3.73717 c -1.651542,0.41983 -4.679069,1.50599 -5.680332,2.33814 a 2,2 0 0 0 -0.24859,-0.19335 c 0.974584,-1.18012 3.269429,-3.02062 4.502281,-4.041 A 8,8 0 0 0 21.2703,312.40965 c -0.870584,1.46641 -2.239216,4.37257 -2.358864,5.6679 a 2,2 0 0 0 -0.314884,0.0387 c -0.14516,-1.52197 0.176756,-4.44234 0.327313,-6.03665 a 8,8 0 0 0 -3.73717,0.96675 c 0.419831,1.65154 1.505992,4.67907 2.338148,5.68033 a 2,2 0 0 0 -0.193351,0.24859 c -1.180123,-0.97458 -3.020626,-3.26943 -4.041005,-4.50228 z"
style="opacity:1;fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="rect1309-5"
d="m 20.421643,318.65275 -2.828124,2.82812 6.203124,6.20313 c 0.523262,-0.32873 1.010254,-0.70649 1.453126,-1.13282 l 0.242187,-0.24218 c 0.426325,-0.44287 0.804082,-0.92987 1.132813,-1.45313 z"
style="opacity:1;fill:url(#linearGradient1373);fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
transform="rotate(-45)"
r="2"
cy="239.76183"
cx="-212.88103"
id="path1305"
style="opacity:1;fill:#7f8c8d;fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1441"
d="m 37.999992,308.06684 22,22 v 2 h -22 z"
style="fill:url(#linearGradient1449);fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="rect1311-5"
d="m 55.365234,313.70353 -12.728515,12.72656 5.636719,5.63672 H 60 v -13.72852 z"
style="opacity:1;fill:url(#linearGradient1341-6);fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
transform="rotate(-90)"
ry="9"
y="40"
x="-329.06668"
height="18"
width="18"
id="rect1309-6"
style="opacity:1;fill:#232627;fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1193-9"
d="m 43.282307,314.47299 a 8,8 0 0 0 -1.952831,3.33114 c 1.466417,0.87058 4.372573,2.23921 5.667904,2.35886 a 2,2 0 0 0 0.03867,0.31489 c -1.521969,0.14516 -4.442339,-0.17676 -6.036647,-0.32732 a 8,8 0 0 0 0.966747,3.73717 c 1.651542,-0.41983 4.679069,-1.50599 5.680332,-2.33814 a 2,2 0 0 0 0.248591,0.19335 c -0.974582,1.18012 -3.269428,3.02062 -4.50228,4.041 a 8,8 0 0 0 3.331136,1.95283 c 0.870583,-1.46642 2.239215,-4.37257 2.358864,-5.6679 a 2,2 0 0 0 0.314884,-0.0387 c 0.14516,1.52197 -0.176756,4.44234 -0.327314,6.03664 a 8,8 0 0 0 3.737171,-0.96674 c -0.419831,-1.65154 -1.505992,-4.67907 -2.338148,-5.68033 a 2,2 0 0 0 0.193351,-0.2486 c 1.180123,0.97459 3.020626,3.26943 4.041005,4.50229 a 8,8 0 0 0 1.95283,-3.33114 c -1.466416,-0.87058 -4.372572,-2.23921 -5.667904,-2.35886 a 2,2 0 0 0 -0.03867,-0.31489 c 1.52197,-0.14516 4.44234,0.17676 6.036648,0.32732 a 8,8 0 0 0 -0.966748,-3.73717 c -1.651542,0.41983 -4.679069,1.50599 -5.680332,2.33814 a 2,2 0 0 0 -0.24859,-0.19335 c 0.974584,-1.18012 3.269429,-3.02062 4.502281,-4.041 a 8,8 0 0 0 -3.331135,-1.95283 c -0.870584,1.46641 -2.239216,4.37257 -2.358864,5.6679 a 2,2 0 0 0 -0.314884,0.0387 c -0.14516,-1.52197 0.176756,-4.44234 0.327313,-6.03665 a 8,8 0 0 0 -3.73717,0.96675 c 0.419831,1.65154 1.505992,4.67907 2.338148,5.68033 a 2,2 0 0 0 -0.193351,0.24859 c -1.180123,-0.97458 -3.020626,-3.26943 -4.041005,-4.50228 z"
style="opacity:1;fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="rect1309-5-3"
d="m 50.413465,318.65275 -2.828124,2.82812 6.203124,6.20313 c 0.523262,-0.32874 1.010254,-0.70649 1.453126,-1.13282 l 0.242187,-0.24218 c 0.426325,-0.44288 0.804082,-0.92987 1.132813,-1.45313 z"
style="opacity:1;fill:url(#linearGradient1373-5);fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
transform="rotate(-45)"
r="2"
cy="260.96924"
cx="-191.67363"
id="path1305-7"
style="opacity:1;fill:#7f8c8d;fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
transform="scale(-1,1)"
y="308.06693"
x="-37.999992"
height="23.999989"
width="8"
id="rect1439"
style="opacity:1;fill:url(#linearGradient891);fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="opacity:1;fill:#27ae60;fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 11 52 L 11 54 L 12 54 L 12 52 L 11 52 z M 13 52 L 13 55 L 30 55 L 30 53 L 31 53 L 31 55 L 34 55 L 36 55 L 36 54 L 34 54 L 34 52 L 31 52 L 30 52 L 13 52 z "
id="rect1469"
transform="translate(0,280.06667)" />
<path
style="opacity:1;fill:url(#linearGradient909);fill-opacity:1;stroke:none;stroke-width:0.00565685;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 14 53 L 14 55 L 15 55 L 15 53 L 14 53 z M 16 53 L 16 55 L 17 55 L 17 53 L 16 53 z M 18 53 L 18 55 L 19 55 L 19 53 L 18 53 z M 20 53 L 20 55 L 21 55 L 21 53 L 20 53 z M 22 53 L 22 55 L 23 55 L 23 53 L 22 53 z M 24 53 L 24 55 L 25 55 L 25 53 L 24 53 z M 26 53 L 26 55 L 27 55 L 27 53 L 26 53 z M 28 53 L 28 55 L 29 55 L 29 53 L 28 53 z M 32 53 L 32 55 L 33 55 L 33 53 L 32 53 z "
transform="translate(0,280.06667)"
id="rect1475" />
<rect
y="312.06693"
x="5.9999924"
height="4"
width="1"
id="rect1499"
style="opacity:1;fill:#2980b9;fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
y="320.06693"
x="5.9999924"
height="3"
width="1"
id="rect1501"
style="opacity:1;fill:#bdc3c7;fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
y="325.06693"
x="5.9999924"
height="3"
width="1"
id="rect1503"
style="opacity:1;fill:#bdc3c7;fill-opacity:1;stroke:none;stroke-width:0.004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path1526"
transform="translate(0,280.06667)"
d="M 31 5 C 30.000003 5 25 8 25 14 C 25 19 30.000003 21 28 27 C 28.000003 25 23.99962 21.999118 21.96875 19.929688 C 20.99962 18.999118 21 15 22 14 C 21 14 19 17 19 19 C 19 24 22 25 22 28 L 40 28 C 40.000003 20 35 18 33 16 C 31 14 29.000003 7 31 5 z M 38 15 C 41 18 43 26 41 28 L 46 28 C 46 22 40 15 38 15 z M 16 25 C 17 26 18 27 18 28 L 20 28 C 20 27 17 25 16 25 z "
style="fill:url(#linearGradient1540);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />
<path
transform="translate(0,1.34792)"
d="m 28.910156,287.98242 c -0.10178,0.10058 -0.190288,0.13426 -0.291015,0.24414 -1.196255,1.30501 -2.271485,3.21431 -2.271485,5.83985 0,2.05064 1.036188,3.51096 2.091797,5.49023 0.969792,1.81836 1.738508,4.18694 1,7.16211 h 9.009766 c -0.540278,-6.05203 -4.110497,-7.40737 -6.402344,-9.69922 -1.397175,-1.39717 -2.321997,-3.72437 -2.863281,-6.16015 -0.216427,-0.97392 -0.265468,-1.9344 -0.273438,-2.87696 z m -8.455078,11.82813 c 0.135356,1.67821 0.590714,2.79507 1.201172,3.8125 0.518823,0.8647 1.061056,1.89315 1.380859,3.0957 h 3.451172 c -0.0573,-0.1621 -0.05674,-0.25474 -0.257812,-0.54883 -0.328554,-0.48053 -0.843482,-1.06379 -1.439453,-1.66211 -1.182453,-1.18712 -2.661151,-2.4278 -3.75586,-3.53906 l -0.002,-0.004 c -0.367802,-0.35435 -0.436236,-0.7613 -0.578125,-1.15429 z m 22.285156,2.29883 c 0.26106,1.2328 0.452351,2.45725 0.404297,3.5625 -0.01578,0.36304 -0.103965,0.69939 -0.162109,1.04687 h 1.375 c -0.243319,-1.55045 -0.795454,-3.08793 -1.617188,-4.60937 z"
id="path1526-5"
style="fill:url(#linearGradient912);fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,32 +0,0 @@
#include "gputypes.h"
gputypes::gputypes()
{}
gputypes::~gputypes()
{}
int gputypes::generateFanPoint(int temp, QVector <int> xPoints, QVector <int> yPoints) {
// Calculate the value for fan speed based on temperature
// First check if the fan speed should be y[0] or y[final]
qDebug("temp: %d", temp);
int index = 0;
if (temp <= xPoints[0]) {
qDebug("ret first point");
return yPoints[0];
} else if (temp >= xPoints.last()) {
qDebug("ret last point %d", xPoints.last());
return yPoints.last();
} else {
// Get the index of the leftmost point of the interpolated interval by comparing it to temperature
for (int i=0; i<xPoints.size(); i++) {
if (temp >= xPoints[i] && temp <= xPoints[i+1]) {
index = i;
break;
}
}
// Check if the change in x is zero to avoid dividing by it
if (xPoints[index] - xPoints[index + 1] == 0) {
return yPoints[index + 1];
} else return (((yPoints[index + 1] - yPoints[index]) * (temp - xPoints[index])) / (xPoints[index + 1] - xPoints[index])) + yPoints[index];
}
}

View File

@ -1,311 +0,0 @@
#ifndef GPUTYPES_H
#define GPUTYPES_H
#include <QObject>
#include <QVector>
#include <QDebug>
#include <QDir>
#include <QtX11Extras/QX11Info>
#include <QProcess>
#include <QSlider>
#include <QSpinBox>
#include <QLabel>
#include <QComboBox>
#include <QPushButton>
#ifdef NVIDIA
#include "nvml.h"
#endif
#ifdef AMD
#include <sys/ioctl.h>
#include <fcntl.h>
#include <libdrm/amdgpu_drm.h>
#include <libdrm/amdgpu.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <QRegularExpressionMatchIterator>
#endif
class gputypes : public QObject
{
Q_OBJECT
public:
gputypes();
enum Type{NV, AMDGPU};
struct GPU
{
// UI variables
int powerLimSliderMin;
int powerLimSliderMax;
int memClkSliderMin;
int memClkSliderMax;
int coreClkSliderMin;
int coreClkSliderMax;
int voltageSliderMax;
int voltageSliderMin;
int voltageSliderCur;
int powerLimSliderCur;
int memClkSliderCur;
int coreClkSliderCur;
QString displayName;
double displayTemp;
double displayPowerDraw;
double displayCoreFreq;
double displayMemFreq;
double displayCoreUtil;
double displayMemUtil;
double displayVoltage;
double displayFanSpeed;
int gputype;
char *name;
char *uuid;
bool overVoltAvailable = false;
bool overClockAvailable = false;
bool memOverClockAvailable = false;
bool powerLimitAvailable = false;
QString pci_id;
bool voltageReadable = false;
bool coreClkReadable = false;
bool memClkReadable = false;
bool powerDrawReadable = false;
bool coreUtilReadable = false;
bool memUtilReadable = false;
bool manualFanCtrlAvailable = false;
int fanControlMode;
int maxVoltageOffset;
int minVoltageOffset;
int minCoreClkOffset;
int maxCoreClkOffset;
int minMemClkOffset;
int maxMemClkOffset;
uint maxCoreClk;
uint maxMemClk;
int voltageOffset;
int coreClkOffset;
int memClkOffset;
int coreFreq;
int memFreq;
int temp;
int voltage;
int fanSpeed;
int fanPwm;
double powerDraw;
uint coreUtil;
uint memUtil;
uint minPowerLim;
uint maxPowerLim;
uint powerLim;
int totalVRAM;
int usedVRAM;
#ifdef AMD
// AMD only:
// GPU index in the filesystem eg. 0 in card0
int fsindex;
// name of the folder in /sys/class/drm/card(n)/device/hwmon
QString hwmonpath;
amdgpu_device_handle *dev;
// Pstate vectors
QVector <int> memvolts, corevolts, memclocks, coreclocks;
int maxVoltageLimit;
int minVoltageLimit;
int maxCoreClkLimit;
int minCoreClkLimit;
int maxMemClkLimit;
int minMemClkLimit;
#endif
};
QVector <GPU> GPUList;
int gpuCount = 0;
// Pointers for modifying the ui main view
QSlider *voltageSlider;
QSlider *coreClockSlider;
QSlider *fanSlider;
QSlider *memClockSlider;
QSlider *powerLimSlider;
QSlider *memVoltageSlider;
QSpinBox *voltageSpinBox;
QSpinBox *coreClockSpinBox;
QSpinBox *fanSpinBox;
QSpinBox *memClockSpinBox;
QSpinBox *powerLimSpinBox;
QSpinBox *memVoltageSpinBox;
QLabel *voltageLabel;
QLabel *coreClockLabel;
QLabel *fanLabel;
QLabel *memClockLabel;
QLabel *powerLimLabel;
QLabel *memVoltageLabel;
QComboBox *fanModeComboBox;
QPushButton *pstateButton;
QTimer *fanUpdateTimer;
// Variables to check if a slider has been changed
int latestFanSlider;
int latestVoltageSlider;
int latestMemClkSlider;
int latestpowerLimSlider;
int latestCoreClkSlider;
int latestMemVoltageSlider;
// Fancurve vectors
QVector <int> xCurvePoints, yCurvePoints;
// Latest GPU index for the fancurve
int currentGPUIndex;
#ifdef NVIDIA
Display *dpy;
nvmlDevice_t *device;
#endif
virtual void calculateUIProperties(int GPUIndex) = 0;
virtual void calculateDisplayValues(int GPUIndex) = 0;
virtual QString applySettings(int GPUIndex) = 0;
virtual bool setupGPU() = 0;
virtual bool setupGPUSecondary(int GPUIndex) = 0;
virtual void queryGPUCount() = 0;
virtual void queryGPUNames() = 0;
virtual void queryGPUUIDs() = 0;
virtual void queryGPUFeatures() = 0;
virtual void queryGPUVoltage(int GPUIndex) = 0;
virtual void queryGPUTemp(int GPUIndex) = 0;
virtual void queryGPUFrequencies(int GPUIndex) = 0;
virtual void queryGPUFanSpeed(int GPUIndex) = 0;
virtual void queryGPUUsedVRAM(int GPUIndex) = 0;
virtual void queryGPUFreqOffset(int GPUIndex) = 0;
virtual void queryGPUMemClkOffset(int GPUIndex) = 0;
virtual void queryGPUVoltageOffset(int GPUIndex) = 0;
virtual void queryGPUUtils(int GPUIndex) = 0;
virtual void queryGPUPowerDraw(int GPUIndex) = 0;
virtual void queryGPUPowerLimit(int GPUIndex) = 0;
virtual void queryGPUPowerLimitLimits(int GPUIndex) = 0;
virtual void queryGPUCurrentMaxClocks(int GPUIndex) = 0;
virtual void queryGPUPowerLimitAvailability(int GPUIndex) = 0;
virtual void queryGPUFanCtlMode(int GPUIndex) = 0;
virtual bool assignGPUFanSpeed(int GPUIndex, int targetValue) = 0;
virtual bool assignGPUFanCtlMode(int GPUIndex, bool targetStatus) = 0;
virtual bool assignGPUFreqOffset(int GPUIndex, int targetValue) = 0;
virtual bool assignGPUMemClockOffset(int GPUIndex, int targetValue) = 0;
virtual bool assignGPUVoltageOffset(int GPUIndex, int targetValue) = 0;
virtual bool assignGPUPowerLimit(int GPUIndex, uint targetValue) = 0;
virtual void tempUpdater() = 0;
// Return the desired fan percentage
int generateFanPoint(int temp, QVector <int> xPoints, QVector <int> yPoints);
protected:
~gputypes();
private:
};
#ifdef NVIDIA
class nvidia : public gputypes
{
Q_OBJECT
public:
nvidia();
signals:
public slots:
void calculateUIProperties();
void calculateDisplayValues(int GPUIndex) = 0;
QString applySettings(int GPUIndex);
bool setupGPU();
bool setupGPUSecondary(int GPUIndex);
void queryGPUCount();
void queryGPUNames();
void queryGPUUIDs();
void queryGPUFeatures();
void queryGPUVoltage(int GPUIndex);
void queryGPUTemp(int GPUIndex);
void queryGPUFrequencies(int GPUIndex);
void queryGPUFanSpeed(int GPUIndex);
void queryGPUUsedVRAM(int GPUIndex);
void queryGPUFreqOffset(int GPUIndex);
void queryGPUMemClkOffset(int GPUIndex);
void queryGPUVoltageOffset(int GPUIndex);
void queryGPUUtils(int GPUIndex);
void queryGPUPowerDraw(int GPUIndex);
void queryGPUPowerLimit(int GPUIndex);
void queryGPUPowerLimitLimits(int GPUIndex);
void queryGPUCurrentMaxClocks(int GPUIndex);
void queryGPUPowerLimitAvailability(int GPUIndex);
void queryGPUFanCtlMode(int GPUIndex) = 0;
bool assignGPUFanSpeed(int GPUIndex, int targetValue);
bool assignGPUFanCtlMode(int GPUIndex, bool manual);
bool assignGPUFreqOffset(int GPUIndex, int targetValue);
bool assignGPUMemClockOffset(int GPUIndex, int targetValue);
bool assignGPUVoltageOffset(int GPUIndex, int targetValue);
// NVML functions know the GPU index already based on the dev object passed in setupNVML()
bool assignGPUPowerLimit(uint targetValue);
void tempUpdater();
private slots:
};
#endif
#ifdef AMD
class amd : public gputypes
{
Q_OBJECT
public:
amd();
signals:
public slots:
void calculateUIProperties(int GPUIndex);
void calculateDisplayValues(int GPUIndex);
QString applySettings(int GPUIndex);
bool setupGPU();
bool setupGPUSecondary(int GPUIndex);
void queryGPUCount();
void queryGPUNames();
void queryGPUUIDs();
void queryGPUFeatures();
void queryGPUVoltage(int GPUIndex);
void queryGPUTemp(int GPUIndex);
void queryGPUFrequencies(int GPUIndex);
void queryGPUFanSpeed(int GPUIndex);
void queryGPUUsedVRAM(int GPUIndex);
void queryGPUFreqOffset(int GPUIndex);
void queryGPUMemClkOffset(int GPUIndex);
void queryGPUVoltageOffset(int GPUIndex);
void queryGPUUtils(int GPUIndex);
void queryGPUPowerDraw(int GPUIndex);
void queryGPUPowerLimit(int GPUIndex);
void queryGPUPowerLimitLimits(int GPUIndex);
void queryGPUCurrentMaxClocks(int GPUIndex);
void queryGPUPowerLimitAvailability(int GPUIndex);
void queryGPUFanCtlMode(int GPUIndex);
bool assignGPUFanSpeed(int GPUIndex, int targetValue);
bool assignGPUFanCtlMode(int GPUIndex, bool manual);
bool assignGPUFreqOffset(int GPUIndex, int targetValue);
bool assignGPUMemClockOffset(int GPUIndex, int targetValue);
bool assignGPUVoltageOffset(int GPUIndex, int targetValue);
bool assignGPUPowerLimit(int GPUIndex, uint targetValue);
void queryPstates();
void tempUpdater();
private slots:
};
#endif
#endif // GPUTYPES_H

View File

@ -1,11 +0,0 @@
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,241 +0,0 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "editprofile.h"
#include "newprofile.h"
#include <QProcess>
#include <QList>
#include <QByteArray>
#include "gputypes.h"
#include "plotwidget.h"
#ifdef AMD
#include "amdpstateeditor.h"
#endif
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
QString currentProfile;
QString nvFanQ = "/bin/sh -c \"nvidia-smi --query-gpu=fan.speed --format=csv | egrep -o '[0-9]{1,4}'\"";
QString nvVoltQ = "nvidia-settings -q GPUCurrentCoreVoltage -t";
QString nvVoltOfsQ = "nvidia-settings -q GPUOverVoltageOffset -t";
QString nvVoltOfsLimQ = "/bin/sh -c \"nvidia-settings -a GPUOverVoltageOffset=99999999 | egrep -o '[0-9]{1,9}'\"";
QString nvCoreClkOfsQ = "nvidia-settings -q GPUGraphicsClockOffset[3] -t";
QString nvCurMaxClkQ = "/bin/sh -c \"nvidia-smi --query-supported-clocks=gr --format=csv | egrep -o '[0-9]{2,9}'\"";
QString nvMaxPowerLimQ = "/bin/sh -c \"nvidia-smi --query-gpu=power.max_limit --format=csv | egrep -o '[0-9]{1,7}'\"";
QString nvMinPowerLimQ = "/bin/sh -c \"nvidia-smi --query-gpu=power.min_limit --format=csv | egrep -o '[0-9]{1,7}'\"";
QString nvCurPowerLimQ = "/bin/sh -c \"nvidia-smi --query-gpu=power.limit --format=csv | egrep -o '[0-9]{1,7}'\"";
QString nvClockLimQ = "/bin/sh -c \"nvidia-settings -a GPUGraphicsClockOffset[3]=999999 | egrep -o '[-0-9]{2,9}'\"";
QString nvMemClkLimQ = "/bin/sh -c \"nvidia-settings -a GPUMemoryTransferRateOffset[3]=999999 | egrep -o '[-0-9]{2,9}'\"";
QString nvCurMaxMemClkQ = "/bin/sh -c \"nvidia-smi --query-supported-clocks=mem --format=csv | egrep -o '[0-9]{2,9}'\"";
QString nvCurMemClkOfsQ = "nvidia-settings -q GPUMemoryTransferRateOffset[3] -t";
QString nvTempQ = "nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits";
QString nvCoreClkSet = "nvidia-settings -a GPUGraphicsClockOffset[3]=";
QString nvMemClkSet = "nvidia-settings -a GPUMemoryTransferRateOffset[3]=";
QString nvPowerLimSet = "nvidia-smi -pl ";
QString nvFanSpeedSet = "nvidia-settings -a GPUTargetFanSpeed=";
QString nvVoltageSet = "nvidia-settings -a GPUOverVoltageOffset=";
QString nvFanCtlStateSet = "nvidia-settings -a GPUFanControlState=";
QString nvFanCtlStateQ = "nvidia-settings -q GPUFanControlState -t";
QString grepStringToInt = " | egrep -o '[0-9]{0,100}'\"";
QString queryForNvidiaProp = "/bin/sh -c \"lspci -vnn | grep -c 'Kernel driver in use: nvidia'\"";
QString queryGPUName = "nvidia-smi --query-gpu=gpu_name --format=csv,noheader";
QString nvGPUCountQ = "nvidia-smi --query-gpu=count --format=csv,noheader";
QString nvUUIDQ = "nvidia-smi --query-gpu=uuid --format=csv,noheader";
QString errorText = "Failed to apply these settings: ";
QString gpuDriver;
QVector <int> xCurvePoints, yCurvePoints;
int currentGPUIndex = 0;
int voltInt = 0;
int voltOfsInt = 0;
int coreFreqOfsInt = 0;
int maxPowerLimInt = 0;
int minPowerLimInt = 0;
int curPowerLimInt = 0;
int minCoreClkOfsInt = 0;
int maxCoreClkOfsInt = 0;
int curMaxClkInt = 0;
int minMemClkOfsInt = 0;
int maxMemClkOfsInt = 0;
int minVoltOfsInt = 0;
int maxVoltOfsInt = 0;
int curMaxMemClkInt = 0;
int memClkOfsInt = 0;
int fanSpeed = 0;
int temp = 0;
int targetFanSpeed = 0;
int fanControlMode = 0;
int defCoreClk = 0;
int defMemClk = 0;
int defVolt = 0;
int latestClkOfs = 0;
int latestPowerLim = 0;
int latestMemClkOfs = 0;
int latestVoltOfs = 0;
bool isRoot = false;
public slots:
void tempUpdater();
private slots:
void on_actionEdit_current_profile_triggered(bool checked);
void on_profileComboBox_activated(const QString &arg1);
void on_frequencySlider_valueChanged(int value);
void on_frequencySpinBox_valueChanged(int arg1);
void on_newProfile_clicked();
void on_powerLimSlider_valueChanged(int value);
void on_powerLimSpinBox_valueChanged(int arg1);
void on_newProfile_closed();
void on_memClkSlider_valueChanged(int value);
void on_memClkSpinBox_valueChanged(int arg1);
void on_voltageSlider_valueChanged(int value);
void on_voltageSpinBox_valueChanged(int arg1);
void fanSpeedUpdater();
void applyGPUSettings();
void on_fanSlider_valueChanged(int value);
void on_fanSpinBox_valueChanged(int arg1);
void on_applyButton_clicked();
void getGPUDriver();
void generateFanPoint();
void checkForRoot();
void resetChanges();
void resetTimer();
void on_editFanCurveButton_pressed();
void on_editProfile_closed();
void enableFanUpdater();
void setupMonitorTab();
void updateMonitor();
void saveProfileSettings();
void loadProfileSettings();
void checkForProfiles();
void on_fanModeComboBox_currentIndexChanged(int index);
void tabHandler(int index);
void setupGraphMonitorTab();
void plotHovered(QMouseEvent *event);
void updateTracer();
void clearPlots();
void clearExtremeValues();
void on_actionManage_profiles_triggered();
void on_GPUComboBox_currentIndexChanged(int index);
void on_amdPstateButton_pressed();
private:
Ui::MainWindow *ui;
bool noProfiles = true;
QStringList UUIDList;
QString latestUUID;
#ifdef NVIDIA
nvidia *nv;
#endif
#ifdef AMD
amd *amdptr;
#endif
gputypes *types;
QTimer *resettimer = new QTimer(this);
QTimer *fanUpdateTimer = new QTimer(this);
QTimer *statusLabelResetTimer = new QTimer(this);
QTimer *fanUpdaterDisablerTimer = new QTimer(this);
QTimer *monitorUpdater = new QTimer(this);
QTimer *plotHoverUpdater = new QTimer(this);
// Widgets for the graph monitor
QWidget *plotWidget = new QWidget;
QScrollArea *plotScrollArea = new QScrollArea;
QVBoxLayout *lo = new QVBoxLayout;
QVBoxLayout *plotLayout = new QVBoxLayout;
//QVector <double> qv_time;
// For updating the plot
bool insidePlot = false;
double latestPointerXcoord;
int plotIndex = 0;
struct monitorCmds {
void (gputypes::*queryFunc)(int);
int displayValue;
};
QVector <monitorCmds> monitorCmdsList;
struct plotCmds
{
QVector <double> vector;
double *valueq;
double maxval;
double minval;
QCustomPlot *plot;
QVBoxLayout *layout;
QWidget *widget;
QCPTextElement *mintext;
QCPTextElement *maxtext;
QCPTextElement *curtext;
QCPItemTracer *tracer;
QCPItemText *valText;
};
// Struct for the tree view
struct treeEntry {
QString unit;
QTreeWidgetItem *item;
double *displayValue;
};
QVector <treeEntry> treeEntryList;
struct datavector {
QVector <double> vector;
};
struct GPUData {
QVector <datavector> data;
QVector <double> qv_time;
};
QVector <GPUData> GPU;
int counter = 0;
// The maximum size of plot data vectors (range +1)
int plotVectorSize = 181;
QVector <plotCmds> plotCmdsList;
};
#endif // MAINWINDOW_H

View File

@ -1,270 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>517</width>
<height>677</height>
</rect>
</property>
<property name="windowTitle">
<string>TuxClocker</string>
</property>
<property name="windowIcon">
<iconset resource="resources.qrc">
<normaloff>:/icons/gpuonfire.svg</normaloff>:/icons/gpuonfire.svg</iconset>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="perfEditorTab">
<attribute name="title">
<string>Performance</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="fanModeLabel">
<property name="text">
<string>Fan mode:</string>
</property>
</widget>
</item>
<item row="12" column="0" colspan="3">
<widget class="QPushButton" name="applyButton">
<property name="text">
<string>Apply changes</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="5">
<widget class="QSlider" name="fanSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="7" column="0" colspan="5">
<widget class="QSlider" name="memClkSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="10" column="0" colspan="3">
<widget class="QLabel" name="clockFreqLabel">
<property name="text">
<string>Clock Frequency Offset (MHz)</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="fanModeComboBox">
<item>
<property name="text">
<string>Driver defined</string>
</property>
</item>
<item>
<property name="text">
<string>Static</string>
</property>
</item>
<item>
<property name="text">
<string>Custom</string>
</property>
</item>
</widget>
</item>
<item row="11" column="5">
<widget class="QSpinBox" name="frequencySpinBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="fanSpeedLabel">
<property name="text">
<string>Fan Speed (%)</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QLabel" name="voltgeLabel">
<property name="text">
<string>Voltage Offset (mV)</string>
</property>
</widget>
</item>
<item row="7" column="5">
<widget class="QSpinBox" name="memClkSpinBox"/>
</item>
<item row="6" column="0" colspan="3">
<widget class="QLabel" name="memClockLabel">
<property name="text">
<string>Memory Clock Offset (MHz)</string>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="QSpinBox" name="fanSpinBox"/>
</item>
<item row="9" column="5">
<widget class="QSpinBox" name="powerLimSpinBox"/>
</item>
<item row="2" column="5">
<widget class="QPushButton" name="editFanCurveButton">
<property name="maximumSize">
<size>
<width>87</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Edit fan curve&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/icons/cog.png</normaloff>:/icons/cog.png</iconset>
</property>
</widget>
</item>
<item row="12" column="3" colspan="3">
<widget class="QComboBox" name="profileComboBox"/>
</item>
<item row="5" column="5">
<widget class="QSpinBox" name="voltageSpinBox"/>
</item>
<item row="8" column="0" colspan="2">
<widget class="QLabel" name="powerLimLabel">
<property name="text">
<string>Power Limit (W)</string>
</property>
</widget>
</item>
<item row="11" column="0" colspan="5">
<widget class="QSlider" name="frequencySlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="0" colspan="5">
<widget class="QSlider" name="voltageSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="9" column="0" colspan="5">
<widget class="QSlider" name="powerLimSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QPushButton" name="amdPstateButton">
<property name="text">
<string>Edit Pstates</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="monitorTab">
<attribute name="title">
<string>Graph Monitor</string>
</attribute>
</widget>
<widget class="QWidget" name="monitorListTab">
<attribute name="title">
<string>List Monitor</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QTreeWidget" name="monitorTree">
<property name="columnCount">
<number>2</number>
</property>
<column>
<property name="text">
<string>Property</string>
</property>
</column>
<column>
<property name="text">
<string>Value</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="0" column="0">
<widget class="QComboBox" name="GPUComboBox"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>517</width>
<height>28</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>Profi&amp;les</string>
</property>
<addaction name="actionManage_profiles"/>
</widget>
<addaction name="menuFile"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionQuit">
<property name="text">
<string>&amp;Quit</string>
</property>
</action>
<action name="actionEdit_current_profile">
<property name="text">
<string>&amp;Edit current profile</string>
</property>
</action>
<action name="actionAdd_profile_from_file">
<property name="text">
<string>Add profile from file...</string>
</property>
</action>
<action name="actionAdd_new_profile">
<property name="text">
<string>&amp;Add new profile</string>
</property>
</action>
<action name="actionManage_profiles">
<property name="text">
<string>&amp;Manage profiles</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
<include location="resources.qrc"/>
</resources>
<connections/>
</ui>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 B

View File

@ -1,59 +0,0 @@
#include "monitor.h"
#include "mainwindow.h"
monitor::monitor(QWidget *parent) : QObject(parent)
{
}
void monitor::queryValues()
{
QProcess process;
process.start(nvTempQ);
process.waitForFinished();
temp = process.readLine();
temp.chop(1);
process.start(nvPowerDrawQ);
process.waitForFinished();
powerdraw = process.readLine();
powerdraw.chop(1);
process.start(nvVoltQ);
process.waitForFinished();
int voltnum = process.readLine().toInt()/1000;
voltage = QString::number(voltnum);
process.start(nvCoreClkQ);
process.waitForFinished();
coreclock = process.readLine();
coreclock.chop(1);
process.start(nvMemClkQ);
process.waitForFinished();
memclock = process.readLine();
memclock.chop(1);
process.start(nvCoreUtilQ);
process.waitForFinished();
coreutil = process.readLine();
coreutil.chop(1);
process.start(nvMemUtilQ);
process.waitForFinished();
memutil = process.readLine();
memutil.chop(1);
process.start(nvTotalMemQ);
process.waitForFinished();
totalmem = process.readLine();
totalmem.chop(1);
process.start(nvUsedMemQ);
process.waitForFinished();
usedmem = process.readLine();
usedmem.chop(1);
//process.start(nvCurMaxClkQ);
//process.waitForFinished();
//curMaxClk = process.readLine();
//curMaxClk.chop(1);
}

View File

@ -1,41 +0,0 @@
#ifndef MONITOR_H
#define MONITOR_H
#include <QObject>
class monitor : public QObject
{
Q_OBJECT
public:
explicit monitor(QWidget *parent = nullptr);
QString temp;
QString powerdraw;
QString voltage;
QString coreclock;
QString memclock;
QString coreutil;
QString memutil;
QString usedmem;
QString totalmem;
QString curMaxClk;
QString nvTempQ = "nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits";
QString nvPowerDrawQ = "nvidia-smi --query-gpu=power.draw --format=csv,nounits,noheader";
QString nvVoltQ = "nvidia-settings -q GPUCurrentCoreVoltage -t";
QString nvCoreClkQ = "nvidia-smi --query-gpu=clocks.gr --format=csv,noheader,nounits";
QString nvMemClkQ = "nvidia-smi --query-gpu=clocks.mem --format=csv,noheader,nounits";
QString nvCoreUtilQ = "nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits";
QString nvMemUtilQ = "nvidia-smi --query-gpu=utilization.memory --format=csv,noheader,nounits";
QString nvUsedMemQ = "nvidia-smi --query-gpu=memory.used --format=csv,noheader";
QString nvTotalMemQ = "nvidia-smi --query-gpu=memory.total --format=csv,noheader";
QString nvCurMaxClkQ = "nvidia-smi --query-supported-clocks=gr --format=csv,noheader";
public slots:
void queryValues();
signals:
public slots:
private slots:
};
#endif // MONITOR_H

View File

@ -1,109 +0,0 @@
#include "newprofile.h"
#include "ui_newprofile.h"
#include "mainwindow.h"
newProfile::newProfile(QWidget *parent) :
QDialog(parent),
ui(new Ui::newProfile)
{
ui->setupUi(this);
listProfiles();
//connect(ui->profileList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), SLOT(editEntryName(QListWidgetItem*)));
SignalItemDelegate *delegate = new SignalItemDelegate(ui->profileList);
connect(delegate, SIGNAL(editFinished()), SLOT(saveChange()));
ui->profileList->setItemDelegate(delegate);
}
newProfile::~newProfile()
{
delete ui;
}
void newProfile::on_profileNameEdit_textChanged(const QString &arg1)
{
newProfileName = arg1;
}
void newProfile::saveChange()
{
//qDebug() << "edit finished";
//QListWidgetItem *item = ui->profileList->item(latestIndex);
newProfileList.clear();
for (int i=0; i<ui->profileList->count(); i++) {
newProfileList.append(ui->profileList->item(i)->text());
//qDebug() << newProfileList[i];
ui->profileList->item(i)->setFlags(Qt::ItemIsEnabled);
}
}
void newProfile::on_saveButton_clicked()
{
QSettings settings("tuxclocker");
// Add the new ones
for (int i=0; i<newProfileList.size(); i++) {
settings.setValue(newProfileList[i] + "/isProfile", true);
}
for (int i=0; i<removedList.size(); i++) {
settings.beginGroup(removedList[i]);
settings.remove("");
settings.endGroup();
}
close();
}
void newProfile::listProfiles()
{
QSettings settings("tuxclocker");
QString isProfile = "/isProfile";
QStringList groups = settings.childGroups();
//qDebug() << "testi";
for (int i=0; i<groups.length(); i++) {
// Make a query $profile/isProfile
QString group = groups[i];
QString query = group.append(isProfile);
//qDebug() << query;
if (settings.value(query).toBool()) {
//qDebug() << groups[i];
ui->profileList->addItem(groups[i]);
origProfileList.append(groups[i]);
newProfileList.append(groups[i]);
}
}
// Make the items editable
for (int i=0; i<ui->profileList->count(); i++) {
ui->profileList->item(i)->setFlags(Qt::ItemIsEnabled);
}
}
/*void newProfile::editEntryName(QListWidgetItem *item)
{
qDebug() << "item dblclicked";
ui->profileList->editItem(item);
latestIndex = ui->profileList->currentRow();
}*/
void newProfile::on_cancelButton_clicked()
{
close();
}
void newProfile::on_addButton_pressed()
{
ui->profileList->addItem("");
int itemCount = ui->profileList->count()-1;
latestIndex = itemCount;
ui->profileList->item(itemCount)->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled);
ui->profileList->editItem(ui->profileList->item(itemCount));
}
void newProfile::on_removeButton_pressed()
{
if (ui->profileList->count() > 1) {
int index = ui->profileList->currentRow();
QListWidgetItem *item = ui->profileList->item(index);
removedList.append(item->text());
newProfileList.removeAt(index);
ui->profileList->takeItem(index);
delete item;
}
}

View File

@ -1,64 +0,0 @@
#ifndef NEWPROFILE_H
#define NEWPROFILE_H
#include <QDialog>
#include <QAbstractButton>
#include <QSettings>
#include <QListWidget>
#include <QStyledItemDelegate>
namespace Ui {
class newProfile;
}
class newProfile : public QDialog
{
Q_OBJECT
public:
explicit newProfile(QWidget *parent = nullptr);
~newProfile();
signals:
void mousePressEvent(QMouseEvent* event);
private slots:
void on_saveButton_clicked();
void on_profileNameEdit_textChanged(const QString &arg1);
void on_cancelButton_clicked();
void listProfiles();
//void editEntryName(QListWidgetItem *item);
void on_addButton_pressed();
void saveChange();
void on_removeButton_pressed();
private:
Ui::newProfile *ui;
QString newProfileName;
QStyledItemDelegate *deleg = new QStyledItemDelegate(this);
QStringList origProfileList;
QStringList newProfileList;
QStringList removedList;
int latestIndex = 0;
};
// New class for editing so we can detect when the editing has finished
class SignalItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
Q_DISABLE_COPY(SignalItemDelegate)
public:
explicit SignalItemDelegate(QObject* parent = Q_NULLPTR):QStyledItemDelegate(parent){
QObject::connect(this,&SignalItemDelegate::closeEditor,this,&SignalItemDelegate::editFinished);
}
void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE {
void editStarted();
return QStyledItemDelegate::setEditorData(editor,index);
}
Q_SIGNALS:
void editStarted();
void editFinished();
};
#endif // NEWPROFILE_H

View File

@ -1,62 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>newProfile</class>
<widget class="QDialog" name="newProfile">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>418</width>
<height>534</height>
</rect>
</property>
<property name="windowTitle">
<string>Manage profiles</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="4">
<widget class="QListWidget" name="profileList"/>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="saveButton">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="cancelButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="addButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/icons/plusicon.png</normaloff>:/icons/plusicon.png</iconset>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="removeButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/icons/minusicon.png</normaloff>:/icons/minusicon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="resources.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -1,439 +0,0 @@
#ifdef NVIDIA
#include "gputypes.h"
#include <X11/Xlib.h>
#include "NVCtrl/NVCtrlLib.h"
nvidia::nvidia()
{
}
void nvidia::calculateUIProperties()
{
}
bool nvidia::setupGPU()
{
// Open the x-server connection and check if the extension exists
dpy = XOpenDisplay(nullptr);
Bool ret;
int *event_basep = nullptr;
int *error_basep = nullptr;
ret = XNVCTRLQueryExtension(dpy,
event_basep,
error_basep);
qDebug() << ret;
queryGPUCount();
queryGPUNames();
queryGPUUIDs();
queryGPUFeatures();
return ret;
}
void nvidia::queryGPUCount()
{
Bool ret;
int queriedCount = 0;
ret = XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_GPU, &queriedCount);
if (!ret) {
qDebug() << "Failed to query amount of GPUs";
}
gpuCount = gpuCount + queriedCount;
// Create an appropriate number of GPU objects
for (int i=0; i<queriedCount; i++) {
GPU gpu;
gpu.gputype = Type::NV;
GPUList.append(gpu);
}
qDebug() << GPUList.size() << "gpus";
}
void nvidia::queryGPUNames()
{
Bool ret;
for (int i=0; i<gpuCount; i++) {
if (GPUList[i].gputype == Type::NV) {
ret = XNVCTRLQueryTargetStringAttribute(dpy,
NV_CTRL_TARGET_TYPE_GPU,
i,
0,
NV_CTRL_STRING_PRODUCT_NAME,
&GPUList[i].name);
if (!ret) {
qDebug() << "Failed to query GPU Name";
}
qDebug() << GPUList[i].name;
}
}
}
void nvidia::queryGPUUIDs()
{
Bool ret;
for (int i=0; i<gpuCount; i++) {
if (GPUList[i].gputype == Type::NV) {
ret = XNVCTRLQueryTargetStringAttribute(dpy,
NV_CTRL_TARGET_TYPE_GPU,
i,
0,
NV_CTRL_STRING_GPU_UUID,
&GPUList[i].uuid);
if (!ret) {
qDebug() << "Failed to query GPU UUID";
}
qDebug() << GPUList[i].uuid;
}
}
}
void nvidia::queryGPUFeatures()
{
// Query static features related to the GPU such as maximum offsets here
Bool ret;
NVCTRLAttributeValidValuesRec values;
for (int i=0; i<gpuCount; i++) {
if (GPUList[i].gputype == Type::NV) {
// Query if voltage offset is writable/readable
ret = XNVCTRLQueryValidTargetAttributeValues(dpy,
NV_CTRL_TARGET_TYPE_GPU,
i,
0,
NV_CTRL_GPU_OVER_VOLTAGE_OFFSET,
&values);
if ((values.permissions & ATTRIBUTE_TYPE_WRITE) == ATTRIBUTE_TYPE_WRITE) {
GPUList[i].overVoltAvailable = true;
GPUList[i].voltageReadable = true;
// If the feature is writable save the offset range
GPUList[i].minVoltageOffset = values.u.range.min;
GPUList[i].maxVoltageOffset = values.u.range.max;
//qDebug() << values.u.range.min << values.u.range.max << "offset range";
} else {
// Check if it's readable
if ((values.permissions & ATTRIBUTE_TYPE_READ) == ATTRIBUTE_TYPE_READ) {
GPUList[i].voltageReadable = true;
}
}
// Query if core clock offset is writable
ret = XNVCTRLQueryValidTargetAttributeValues(dpy,
NV_CTRL_TARGET_TYPE_GPU,
i,
3,
NV_CTRL_GPU_NVCLOCK_OFFSET,
&values);
if ((values.permissions & ATTRIBUTE_TYPE_WRITE) == ATTRIBUTE_TYPE_WRITE) {
GPUList[i].overClockAvailable = true;
GPUList[i].coreClkReadable = true;
GPUList[i].minCoreClkOffset = values.u.range.min;
GPUList[i].maxCoreClkOffset = values.u.range.max;
//qDebug() << values.u.range.min << values.u.range.max << "offset range";
} else {
if ((values.permissions & ATTRIBUTE_TYPE_READ) == ATTRIBUTE_TYPE_READ) {
GPUList[i].coreClkReadable = true;
}
}
// Query if memory clock offset is writable
ret = XNVCTRLQueryValidTargetAttributeValues(dpy,
NV_CTRL_TARGET_TYPE_GPU,
i,
3,
NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET,
&values);
if ((values.permissions & ATTRIBUTE_TYPE_WRITE) == ATTRIBUTE_TYPE_WRITE) {
GPUList[i].memOverClockAvailable = true;
GPUList[i].memClkReadable = true;
GPUList[i].minMemClkOffset = values.u.range.min;
GPUList[i].maxMemClkOffset = values.u.range.max;
qDebug() << values.u.range.min << values.u.range.max << "offset range";
} else {
if ((values.permissions & ATTRIBUTE_TYPE_READ) == ATTRIBUTE_TYPE_READ) {
GPUList[i].memClkReadable = true;
}
}
// Query if fan control mode is writable
ret = XNVCTRLQueryValidTargetAttributeValues(dpy,
NV_CTRL_TARGET_TYPE_GPU,
i,
0,
NV_CTRL_GPU_COOLER_MANUAL_CONTROL,
&values);
if ((values.permissions & ATTRIBUTE_TYPE_WRITE) == ATTRIBUTE_TYPE_WRITE) {
GPUList[i].manualFanCtrlAvailable = true;
qDebug() << "fan control available";
// Query fan control mode
int retval;
ret = XNVCTRLQueryTargetAttribute(dpy,
NV_CTRL_TARGET_TYPE_GPU,
i,
0,
NV_CTRL_GPU_COOLER_MANUAL_CONTROL,
&retval);
if ((retval & NV_CTRL_GPU_COOLER_MANUAL_CONTROL_TRUE) == NV_CTRL_GPU_COOLER_MANUAL_CONTROL_TRUE) {
qDebug() << "fanctl on";
GPUList[i].fanControlMode = 1;
} else {
GPUList[i].fanControlMode = 0;
qDebug() << "fanctl off";
}
}
// Query amount of VRAM
ret = XNVCTRLQueryTargetAttribute(dpy,
NV_CTRL_TARGET_TYPE_GPU,
i,
0,
NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY,
&GPUList[i].totalVRAM);
qDebug() << GPUList[i].totalVRAM << "vram";
}
}
}
void nvidia::queryGPUVoltage(int GPUIndex)
{
Bool ret;
ret = XNVCTRLQueryTargetAttribute(dpy,
NV_CTRL_TARGET_TYPE_GPU,
GPUIndex,
0,
NV_CTRL_GPU_CURRENT_CORE_VOLTAGE,
&GPUList[GPUIndex].voltage);
if (!ret) {
qDebug() << "Couldn't query voltage for GPU";
}
qDebug() << GPUList[GPUIndex].voltage;
}
void nvidia::queryGPUTemp(int GPUIndex)
{
qDebug() << GPUList.size();
Bool ret;
ret = XNVCTRLQueryTargetAttribute(dpy,
NV_CTRL_TARGET_TYPE_THERMAL_SENSOR,
GPUIndex,
0,
NV_CTRL_THERMAL_SENSOR_READING,
&GPUList[GPUIndex].temp);
if (!ret) {
qDebug() << "failed to query GPU temperature";
}
qDebug() << GPUList[GPUIndex].temp;
}
void nvidia::queryGPUFrequencies(int GPUIndex)
{
Bool ret;
int packedInt = 0;
int mem = 0;
int core = 0;
ret = XNVCTRLQueryTargetAttribute(dpy,
NV_CTRL_TARGET_TYPE_GPU,
GPUIndex,
0,
NV_CTRL_GPU_CURRENT_CLOCK_FREQS,
&packedInt);
// The function returns a 32-bit packed integer, GPU Clock is the upper 16 and Memory Clock lower 16
mem = (packedInt) & 0xFFFF;
core = (packedInt & (0xFFFF << (32 - 16))) >> (32 - 16);
qDebug() << GPUList[GPUIndex].coreFreq << "freq" << core << mem;
GPUList[GPUIndex].coreFreq = core;
GPUList[GPUIndex].memFreq = mem;
}
void nvidia::queryGPUFanSpeed(int GPUIndex)
{
Bool ret;
ret = XNVCTRLQueryTargetAttribute(dpy,
NV_CTRL_TARGET_TYPE_COOLER,
GPUIndex,
0,
NV_CTRL_THERMAL_COOLER_CURRENT_LEVEL,
&GPUList[GPUIndex].fanSpeed);
}
void nvidia::queryGPUUsedVRAM(int GPUIndex)
{
Bool ret = XNVCTRLQueryTargetAttribute(dpy,
NV_CTRL_TARGET_TYPE_GPU,
GPUIndex,
0,
NV_CTRL_USED_DEDICATED_GPU_MEMORY,
&GPUList[GPUIndex].usedVRAM);
if (!ret) {
qDebug() << "failed to query used VRAM";
}
qDebug() << GPUList[GPUIndex].usedVRAM << "usedvram";
}
void nvidia::queryGPUFreqOffset(int GPUIndex)
{
Bool ret = XNVCTRLQueryTargetAttribute(dpy,
NV_CTRL_TARGET_TYPE_GPU,
GPUIndex,
3,
NV_CTRL_GPU_NVCLOCK_OFFSET,
&GPUList[GPUIndex].coreClkOffset);
}
void nvidia::queryGPUMemClkOffset(int GPUIndex)
{
Bool ret = XNVCTRLQueryTargetAttribute(dpy,
NV_CTRL_TARGET_TYPE_GPU,
GPUIndex,
3,
NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET,
&GPUList[GPUIndex].memClkOffset);
}
void nvidia::queryGPUVoltageOffset(int GPUIndex)
{
Bool ret = XNVCTRLQueryTargetAttribute(dpy,
NV_CTRL_TARGET_TYPE_GPU,
GPUIndex,
0,
NV_CTRL_GPU_OVER_VOLTAGE_OFFSET,
&GPUList[GPUIndex].voltageOffset);
qDebug() << GPUList[GPUIndex].voltageOffset << "offset";
}
bool nvidia::assignGPUFanSpeed(int GPUIndex, int targetValue)
{
Bool ret;
ret = XNVCTRLSetTargetAttributeAndGetStatus(dpy,
NV_CTRL_TARGET_TYPE_COOLER,
GPUIndex,
0,
NV_CTRL_THERMAL_COOLER_LEVEL,
targetValue);
return ret;
}
bool nvidia::assignGPUFanCtlMode(int GPUIndex, bool manual)
{
int targetValue;
if (manual) targetValue = NV_CTRL_GPU_COOLER_MANUAL_CONTROL_TRUE;
else targetValue = NV_CTRL_GPU_COOLER_MANUAL_CONTROL_FALSE;
Bool ret = XNVCTRLSetTargetAttributeAndGetStatus(dpy,
NV_CTRL_TARGET_TYPE_GPU,
GPUIndex,
0,
NV_CTRL_GPU_COOLER_MANUAL_CONTROL,
targetValue);
return ret;
}
bool nvidia::assignGPUFreqOffset(int GPUIndex, int targetValue)
{
Bool ret = XNVCTRLSetTargetAttributeAndGetStatus(dpy,
NV_CTRL_TARGET_TYPE_GPU,
GPUIndex,
3, // This argument is the performance mode
NV_CTRL_GPU_NVCLOCK_OFFSET,
targetValue);
qDebug() << ret << "freqassign";
return ret;
}
bool nvidia::assignGPUMemClockOffset(int GPUIndex, int targetValue)
{
Bool ret = XNVCTRLSetTargetAttributeAndGetStatus(dpy,
NV_CTRL_TARGET_TYPE_GPU,
GPUIndex,
3,
NV_CTRL_GPU_MEM_TRANSFER_RATE_OFFSET,
targetValue);
qDebug() << ret << "memassign";
return ret;
}
bool nvidia::assignGPUVoltageOffset(int GPUIndex, int targetValue)
{
Bool ret = XNVCTRLSetTargetAttributeAndGetStatus(dpy,
NV_CTRL_TARGET_TYPE_GPU,
GPUIndex,
0,
NV_CTRL_GPU_OVER_VOLTAGE_OFFSET,
targetValue);
qDebug() << ret;
return ret;
}
bool nvidia::setupGPUSecondary(int GPUIndex)
{
nvmlDevice_t *dev = new nvmlDevice_t;
device = dev;
nvmlReturn_t ret = nvmlInit();
nvmlDeviceGetHandleByIndex(GPUIndex, dev);
if (NVML_SUCCESS != ret) {
return false;
}
return true;
}
void nvidia::queryGPUUtils(int GPUIndex)
{
nvmlUtilization_t utils;
nvmlReturn_t ret = nvmlDeviceGetUtilizationRates(*device, &utils);
if (NVML_SUCCESS != ret) {
qDebug() << "failed to query GPU utilizations";
}
qDebug() << utils.gpu << utils.memory << "utils";
GPUList[GPUIndex].memUtil = utils.memory;
GPUList[GPUIndex].coreUtil = utils.gpu;
}
void nvidia::queryGPUPowerDraw(int GPUIndex)
{
uint usg;
nvmlReturn_t ret = nvmlDeviceGetPowerUsage(*device, &usg);
if (NVML_SUCCESS != ret) {
qDebug() << "failed to query power usage";
} else {
GPUList[GPUIndex].powerDraw = usg;
qDebug() << usg << "pwrusg";
}
}
void nvidia::queryGPUPowerLimitLimits(int GPUIndex)
{
uint maxlim;
uint minlim;
nvmlReturn_t ret = nvmlDeviceGetPowerManagementLimitConstraints(*device, &minlim, &maxlim);
if (NVML_SUCCESS != ret) {
qDebug() << "failed to query power limit constraints";
} else {
GPUList[GPUIndex].minPowerLim = minlim;
GPUList[GPUIndex].maxPowerLim = maxlim;
qDebug() << minlim << maxlim << "powerlims";
}
}
void nvidia::queryGPUPowerLimit(int GPUIndex)
{
uint lim;
nvmlReturn_t ret = nvmlDeviceGetPowerManagementLimit(*device, &lim);
if (NVML_SUCCESS != ret) {
qDebug() << "failed to query power limit";
} else {
GPUList[GPUIndex].powerLim = lim;
}
}
void nvidia::queryGPUCurrentMaxClocks(int GPUIndex)
{
uint curmax;
// Query maximum core clock
nvmlReturn_t ret = nvmlDeviceGetMaxClockInfo(*device, NVML_CLOCK_GRAPHICS, &curmax);
if (NVML_SUCCESS != ret) {
qDebug() << "Failed to query maximum core clock";
} else {
GPUList[GPUIndex].maxCoreClk = curmax;
}
// Query maximum memory clock
ret = nvmlDeviceGetMaxClockInfo(*device, NVML_CLOCK_MEM, &curmax);
if (NVML_SUCCESS != ret) {
qDebug() << "Failed to query maximum memory clock";
} else {
GPUList[GPUIndex].maxMemClk = curmax;
qDebug() << curmax << "current max clock";
}
}
void nvidia::queryGPUPowerLimitAvailability(int GPUIndex)
{
// Assign the current power limit to see if modifying it is available
nvmlReturn_t ret = nvmlDeviceSetPowerManagementLimit(*device, GPUList[GPUIndex].powerLim);
if (NVML_ERROR_NOT_SUPPORTED == ret) {
GPUList[GPUIndex].powerLimitAvailable = false;
} else {
GPUList[GPUIndex].powerLimitAvailable = true;
}
}
bool nvidia::assignGPUPowerLimit(uint targetValue)
{
nvmlReturn_t ret = nvmlDeviceSetPowerManagementLimit(*device, targetValue);
if (NVML_SUCCESS != ret) {
return false;
}
return true;
}
#endif

View File

@ -1,98 +0,0 @@
#ifndef NVIDIA_H
#define NVIDIA_H
#include <QObject>
#include <QDebug>
#include <QtX11Extras/QX11Info>
#include <QProcess>
#include "nvml.h"
#include "gputypes.h"
class nvidia : public QObject, public gputypes
{
Q_OBJECT
public:
explicit nvidia(QObject *parent = nullptr);
//gputypes *types;
struct GPU
{
char *name;
char *uuid;
bool overVoltAvailable = false;
bool overClockAvailable = false;
bool memOverClockAvailable = false;
bool powerLimitAvailable = false;
bool voltageReadable = false;
bool coreClkReadable = false;
bool memClkReadable = false;
bool manualFanCtrlAvailable = false;
int fanControlMode;
int maxVoltageOffset;
int minVoltageOffset;
int minCoreClkOffset;
int maxCoreClkOffset;
int minMemClkOffset;
int maxMemClkOffset;
uint maxCoreClk;
uint maxMemClk;
int voltageOffset;
int coreClkOffset;
int memClkOffset;
int coreFreq;
int memFreq;
int temp;
int voltage;
int fanSpeed;
double powerDraw;
uint coreUtil;
uint memUtil;
uint minPowerLim;
uint maxPowerLim;
uint powerLim;
int totalVRAM;
int usedVRAM;
};
QVector <GPU> GPUList;
int gpuCount = 0;
private:
Display *dpy;
nvmlDevice_t *device;
signals:
public slots:
bool setupXNVCtrl();
bool setupNVML(int GPUIndex);
void queryGPUCount();
void queryGPUNames();
void queryGPUUIDs();
void queryGPUFeatures();
void queryGPUVoltage(int GPUIndex);
void queryGPUTemp(int GPUIndex);
void queryGPUFrequencies(int GPUIndex);
void queryGPUFanSpeed(int GPUIndex);
void queryGPUUsedVRAM(int GPUIndex);
void queryGPUFreqOffset(int GPUIndex);
void queryGPUMemClkOffset(int GPUIndex);
void queryGPUVoltageOffset(int GPUIndex);
void queryGPUUtils(int GPUIndex);
void queryGPUPowerDraw(int GPUIndex);
void queryGPUPowerLimit(int GPUIndex);
void queryGPUPowerLimitLimits(int GPUIndex);
void queryGPUCurrentMaxClocks(int GPUIndex);
void queryGPUPowerLimitAvailability(int GPUIndex);
bool assignGPUFanSpeed(int GPUIndex, int targetValue);
bool assignGPUFanCtlMode(int GPUIndex, int targetValue);
bool assignGPUFreqOffset(int GPUIndex, int targetValue);
bool assignGPUMemClockOffset(int GPUIndex, int targetValue);
bool assignGPUVoltageOffset(int GPUIndex, int targetValue);
// NVML functions know the GPU index already based on the dev object passed in setupNVML()
bool assignGPUPowerLimit(uint targetValue);
private slots:
};
#endif // NVIDIA_H

6284
nvml.h

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
#include "plotwidget.h"
PlotWidget::PlotWidget(QWidget *parent) : QWidget(parent)
{
}
void PlotWidget::leaveEvent(QEvent *event)
{
emit leftPlot();
}

View File

@ -1,19 +0,0 @@
#ifndef PLOTWIDGET_H
#define PLOTWIDGET_H
#include <QWidget>
class PlotWidget : public QWidget
{
Q_OBJECT
public:
explicit PlotWidget(QWidget *parent = nullptr);
signals:
void leftPlot();
protected:
void leaveEvent(QEvent *event);
public slots:
};
#endif // PLOTWIDGET_H

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
<RCC>
<qresource prefix="/icons">
<file>cog.png</file>
<file>plusicon.png</file>
<file>minusicon.png</file>
<file>gpuonfire.svg</file>
</qresource>
</RCC>

View File

@ -1,77 +0,0 @@
#-------------------------------------------------
#
# Project created by QtCreator 2018-11-02T23:09:52
#
#-------------------------------------------------
QT += core gui x11extras
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
TARGET = tuxclocker
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++11
CONFIG (release, debug|release) {
DEFINES += QT_NO_DEBUG_OUTPUT
}
#DEFINES += NVIDIA
DEFINES += AMD
SOURCES += \
main.cpp \
mainwindow.cpp \
qcustomplot.cpp \
editprofile.cpp \
newprofile.cpp \
plotwidget.cpp \
nvidia.cpp \
gputypes.cpp \
amd.cpp \
amdpstateeditor.cpp
HEADERS += \
mainwindow.h \
qcustomplot.h \
editprofile.h \
newprofile.h \
plotwidget.h \
#nvidia.h \
nvml.h \
gputypes.h \
#xlibvars.h
amdpstateeditor.h
FORMS += \
mainwindow.ui \
editprofile.ui \
newprofile.ui \
amdpstateeditor.ui
INCLUDEPATH += "/usr/lib"
INCLUDEPATH += $$(INCLUDEPATH)
INCLUDEPATH += "/usr/include/libdrm"
#LIBS += -lXext -lXNVCtrl -lX11 -lnvidia-ml
LIBS += -ldrm -ldrm_amdgpu
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
resources.qrc