Merge pull request #108 from ilya-zlobintsev/rx-6000-fixes

feat: voltage offset support, fixes for rx 6000 series format
This commit is contained in:
Ilya Zlobintsev 2023-02-27 20:59:07 +02:00 committed by GitHub
commit b9f8f1cc86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 115 additions and 19 deletions

4
Cargo.lock generated
View File

@ -25,9 +25,9 @@ dependencies = [
[[package]]
name = "amdgpu-sysfs"
version = "0.9.5"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae160ad9551e11cf5aa19fc78b590ee5f8ccfe07f983a99bead7a6680907da30"
checksum = "6667682d11c8face0277986d0cfc0862399febf666e0d9a9d8b12fa0362373ba"
dependencies = [
"enum_dispatch",
"serde",

View File

@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
amdgpu-sysfs = { version = "0.9.5", features = ["serde"] }
amdgpu-sysfs = { version = "0.9.7", features = ["serde"] }
anyhow = "1.0"
bincode = "1.3"
nix = "0.26"

View File

@ -41,6 +41,7 @@ pub struct Gpu {
pub max_core_clock: Option<u32>,
pub max_memory_clock: Option<u32>,
pub max_voltage: Option<u32>,
pub voltage_offset: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]

View File

@ -11,8 +11,8 @@ use amdgpu_sysfs::{
};
use anyhow::{anyhow, Context};
use lact_schema::{
ClocksInfo, ClocksTable, ClockspeedStats, DeviceInfo, DeviceStats, FanStats, GpuPciInfo,
LinkInfo, PciInfo, PerformanceLevel, PowerStats, VoltageStats, VramStats,
ClocksInfo, ClocksTable, ClocksTableGen, ClockspeedStats, DeviceInfo, DeviceStats, FanStats,
GpuPciInfo, LinkInfo, PciInfo, PerformanceLevel, PowerStats, VoltageStats, VramStats,
};
use pciid_parser::Database;
use std::{
@ -347,6 +347,15 @@ impl GpuController {
{
let mut table = self.handle.get_clocks_table()?;
if let ClocksTableGen::Vega20(ref mut table) = table {
// Avoid writing settings to the clocks table except the user-specified ones
// There is an issue on some GPU models where the default values are actually outside of the allowed range
// See https://github.com/sibradzic/amdgpu-clocks/issues/32#issuecomment-829953519 (part 2) for an example
table.clear();
table.voltage_offset = config.voltage_offset;
}
if let Some(clockspeed) = config.max_core_clock {
table.set_max_sclk(clockspeed)?;
}

View File

@ -214,6 +214,7 @@ impl<'a> Handler {
SetClocksCommand::MaxCoreClock(clock) => gpu_config.max_core_clock = Some(clock),
SetClocksCommand::MaxMemoryClock(clock) => gpu_config.max_memory_clock = Some(clock),
SetClocksCommand::MaxVoltage(voltage) => gpu_config.max_voltage = Some(voltage),
SetClocksCommand::VoltageOffset(offset) => gpu_config.voltage_offset = Some(offset),
SetClocksCommand::Reset => {
gpu_config.max_core_clock = None;
gpu_config.max_memory_clock = None;

View File

@ -297,6 +297,12 @@ impl App {
.context("Could not set the maximum voltage")?;
}
if let Some(offset) = clocks_settings.voltage_offset {
self.daemon_client
.set_clocks_value(&gpu_id, SetClocksCommand::VoltageOffset(offset))
.context("Could not set the voltage offset")?;
}
self.set_initial(&gpu_id);
Ok(())

View File

@ -34,7 +34,7 @@ impl InformationPage {
let gpu_name_label = label_row("GPU Model:", &values_grid, 0, 0, true);
let gpu_manufacturer_label = label_row("GPU Manufacturer:", &values_grid, 1, 0, true);
let vbios_version_label = label_row("VBIOS Version:", &values_grid, 2, 0, true);
let driver_label = label_row("Driver Version:", &values_grid, 3, 0, true);
let driver_label = label_row("Driver Used:", &values_grid, 3, 0, true);
let vram_size_label = label_row("VRAM Size:", &values_grid, 4, 0, true);
let link_speed_label = label_row("Link Speed:", &values_grid, 5, 0, true);

View File

@ -4,6 +4,9 @@ use gtk::prelude::*;
use gtk::*;
use lact_client::schema::{ClocksTable, ClocksTableGen};
const VOLTAGE_OFFSET_RANGE: f64 = 250.0;
const WARNING_TEXT: &str = "Warning: changing these values may lead to system instability and potentially damage your hardware!";
#[derive(Clone)]
pub struct ClocksFrame {
pub container: Box,
@ -11,6 +14,7 @@ pub struct ClocksFrame {
max_sclk_adjustment: Adjustment,
max_mclk_adjustment: Adjustment,
max_voltage_adjustment: Adjustment,
voltage_offset_adjustment: Adjustment,
reset_button: Button,
clocks_data_unavailable_label: Label,
}
@ -20,15 +24,29 @@ impl ClocksFrame {
let container = section_box("Maximum Clocks");
let tweaking_grid = Grid::builder().row_spacing(5).build();
let max_sclk_adjustment = oc_adjustment("GPU Clock (MHz)", &tweaking_grid, 0);
let max_voltage_adjustment = oc_adjustment("GPU voltage (mV)", &tweaking_grid, 1);
let max_mclk_adjustment = oc_adjustment("VRAM Clock (MHz)", &tweaking_grid, 2);
let warning_label = Label::builder()
.label(WARNING_TEXT)
.wrap_mode(pango::WrapMode::Word)
.halign(Align::Start)
.hexpand(true)
.margin_top(5)
.margin_bottom(5)
.build();
tweaking_grid.attach(&warning_label, 0, 0, 7, 1);
let max_sclk_adjustment = oc_adjustment("GPU Clock (MHz)", &tweaking_grid, 1);
let max_voltage_adjustment = oc_adjustment("GPU voltage (mV)", &tweaking_grid, 2);
let max_mclk_adjustment = oc_adjustment("VRAM Clock (MHz)", &tweaking_grid, 3);
let voltage_offset_adjustment = oc_adjustment("GPU voltage offset (mV)", &tweaking_grid, 4);
let reset_button = Button::builder()
.label("Defaults")
.label("Reset")
.halign(Align::End)
.tooltip_text("Warning: this resets all clock settings to defaults!")
.css_classes(["destructive-action"])
.build();
tweaking_grid.attach(&reset_button, 6, 3, 1, 1);
tweaking_grid.attach(&reset_button, 6, 5, 1, 1);
let clocks_data_unavailable_label = Label::new(Some("No clocks data available"));
@ -43,10 +61,12 @@ impl ClocksFrame {
max_voltage_adjustment,
reset_button,
clocks_data_unavailable_label,
voltage_offset_adjustment,
}
}
pub fn set_table(&self, table: ClocksTableGen) -> anyhow::Result<()> {
// The upper value "0.0" is used to hide the adjustment when info is not available
if let Some((current_sclk_max, sclk_min, sclk_max)) =
extract_value_and_range(&table, |table| {
(table.get_max_sclk(), table.get_max_sclk_range())
@ -55,6 +75,8 @@ impl ClocksFrame {
self.max_sclk_adjustment.set_lower(sclk_min.into());
self.max_sclk_adjustment.set_upper(sclk_max.into());
self.max_sclk_adjustment.set_value(current_sclk_max.into());
} else {
self.max_sclk_adjustment.set_upper(0.0);
}
if let Some((current_mclk_max, mclk_min, mclk_max)) =
@ -65,6 +87,8 @@ impl ClocksFrame {
self.max_mclk_adjustment.set_lower(mclk_min.into());
self.max_mclk_adjustment.set_upper(mclk_max.into());
self.max_mclk_adjustment.set_value(current_mclk_max.into());
} else {
self.max_mclk_adjustment.set_upper(0.0);
}
if let Some((current_voltage_max, voltage_min, voltage_max)) =
@ -76,8 +100,30 @@ impl ClocksFrame {
self.max_voltage_adjustment.set_upper(voltage_max.into());
self.max_voltage_adjustment
.set_value(current_voltage_max.into());
} else {
self.max_voltage_adjustment.set_upper(0.0);
}
if let ClocksTableGen::Vega20(table) = table {
if let Some(offset) = table.voltage_offset {
// TODO: check this
self.voltage_offset_adjustment
.set_lower(VOLTAGE_OFFSET_RANGE * -1.0);
self.voltage_offset_adjustment
.set_upper(VOLTAGE_OFFSET_RANGE);
self.voltage_offset_adjustment.set_value(offset.into());
} else {
self.voltage_offset_adjustment.set_upper(0.0);
}
} else {
self.voltage_offset_adjustment.set_upper(0.0);
}
emit_changed(&self.max_sclk_adjustment);
emit_changed(&self.max_mclk_adjustment);
emit_changed(&self.max_voltage_adjustment);
emit_changed(&self.voltage_offset_adjustment);
Ok(())
}
@ -95,7 +141,8 @@ impl ClocksFrame {
let f = clone!(@strong f => move |_: &Adjustment| f());
self.max_sclk_adjustment.connect_value_changed(f.clone());
self.max_mclk_adjustment.connect_value_changed(f.clone());
self.max_voltage_adjustment.connect_value_changed(f);
self.max_voltage_adjustment.connect_value_changed(f.clone());
self.voltage_offset_adjustment.connect_value_changed(f);
}
pub fn connect_clocks_reset<F: Fn() + 'static + Clone>(&self, f: F) {
@ -108,10 +155,17 @@ impl ClocksFrame {
let max_memory_clock = zero_to_option(self.max_mclk_adjustment.value());
let max_voltage = zero_to_option(self.max_voltage_adjustment.value());
let voltage_offset = if self.voltage_offset_adjustment.upper() == 0.0 {
None
} else {
Some(self.voltage_offset_adjustment.value() as i32)
};
ClocksSettings {
max_core_clock,
max_memory_clock,
max_voltage,
voltage_offset,
}
} else {
ClocksSettings::default()
@ -130,7 +184,7 @@ fn extract_value_and_range(
}
fn oc_adjustment(title: &'static str, grid: &Grid, row: i32) -> Adjustment {
let label = Label::new(Some(title));
let label = Label::builder().label(title).halign(Align::Start).build();
let adjustment = Adjustment::new(0.0, 0.0, 0.0, 1.0, 10.0, 0.0);
@ -148,17 +202,36 @@ fn oc_adjustment(title: &'static str, grid: &Grid, row: i32) -> Adjustment {
let value_selector = SpinButton::new(Some(&adjustment), 1.0, 0);
let value_label = Label::new(None);
adjustment.connect_value_changed(clone!(@strong value_label => move |adjustment| {
let value = adjustment.value();
value_label.set_text(&value.to_string());
}));
let popover = Popover::builder().child(&value_selector).build();
let value_button = MenuButton::builder()
.popover(&popover)
.child(&value_label)
.build();
adjustment.connect_value_changed(clone!(@strong value_label => move |adjustment| {
let value = adjustment.value();
value_label.set_text(&value.to_string());
}));
adjustment.connect_changed(
clone!(@strong label, @strong value_label, @strong scale, @strong value_button => move |adjustment| {
let value = adjustment.value();
value_label.set_text(&value.to_string());
if adjustment.upper() == 0.0 {
label.hide();
value_label.hide();
scale.hide();
value_button.hide();
} else {
label.show();
value_label.show();
scale.show();
value_button.show();
}
}
));
grid.attach(&label, 0, row, 1, 1);
grid.attach(&scale, 1, row, 4, 1);
grid.attach(&value_button, 6, row, 4, 1);
@ -171,6 +244,7 @@ pub struct ClocksSettings {
pub max_core_clock: Option<u32>,
pub max_memory_clock: Option<u32>,
pub max_voltage: Option<u32>,
pub voltage_offset: Option<i32>,
}
fn zero_to_option(value: f64) -> Option<u32> {
@ -180,3 +254,7 @@ fn zero_to_option(value: f64) -> Option<u32> {
Some(value as u32)
}
}
fn emit_changed(adjustment: &Adjustment) {
adjustment.emit_by_name::<()>("changed", &[]);
}

View File

@ -4,7 +4,7 @@ version = "0.2.2"
edition = "2021"
[dependencies]
amdgpu-sysfs = { version = "0.9.5", features = ["serde"] }
amdgpu-sysfs = { version = "0.9.7", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
indexmap = { version = "*", features = ["serde"] }

View File

@ -42,5 +42,6 @@ pub enum SetClocksCommand {
MaxCoreClock(u32),
MaxMemoryClock(u32),
MaxVoltage(u32),
VoltageOffset(i32),
Reset,
}