mirror of
https://github.com/Lurkki14/tuxclocker.git
synced 2025-02-25 18:55:24 -06:00
start new branch from scratch
This commit is contained in:
parent
41a769c674
commit
4411c29aeb
41
README.md
41
README.md
@ -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
|
||||
|
||||
    
|
||||
|
||||
# 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
795
amd.cpp
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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>
|
370
editprofile.cpp
370
editprofile.cpp
@ -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();
|
||||
}
|
@ -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
|
||||
|
@ -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><html><head/><body><p>This graph defines the relation of fan speed to the GPU temperature.</p><p>To add a point, double click on the area.</p><p>To remove a point, click on it.</p><p>To move a point, drag it.</p></body></html></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>
|
378
gpuonfire.svg
378
gpuonfire.svg
@ -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 |
32
gputypes.cpp
32
gputypes.cpp
@ -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];
|
||||
}
|
||||
}
|
311
gputypes.h
311
gputypes.h
@ -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
|
11
main.cpp
11
main.cpp
@ -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();
|
||||
}
|
1279
mainwindow.cpp
1279
mainwindow.cpp
File diff suppressed because it is too large
Load Diff
241
mainwindow.h
241
mainwindow.h
@ -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
|
270
mainwindow.ui
270
mainwindow.ui
@ -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><html><head/><body><p>Edit fan curve</p></body></html></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&les</string>
|
||||
</property>
|
||||
<addaction name="actionManage_profiles"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
<action name="actionQuit">
|
||||
<property name="text">
|
||||
<string>&Quit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEdit_current_profile">
|
||||
<property name="text">
|
||||
<string>&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>&Add new profile</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionManage_profiles">
|
||||
<property name="text">
|
||||
<string>&Manage profiles</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
BIN
minusicon.png
BIN
minusicon.png
Binary file not shown.
Before Width: | Height: | Size: 227 B |
59
monitor.cpp
59
monitor.cpp
@ -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);
|
||||
}
|
41
monitor.h
41
monitor.h
@ -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
|
109
newprofile.cpp
109
newprofile.cpp
@ -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;
|
||||
}
|
||||
}
|
64
newprofile.h
64
newprofile.h
@ -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
|
@ -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>
|
439
nvidia.cpp
439
nvidia.cpp
@ -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
|
98
nvidia.h
98
nvidia.h
@ -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
|
@ -1,10 +0,0 @@
|
||||
#include "plotwidget.h"
|
||||
|
||||
PlotWidget::PlotWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
|
||||
}
|
||||
void PlotWidget::leaveEvent(QEvent *event)
|
||||
{
|
||||
emit leftPlot();
|
||||
}
|
19
plotwidget.h
19
plotwidget.h
@ -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
|
BIN
plusicon.png
BIN
plusicon.png
Binary file not shown.
Before Width: | Height: | Size: 64 KiB |
30214
qcustomplot.cpp
30214
qcustomplot.cpp
File diff suppressed because it is too large
Load Diff
6673
qcustomplot.h
6673
qcustomplot.h
File diff suppressed because it is too large
Load Diff
@ -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>
|
77
rojekti.pro
77
rojekti.pro
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user