mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
feat: show effective VRAM clockspeed in the GUI on GDDR6 (#368)
* feat: refactor clocks frame adjustments into a separate widget * feat: show effective VRAM clockspeed in the GUI on GDDR6
This commit is contained in:
parent
99f6e9ee35
commit
9dbce2a812
@ -189,6 +189,8 @@ impl GpuController {
|
|||||||
|
|
||||||
#[cfg(feature = "libdrm_amdgpu_sys")]
|
#[cfg(feature = "libdrm_amdgpu_sys")]
|
||||||
fn get_drm_info(&self) -> Option<DrmInfo> {
|
fn get_drm_info(&self) -> Option<DrmInfo> {
|
||||||
|
use libdrm_amdgpu_sys::AMDGPU::VRAM_TYPE;
|
||||||
|
|
||||||
trace!("Reading DRM info");
|
trace!("Reading DRM info");
|
||||||
let drm_handle = self.drm_handle.as_ref();
|
let drm_handle = self.drm_handle.as_ref();
|
||||||
|
|
||||||
@ -211,6 +213,10 @@ impl GpuController {
|
|||||||
chip_class: drm_info.get_chip_class().to_string(),
|
chip_class: drm_info.get_chip_class().to_string(),
|
||||||
compute_units: drm_info.cu_active_number,
|
compute_units: drm_info.cu_active_number,
|
||||||
vram_type: drm_info.get_vram_type().to_string(),
|
vram_type: drm_info.get_vram_type().to_string(),
|
||||||
|
vram_clock_ratio: match drm_info.get_vram_type() {
|
||||||
|
VRAM_TYPE::GDDR6 => 2.0,
|
||||||
|
_ => 1.0,
|
||||||
|
},
|
||||||
vram_bit_width: drm_info.vram_bit_width,
|
vram_bit_width: drm_info.vram_bit_width,
|
||||||
vram_max_bw: drm_info.peak_memory_bw_gb().to_string(),
|
vram_max_bw: drm_info.peak_memory_bw_gb().to_string(),
|
||||||
l1_cache_per_cu: drm_info.get_l1_cache_size(),
|
l1_cache_per_cu: drm_info.get_l1_cache_size(),
|
||||||
|
@ -18,7 +18,7 @@ glib::wrapper! {
|
|||||||
|
|
||||||
impl GraphsWindow {
|
impl GraphsWindow {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Object::builder().build()
|
Object::builder().property("vram_clock_ratio", 1.0).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_stats(&self, stats: &DeviceStats) {
|
pub fn set_stats(&self, stats: &DeviceStats) {
|
||||||
@ -79,7 +79,7 @@ impl GraphsWindow {
|
|||||||
clockspeed_plot.push_line_series("GPU (Trgt)", point as f64);
|
clockspeed_plot.push_line_series("GPU (Trgt)", point as f64);
|
||||||
}
|
}
|
||||||
if let Some(point) = stats.clockspeed.vram_clockspeed {
|
if let Some(point) = stats.clockspeed.vram_clockspeed {
|
||||||
clockspeed_plot.push_line_series("VRAM", point as f64);
|
clockspeed_plot.push_line_series("VRAM", point as f64 * self.vram_clock_ratio());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(max_speed) = stats.fan.speed_max {
|
if let Some(max_speed) = stats.fan.speed_max {
|
||||||
@ -132,7 +132,7 @@ impl Default for GraphsWindow {
|
|||||||
mod imp {
|
mod imp {
|
||||||
use super::plot::Plot;
|
use super::plot::Plot;
|
||||||
use gtk::{
|
use gtk::{
|
||||||
glib::{self, subclass::InitializingObject},
|
glib::{self, subclass::InitializingObject, Properties},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
subclass::{
|
subclass::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
@ -140,8 +140,10 @@ mod imp {
|
|||||||
},
|
},
|
||||||
CompositeTemplate,
|
CompositeTemplate,
|
||||||
};
|
};
|
||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
#[derive(CompositeTemplate, Default)]
|
#[derive(CompositeTemplate, Default, Properties)]
|
||||||
|
#[properties(wrapper_type = super::GraphsWindow)]
|
||||||
#[template(file = "ui/graphs_window.blp")]
|
#[template(file = "ui/graphs_window.blp")]
|
||||||
pub struct GraphsWindow {
|
pub struct GraphsWindow {
|
||||||
#[template_child]
|
#[template_child]
|
||||||
@ -152,6 +154,9 @@ mod imp {
|
|||||||
pub(super) power_plot: TemplateChild<Plot>,
|
pub(super) power_plot: TemplateChild<Plot>,
|
||||||
#[template_child]
|
#[template_child]
|
||||||
pub(super) fan_plot: TemplateChild<Plot>,
|
pub(super) fan_plot: TemplateChild<Plot>,
|
||||||
|
|
||||||
|
#[property(get, set)]
|
||||||
|
pub vram_clock_ratio: Cell<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
@ -171,6 +176,7 @@ mod imp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[glib::derived_properties]
|
||||||
impl ObjectImpl for GraphsWindow {}
|
impl ObjectImpl for GraphsWindow {}
|
||||||
|
|
||||||
impl WidgetImpl for GraphsWindow {}
|
impl WidgetImpl for GraphsWindow {}
|
||||||
|
@ -361,6 +361,14 @@ impl App {
|
|||||||
trace!("setting info {info:?}");
|
trace!("setting info {info:?}");
|
||||||
|
|
||||||
self.root_stack.info_page.set_info(&info);
|
self.root_stack.info_page.set_info(&info);
|
||||||
|
self.root_stack.oc_page.set_info(&info);
|
||||||
|
|
||||||
|
let vram_clock_ratio = info
|
||||||
|
.drm_info
|
||||||
|
.as_ref()
|
||||||
|
.map(|info| info.vram_clock_ratio)
|
||||||
|
.unwrap_or(1.0);
|
||||||
|
self.graphs_window.set_vram_clock_ratio(vram_clock_ratio);
|
||||||
|
|
||||||
self.set_initial(gpu_id);
|
self.set_initial(gpu_id);
|
||||||
self.root_stack.thermals_page.set_info(&info);
|
self.root_stack.thermals_page.set_info(&info);
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
|
mod adjustment_row;
|
||||||
|
|
||||||
use crate::app::page_section::PageSection;
|
use crate::app::page_section::PageSection;
|
||||||
|
use crate::app::root_stack::oc_adjustment::OcAdjustment;
|
||||||
|
use adjustment_row::AdjustmentRow;
|
||||||
use amdgpu_sysfs::gpu_handle::overdrive::{ClocksTable, ClocksTableGen};
|
use amdgpu_sysfs::gpu_handle::overdrive::{ClocksTable, ClocksTableGen};
|
||||||
use glib::clone;
|
use glib::clone;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::*;
|
use gtk::*;
|
||||||
use std::rc::Rc;
|
use subclass::prelude::ObjectSubclassIsExt;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
const DEFAULT_VOLTAGE_OFFSET_RANGE: i32 = 250;
|
const DEFAULT_VOLTAGE_OFFSET_RANGE: i32 = 250;
|
||||||
@ -19,13 +22,13 @@ pub struct ClocksFrame {
|
|||||||
basic_togglebutton: ToggleButton,
|
basic_togglebutton: ToggleButton,
|
||||||
advanced_togglebutton: ToggleButton,
|
advanced_togglebutton: ToggleButton,
|
||||||
min_values_grid: Grid,
|
min_values_grid: Grid,
|
||||||
min_sclk_adjustment: (Adjustment, Scale, Rc<AtomicBool>),
|
min_sclk_adjustment: AdjustmentRow,
|
||||||
min_mclk_adjustment: (Adjustment, Scale, Rc<AtomicBool>),
|
min_mclk_adjustment: AdjustmentRow,
|
||||||
min_voltage_adjustment: (Adjustment, Scale, Rc<AtomicBool>),
|
min_voltage_adjustment: AdjustmentRow,
|
||||||
max_sclk_adjustment: (Adjustment, Scale, Rc<AtomicBool>),
|
max_sclk_adjustment: AdjustmentRow,
|
||||||
max_mclk_adjustment: (Adjustment, Scale, Rc<AtomicBool>),
|
max_mclk_adjustment: AdjustmentRow,
|
||||||
max_voltage_adjustment: (Adjustment, Scale, Rc<AtomicBool>),
|
max_voltage_adjustment: AdjustmentRow,
|
||||||
voltage_offset_adjustment: (Adjustment, Scale, Rc<AtomicBool>),
|
voltage_offset_adjustment: AdjustmentRow,
|
||||||
reset_button: Button,
|
reset_button: Button,
|
||||||
warning_label: Label,
|
warning_label: Label,
|
||||||
clocks_data_unavailable_label: Label,
|
clocks_data_unavailable_label: Label,
|
||||||
@ -62,18 +65,25 @@ impl ClocksFrame {
|
|||||||
|
|
||||||
let min_values_grid = Grid::builder().row_spacing(5).build();
|
let min_values_grid = Grid::builder().row_spacing(5).build();
|
||||||
|
|
||||||
let min_sclk_adjustment = oc_adjustment("Minimum GPU Clock (MHz)", &min_values_grid, 0);
|
let min_sclk_adjustment =
|
||||||
let min_mclk_adjustment = oc_adjustment("Minimum VRAM Clock (MHz)", &min_values_grid, 1);
|
AdjustmentRow::new_and_attach("Minimum GPU Clock (MHz)", &min_values_grid, 0);
|
||||||
let min_voltage_adjustment = oc_adjustment("Minimum GPU voltage (mV)", &min_values_grid, 2);
|
let min_mclk_adjustment =
|
||||||
|
AdjustmentRow::new_and_attach("Minimum VRAM Clock (MHz)", &min_values_grid, 1);
|
||||||
|
let min_voltage_adjustment =
|
||||||
|
AdjustmentRow::new_and_attach("Minimum GPU voltage (mV)", &min_values_grid, 2);
|
||||||
|
|
||||||
container.append(&min_values_grid);
|
container.append(&min_values_grid);
|
||||||
|
|
||||||
let tweaking_grid = Grid::builder().row_spacing(5).build();
|
let tweaking_grid = Grid::builder().row_spacing(5).build();
|
||||||
|
|
||||||
let max_sclk_adjustment = oc_adjustment("Maximum GPU Clock (MHz)", &tweaking_grid, 1);
|
let max_sclk_adjustment =
|
||||||
let max_voltage_adjustment = oc_adjustment("Maximum GPU voltage (mV)", &tweaking_grid, 2);
|
AdjustmentRow::new_and_attach("Maximum GPU Clock (MHz)", &tweaking_grid, 1);
|
||||||
let max_mclk_adjustment = oc_adjustment("Maximum VRAM Clock (MHz)", &tweaking_grid, 3);
|
let max_voltage_adjustment =
|
||||||
let voltage_offset_adjustment = oc_adjustment("GPU voltage offset (mV)", &tweaking_grid, 4);
|
AdjustmentRow::new_and_attach("Maximum GPU voltage (mV)", &tweaking_grid, 2);
|
||||||
|
let max_mclk_adjustment =
|
||||||
|
AdjustmentRow::new_and_attach("Maximum VRAM Clock (MHz)", &tweaking_grid, 3);
|
||||||
|
let voltage_offset_adjustment =
|
||||||
|
AdjustmentRow::new_and_attach("GPU voltage offset (mV)", &tweaking_grid, 4);
|
||||||
|
|
||||||
let reset_button = Button::builder()
|
let reset_button = Button::builder()
|
||||||
.label("Reset")
|
.label("Reset")
|
||||||
@ -145,15 +155,14 @@ impl ClocksFrame {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
self.min_sclk_adjustment.0.set_lower(sclk_min.into());
|
let min_sclk_adjustment = &self.min_sclk_adjustment.imp().adjustment;
|
||||||
self.min_sclk_adjustment.0.set_upper(sclk_max.into());
|
min_sclk_adjustment.set_lower(sclk_min.into());
|
||||||
self.min_sclk_adjustment
|
min_sclk_adjustment.set_upper(sclk_max.into());
|
||||||
.0
|
min_sclk_adjustment.set_initial_value(current_sclk_min.into());
|
||||||
.set_value(current_sclk_min.into());
|
|
||||||
|
|
||||||
self.min_sclk_adjustment.1.set_visible(true);
|
self.min_sclk_adjustment.set_visible(true);
|
||||||
} else {
|
} else {
|
||||||
self.min_sclk_adjustment.1.set_visible(false);
|
self.min_sclk_adjustment.set_visible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((current_mclk_min, mclk_min, mclk_max)) =
|
if let Some((current_mclk_min, mclk_min, mclk_max)) =
|
||||||
@ -164,14 +173,14 @@ impl ClocksFrame {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
self.min_mclk_adjustment.0.set_lower(mclk_min.into());
|
let min_mclk_adjustment = &self.min_mclk_adjustment.imp().adjustment;
|
||||||
self.min_mclk_adjustment.0.set_upper(mclk_max.into());
|
min_mclk_adjustment.set_lower(mclk_min.into());
|
||||||
self.min_mclk_adjustment
|
min_mclk_adjustment.set_upper(mclk_max.into());
|
||||||
.0
|
min_mclk_adjustment.set_initial_value(current_mclk_min.into());
|
||||||
.set_value(current_mclk_min.into());
|
|
||||||
self.min_mclk_adjustment.1.set_visible(true);
|
self.min_mclk_adjustment.set_visible(true);
|
||||||
} else {
|
} else {
|
||||||
self.min_mclk_adjustment.1.set_visible(false);
|
self.min_mclk_adjustment.set_visible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((current_min_voltage, voltage_min, voltage_max)) =
|
if let Some((current_min_voltage, voltage_min, voltage_max)) =
|
||||||
@ -184,14 +193,15 @@ impl ClocksFrame {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
self.min_voltage_adjustment.0.set_lower(voltage_min.into());
|
let min_voltage_adjustment = &self.min_voltage_adjustment.imp().adjustment;
|
||||||
self.min_voltage_adjustment.0.set_upper(voltage_max.into());
|
|
||||||
self.min_voltage_adjustment
|
min_voltage_adjustment.set_lower(voltage_min.into());
|
||||||
.0
|
min_voltage_adjustment.set_upper(voltage_max.into());
|
||||||
.set_value(current_min_voltage.into());
|
min_voltage_adjustment.set_value(current_min_voltage.into());
|
||||||
self.min_voltage_adjustment.1.set_visible(true);
|
|
||||||
|
self.min_voltage_adjustment.set_visible(true);
|
||||||
} else {
|
} else {
|
||||||
self.min_voltage_adjustment.1.set_visible(false);
|
self.min_voltage_adjustment.set_visible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((current_sclk_max, sclk_min, sclk_max)) =
|
if let Some((current_sclk_max, sclk_min, sclk_max)) =
|
||||||
@ -199,14 +209,15 @@ impl ClocksFrame {
|
|||||||
(table.get_max_sclk(), table.get_max_sclk_range())
|
(table.get_max_sclk(), table.get_max_sclk_range())
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
self.max_sclk_adjustment.0.set_lower(sclk_min.into());
|
let max_sclk_adjustment = &self.max_sclk_adjustment.imp().adjustment;
|
||||||
self.max_sclk_adjustment.0.set_upper(sclk_max.into());
|
|
||||||
self.max_sclk_adjustment
|
max_sclk_adjustment.set_lower(sclk_min.into());
|
||||||
.0
|
max_sclk_adjustment.set_upper(sclk_max.into());
|
||||||
.set_value(current_sclk_max.into());
|
max_sclk_adjustment.set_value(current_sclk_max.into());
|
||||||
self.max_sclk_adjustment.1.set_visible(true);
|
|
||||||
|
self.max_sclk_adjustment.set_visible(true);
|
||||||
} else {
|
} else {
|
||||||
self.max_sclk_adjustment.1.set_visible(false);
|
self.max_sclk_adjustment.set_visible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((current_mclk_max, mclk_min, mclk_max)) =
|
if let Some((current_mclk_max, mclk_min, mclk_max)) =
|
||||||
@ -214,14 +225,14 @@ impl ClocksFrame {
|
|||||||
(table.get_max_mclk(), table.get_max_mclk_range())
|
(table.get_max_mclk(), table.get_max_mclk_range())
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
self.max_mclk_adjustment.0.set_lower(mclk_min.into());
|
let max_mclk_adjustment = &self.max_mclk_adjustment.imp().adjustment;
|
||||||
self.max_mclk_adjustment.0.set_upper(mclk_max.into());
|
max_mclk_adjustment.set_lower(mclk_min.into());
|
||||||
self.max_mclk_adjustment
|
max_mclk_adjustment.set_upper(mclk_max.into());
|
||||||
.0
|
max_mclk_adjustment.set_value(current_mclk_max.into());
|
||||||
.set_value(current_mclk_max.into());
|
|
||||||
self.max_mclk_adjustment.1.set_visible(true);
|
self.max_mclk_adjustment.set_visible(true);
|
||||||
} else {
|
} else {
|
||||||
self.max_mclk_adjustment.1.set_visible(false);
|
self.max_mclk_adjustment.set_visible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((current_voltage_max, voltage_min, voltage_max)) =
|
if let Some((current_voltage_max, voltage_min, voltage_max)) =
|
||||||
@ -229,14 +240,14 @@ impl ClocksFrame {
|
|||||||
(table.get_max_sclk_voltage(), table.get_max_voltage_range())
|
(table.get_max_sclk_voltage(), table.get_max_voltage_range())
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
self.max_voltage_adjustment.0.set_lower(voltage_min.into());
|
let max_voltage_adjustment = &self.max_voltage_adjustment.imp().adjustment;
|
||||||
self.max_voltage_adjustment.0.set_upper(voltage_max.into());
|
max_voltage_adjustment.set_lower(voltage_min.into());
|
||||||
self.max_voltage_adjustment
|
max_voltage_adjustment.set_upper(voltage_max.into());
|
||||||
.0
|
max_voltage_adjustment.set_value(current_voltage_max.into());
|
||||||
.set_value(current_voltage_max.into());
|
|
||||||
self.max_voltage_adjustment.1.set_visible(true);
|
self.max_voltage_adjustment.set_visible(true);
|
||||||
} else {
|
} else {
|
||||||
self.max_voltage_adjustment.1.set_visible(false);
|
self.max_voltage_adjustment.set_visible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ClocksTableGen::Vega20(table) = table {
|
if let ClocksTableGen::Vega20(table) = table {
|
||||||
@ -247,28 +258,26 @@ impl ClocksFrame {
|
|||||||
.and_then(|range| range.into_full())
|
.and_then(|range| range.into_full())
|
||||||
.unwrap_or((-DEFAULT_VOLTAGE_OFFSET_RANGE, DEFAULT_VOLTAGE_OFFSET_RANGE));
|
.unwrap_or((-DEFAULT_VOLTAGE_OFFSET_RANGE, DEFAULT_VOLTAGE_OFFSET_RANGE));
|
||||||
|
|
||||||
self.voltage_offset_adjustment
|
let voltage_offset_adjustment = &self.voltage_offset_adjustment.imp().adjustment;
|
||||||
.0
|
voltage_offset_adjustment.set_lower(min_offset as f64);
|
||||||
.set_lower(min_offset as f64);
|
voltage_offset_adjustment.set_upper(max_offset as f64);
|
||||||
self.voltage_offset_adjustment
|
voltage_offset_adjustment.set_value(offset.into());
|
||||||
.0
|
|
||||||
.set_upper(max_offset as f64);
|
self.voltage_offset_adjustment.set_visible(true);
|
||||||
self.voltage_offset_adjustment.0.set_value(offset.into());
|
|
||||||
self.voltage_offset_adjustment.1.set_visible(true);
|
|
||||||
} else {
|
} else {
|
||||||
self.voltage_offset_adjustment.1.set_visible(false);
|
self.voltage_offset_adjustment.set_visible(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.voltage_offset_adjustment.1.set_visible(false);
|
self.voltage_offset_adjustment.set_visible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_changed(&self.min_sclk_adjustment);
|
self.min_sclk_adjustment.refresh();
|
||||||
emit_changed(&self.min_mclk_adjustment);
|
self.min_mclk_adjustment.refresh();
|
||||||
emit_changed(&self.min_voltage_adjustment);
|
self.min_voltage_adjustment.refresh();
|
||||||
emit_changed(&self.max_sclk_adjustment);
|
self.max_sclk_adjustment.refresh();
|
||||||
emit_changed(&self.max_mclk_adjustment);
|
self.max_mclk_adjustment.refresh();
|
||||||
emit_changed(&self.max_voltage_adjustment);
|
self.max_voltage_adjustment.refresh();
|
||||||
emit_changed(&self.voltage_offset_adjustment);
|
self.voltage_offset_adjustment.refresh();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -287,23 +296,46 @@ impl ClocksFrame {
|
|||||||
self.clocks_data_unavailable_label.show();
|
self.clocks_data_unavailable_label.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_vram_clock_ratio(&self, ratio: f64) {
|
||||||
|
self.min_mclk_adjustment.set_value_ratio(ratio);
|
||||||
|
self.max_mclk_adjustment.set_value_ratio(ratio);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn connect_clocks_changed<F: Fn() + 'static + Clone>(&self, f: F) {
|
pub fn connect_clocks_changed<F: Fn() + 'static + Clone>(&self, f: F) {
|
||||||
let f = clone!(
|
let f = clone!(
|
||||||
#[strong]
|
#[strong]
|
||||||
f,
|
f,
|
||||||
move |_: &Adjustment| f()
|
move |_: &OcAdjustment| f()
|
||||||
);
|
);
|
||||||
self.min_sclk_adjustment.0.connect_value_changed(f.clone());
|
|
||||||
self.min_mclk_adjustment.0.connect_value_changed(f.clone());
|
self.min_sclk_adjustment
|
||||||
|
.imp()
|
||||||
|
.adjustment
|
||||||
|
.connect_value_changed(f.clone());
|
||||||
|
self.min_mclk_adjustment
|
||||||
|
.imp()
|
||||||
|
.adjustment
|
||||||
|
.connect_value_changed(f.clone());
|
||||||
self.min_voltage_adjustment
|
self.min_voltage_adjustment
|
||||||
.0
|
.imp()
|
||||||
|
.adjustment
|
||||||
|
.connect_value_changed(f.clone());
|
||||||
|
self.max_sclk_adjustment
|
||||||
|
.imp()
|
||||||
|
.adjustment
|
||||||
|
.connect_value_changed(f.clone());
|
||||||
|
self.max_mclk_adjustment
|
||||||
|
.imp()
|
||||||
|
.adjustment
|
||||||
.connect_value_changed(f.clone());
|
.connect_value_changed(f.clone());
|
||||||
self.max_sclk_adjustment.0.connect_value_changed(f.clone());
|
|
||||||
self.max_mclk_adjustment.0.connect_value_changed(f.clone());
|
|
||||||
self.max_voltage_adjustment
|
self.max_voltage_adjustment
|
||||||
.0
|
.imp()
|
||||||
|
.adjustment
|
||||||
.connect_value_changed(f.clone());
|
.connect_value_changed(f.clone());
|
||||||
self.voltage_offset_adjustment.0.connect_value_changed(f);
|
self.voltage_offset_adjustment
|
||||||
|
.imp()
|
||||||
|
.adjustment
|
||||||
|
.connect_value_changed(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect_clocks_reset<F: Fn() + 'static + Clone>(&self, f: F) {
|
pub fn connect_clocks_reset<F: Fn() + 'static + Clone>(&self, f: F) {
|
||||||
@ -312,15 +344,15 @@ impl ClocksFrame {
|
|||||||
|
|
||||||
pub fn get_settings(&self) -> ClocksSettings {
|
pub fn get_settings(&self) -> ClocksSettings {
|
||||||
if self.tweaking_grid.get_visible() {
|
if self.tweaking_grid.get_visible() {
|
||||||
let min_core_clock = get_adjustment_value(&self.min_sclk_adjustment);
|
let min_core_clock = self.min_sclk_adjustment.get_value();
|
||||||
let min_memory_clock = get_adjustment_value(&self.min_mclk_adjustment);
|
let min_memory_clock = self.min_mclk_adjustment.get_value();
|
||||||
let min_voltage = get_adjustment_value(&self.min_voltage_adjustment);
|
let min_voltage = self.min_voltage_adjustment.get_value();
|
||||||
let max_core_clock = get_adjustment_value(&self.max_sclk_adjustment);
|
let max_core_clock = self.max_sclk_adjustment.get_value();
|
||||||
let max_memory_clock = get_adjustment_value(&self.max_mclk_adjustment);
|
let max_memory_clock = self.max_mclk_adjustment.get_value();
|
||||||
let max_voltage = get_adjustment_value(&self.max_voltage_adjustment);
|
let max_voltage = self.max_voltage_adjustment.get_value();
|
||||||
|
|
||||||
let voltage_offset = if self.voltage_offset_adjustment.1.get_visible() {
|
let voltage_offset = if self.voltage_offset_adjustment.get_visible() {
|
||||||
Some(self.voltage_offset_adjustment.0.value() as i32)
|
self.voltage_offset_adjustment.get_value()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -362,71 +394,6 @@ fn extract_value_and_range(
|
|||||||
Some((value, min, max))
|
Some((value, min, max))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn oc_adjustment(
|
|
||||||
title: &'static str,
|
|
||||||
grid: &Grid,
|
|
||||||
row: i32,
|
|
||||||
) -> (Adjustment, Scale, Rc<AtomicBool>) {
|
|
||||||
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);
|
|
||||||
|
|
||||||
let scale = Scale::builder()
|
|
||||||
.orientation(Orientation::Horizontal)
|
|
||||||
.adjustment(&adjustment)
|
|
||||||
.hexpand(true)
|
|
||||||
.round_digits(0)
|
|
||||||
.digits(0)
|
|
||||||
.value_pos(PositionType::Right)
|
|
||||||
.margin_start(5)
|
|
||||||
.margin_end(5)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let value_selector = SpinButton::new(Some(&adjustment), 1.0, 0);
|
|
||||||
let value_label = Label::new(None);
|
|
||||||
|
|
||||||
let popover = Popover::builder().child(&value_selector).build();
|
|
||||||
let value_button = MenuButton::builder()
|
|
||||||
.popover(&popover)
|
|
||||||
.child(&value_label)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let changed = Rc::new(AtomicBool::new(false));
|
|
||||||
|
|
||||||
adjustment.connect_value_changed(clone!(
|
|
||||||
#[strong]
|
|
||||||
value_label,
|
|
||||||
#[strong]
|
|
||||||
changed,
|
|
||||||
move |adjustment| {
|
|
||||||
changed.store(true, Ordering::SeqCst);
|
|
||||||
|
|
||||||
let value = adjustment.value();
|
|
||||||
value_label.set_text(&value.to_string());
|
|
||||||
}
|
|
||||||
));
|
|
||||||
|
|
||||||
scale.connect_visible_notify(clone!(
|
|
||||||
#[strong]
|
|
||||||
label,
|
|
||||||
#[strong]
|
|
||||||
value_label,
|
|
||||||
#[strong]
|
|
||||||
value_button,
|
|
||||||
move |scale| {
|
|
||||||
label.set_visible(scale.get_visible());
|
|
||||||
value_button.set_visible(scale.get_visible());
|
|
||||||
value_label.set_visible(scale.get_visible());
|
|
||||||
}
|
|
||||||
));
|
|
||||||
|
|
||||||
grid.attach(&label, 0, row, 1, 1);
|
|
||||||
grid.attach(&scale, 1, row, 4, 1);
|
|
||||||
grid.attach(&value_button, 6, row, 4, 1);
|
|
||||||
|
|
||||||
(adjustment, scale, changed)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ClocksSettings {
|
pub struct ClocksSettings {
|
||||||
pub min_core_clock: Option<i32>,
|
pub min_core_clock: Option<i32>,
|
||||||
@ -437,26 +404,3 @@ pub struct ClocksSettings {
|
|||||||
pub max_voltage: Option<i32>,
|
pub max_voltage: Option<i32>,
|
||||||
pub voltage_offset: Option<i32>,
|
pub voltage_offset: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_adjustment_value(
|
|
||||||
(adjustment, scale, changed): &(Adjustment, Scale, Rc<AtomicBool>),
|
|
||||||
) -> Option<i32> {
|
|
||||||
let changed = changed.load(Ordering::SeqCst);
|
|
||||||
|
|
||||||
if changed {
|
|
||||||
let value = adjustment.value();
|
|
||||||
if scale.get_visible() {
|
|
||||||
Some(value as i32)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn emit_changed(adjustment: &(Adjustment, Scale, Rc<AtomicBool>)) {
|
|
||||||
adjustment.0.emit_by_name::<()>("value-changed", &[]);
|
|
||||||
adjustment.1.notify("visible");
|
|
||||||
adjustment.2.store(false, Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,151 @@
|
|||||||
|
use gtk::{
|
||||||
|
glib::{self, Object},
|
||||||
|
prelude::WidgetExt,
|
||||||
|
prelude::{GridExt, ObjectExt},
|
||||||
|
subclass::prelude::ObjectSubclassIsExt,
|
||||||
|
Grid,
|
||||||
|
};
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct AdjustmentRow(ObjectSubclass<imp::AdjustmentRow>)
|
||||||
|
@extends gtk::Widget,
|
||||||
|
@implements gtk::Orientable, gtk::Accessible, gtk::Buildable;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AdjustmentRow {
|
||||||
|
pub fn new(title: &str) -> Self {
|
||||||
|
Object::builder()
|
||||||
|
.property("title", title)
|
||||||
|
.property("visible", true)
|
||||||
|
.property("value_ratio", 1.0)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_and_attach(title: &str, grid: &Grid, row: i32) -> Self {
|
||||||
|
let adj_row = Self::new(title);
|
||||||
|
adj_row.attach_to_grid(grid, row);
|
||||||
|
adj_row
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> Option<i32> {
|
||||||
|
self.imp()
|
||||||
|
.adjustment
|
||||||
|
.get_changed_value(false)
|
||||||
|
.map(|value| value as i32)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn attach_to_grid(&self, grid: &Grid, row: i32) {
|
||||||
|
let obj = self.imp();
|
||||||
|
|
||||||
|
obj.label.unparent();
|
||||||
|
obj.scale.unparent();
|
||||||
|
obj.value_button.unparent();
|
||||||
|
|
||||||
|
grid.attach(&obj.label.get(), 0, row, 1, 1);
|
||||||
|
grid.attach(&obj.scale.get(), 1, row, 4, 1);
|
||||||
|
grid.attach(&obj.value_button.get(), 6, row, 4, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn refresh(&self) {
|
||||||
|
let obj = self.imp();
|
||||||
|
obj.adjustment.emit_by_name::<()>("value-changed", &[]);
|
||||||
|
self.notify("visible");
|
||||||
|
obj.adjustment.imp().changed.store(false, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod imp {
|
||||||
|
use crate::app::root_stack::oc_adjustment::OcAdjustment;
|
||||||
|
use glib::{clone, subclass::InitializingObject};
|
||||||
|
use gtk::{
|
||||||
|
glib::{self, Properties},
|
||||||
|
prelude::*,
|
||||||
|
subclass::{
|
||||||
|
prelude::*,
|
||||||
|
widget::{CompositeTemplateClass, WidgetImpl},
|
||||||
|
},
|
||||||
|
CompositeTemplate, Label, MenuButton, Scale, SpinButton, TemplateChild,
|
||||||
|
};
|
||||||
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
|
#[derive(CompositeTemplate, Default, Properties)]
|
||||||
|
#[properties(wrapper_type = super::AdjustmentRow)]
|
||||||
|
#[template(file = "ui/oc_page/clocks_frame/adjustment_row.blp")]
|
||||||
|
pub struct AdjustmentRow {
|
||||||
|
#[property(get, set)]
|
||||||
|
pub visible: Rc<RefCell<bool>>,
|
||||||
|
#[property(get, set)]
|
||||||
|
pub value_ratio: Rc<RefCell<f64>>,
|
||||||
|
#[property(get, set)]
|
||||||
|
pub title: Rc<RefCell<String>>,
|
||||||
|
|
||||||
|
#[template_child]
|
||||||
|
pub label: TemplateChild<Label>,
|
||||||
|
#[template_child]
|
||||||
|
pub scale: TemplateChild<Scale>,
|
||||||
|
#[template_child]
|
||||||
|
pub value_button: TemplateChild<MenuButton>,
|
||||||
|
#[template_child]
|
||||||
|
pub value_spinbutton: TemplateChild<SpinButton>,
|
||||||
|
#[template_child]
|
||||||
|
pub adjustment: TemplateChild<OcAdjustment>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for AdjustmentRow {
|
||||||
|
const NAME: &'static str = "AdjustmentRow";
|
||||||
|
type Type = super::AdjustmentRow;
|
||||||
|
type ParentType = gtk::Widget;
|
||||||
|
|
||||||
|
fn class_init(class: &mut Self::Class) {
|
||||||
|
OcAdjustment::ensure_type();
|
||||||
|
class.bind_template();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instance_init(obj: &InitializingObject<Self>) {
|
||||||
|
obj.init_template();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::derived_properties]
|
||||||
|
impl ObjectImpl for AdjustmentRow {
|
||||||
|
fn constructed(&self) {
|
||||||
|
self.parent_constructed();
|
||||||
|
|
||||||
|
self.adjustment.connect_value_changed(clone!(
|
||||||
|
#[strong(rename_to = value_button)]
|
||||||
|
self.value_button,
|
||||||
|
#[strong(rename_to = value_ratio)]
|
||||||
|
self.value_ratio,
|
||||||
|
move |adj| {
|
||||||
|
let ratio = *value_ratio.borrow();
|
||||||
|
let text = (adj.value() * ratio).to_string();
|
||||||
|
value_button.set_label(&text);
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
self.value_spinbutton.connect_input(clone!(
|
||||||
|
#[strong(rename_to = value_ratio)]
|
||||||
|
self.value_ratio,
|
||||||
|
move |spin| {
|
||||||
|
let text = spin.text();
|
||||||
|
let value: f64 = text.parse().ok()?;
|
||||||
|
Some(Ok(value / *value_ratio.borrow()))
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
self.value_spinbutton.connect_output(clone!(
|
||||||
|
#[strong(rename_to = value_ratio)]
|
||||||
|
self.value_ratio,
|
||||||
|
move |spin| {
|
||||||
|
let display_value = spin.value() * *value_ratio.borrow();
|
||||||
|
spin.set_text(&display_value.to_string());
|
||||||
|
glib::Propagation::Stop
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetImpl for AdjustmentRow {}
|
||||||
|
}
|
@ -10,7 +10,7 @@ glib::wrapper! {
|
|||||||
|
|
||||||
impl GpuStatsSection {
|
impl GpuStatsSection {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Object::builder().build()
|
Object::builder().property("vram_clock_ratio", 1.0).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_stats(&self, stats: &DeviceStats) {
|
pub fn set_stats(&self, stats: &DeviceStats) {
|
||||||
@ -28,9 +28,12 @@ impl GpuStatsSection {
|
|||||||
));
|
));
|
||||||
|
|
||||||
let clockspeed = stats.clockspeed;
|
let clockspeed = stats.clockspeed;
|
||||||
self.set_core_clock(format_clockspeed(clockspeed.gpu_clockspeed));
|
self.set_core_clock(format_clockspeed(clockspeed.gpu_clockspeed, 1.0));
|
||||||
self.set_current_core_clock(format_current_gfxclk(clockspeed.current_gfxclk));
|
self.set_current_core_clock(format_current_gfxclk(clockspeed.current_gfxclk));
|
||||||
self.set_vram_clock(format_clockspeed(clockspeed.vram_clockspeed));
|
self.set_vram_clock(format_clockspeed(
|
||||||
|
clockspeed.vram_clockspeed,
|
||||||
|
self.vram_clock_ratio(),
|
||||||
|
));
|
||||||
|
|
||||||
let voltage = format!("{:.3} V", stats.voltage.gpu.unwrap_or(0) as f64 / 1000f64);
|
let voltage = format!("{:.3} V", stats.voltage.gpu.unwrap_or(0) as f64 / 1000f64);
|
||||||
self.set_voltage(voltage);
|
self.set_voltage(voltage);
|
||||||
@ -99,7 +102,7 @@ mod imp {
|
|||||||
},
|
},
|
||||||
CompositeTemplate,
|
CompositeTemplate,
|
||||||
};
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::{Cell, RefCell};
|
||||||
|
|
||||||
#[derive(CompositeTemplate, Default, Properties)]
|
#[derive(CompositeTemplate, Default, Properties)]
|
||||||
#[properties(wrapper_type = super::GpuStatsSection)]
|
#[properties(wrapper_type = super::GpuStatsSection)]
|
||||||
@ -125,6 +128,9 @@ mod imp {
|
|||||||
vram_usage_text: RefCell<String>,
|
vram_usage_text: RefCell<String>,
|
||||||
#[property(get, set)]
|
#[property(get, set)]
|
||||||
throttling: RefCell<String>,
|
throttling: RefCell<String>,
|
||||||
|
|
||||||
|
#[property(get, set)]
|
||||||
|
vram_clock_ratio: Cell<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
@ -150,8 +156,8 @@ mod imp {
|
|||||||
impl BoxImpl for GpuStatsSection {}
|
impl BoxImpl for GpuStatsSection {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_clockspeed(value: Option<u64>) -> String {
|
fn format_clockspeed(value: Option<u64>, ratio: f64) -> String {
|
||||||
format!("{:.3} GHz", value.unwrap_or(0) as f64 / 1000.0)
|
format!("{:.3} GHz", value.unwrap_or(0) as f64 / 1000.0 * ratio)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_current_gfxclk(value: Option<u16>) -> String {
|
fn format_current_gfxclk(value: Option<u16>) -> String {
|
||||||
@ -161,7 +167,7 @@ fn format_current_gfxclk(value: Option<u16>) -> String {
|
|||||||
if v == u16::MAX {
|
if v == u16::MAX {
|
||||||
"N/A".to_string()
|
"N/A".to_string()
|
||||||
} else {
|
} else {
|
||||||
format_clockspeed(Some(v as u64))
|
format_clockspeed(Some(v as u64), 1.0)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
"N/A".to_string()
|
"N/A".to_string()
|
||||||
|
@ -12,7 +12,7 @@ use clocks_frame::ClocksFrame;
|
|||||||
use gpu_stats_section::GpuStatsSection;
|
use gpu_stats_section::GpuStatsSection;
|
||||||
use gtk::*;
|
use gtk::*;
|
||||||
use gtk::{glib::clone, prelude::*};
|
use gtk::{glib::clone, prelude::*};
|
||||||
use lact_client::schema::{DeviceStats, SystemInfo};
|
use lact_client::schema::{DeviceInfo, DeviceStats, SystemInfo};
|
||||||
use performance_frame::PerformanceFrame;
|
use performance_frame::PerformanceFrame;
|
||||||
// use power_cap_frame::PowerCapFrame;
|
// use power_cap_frame::PowerCapFrame;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -113,6 +113,17 @@ impl OcPage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_info(&self, info: &DeviceInfo) {
|
||||||
|
let vram_clock_ratio = info
|
||||||
|
.drm_info
|
||||||
|
.as_ref()
|
||||||
|
.map(|info| info.vram_clock_ratio)
|
||||||
|
.unwrap_or(1.0);
|
||||||
|
|
||||||
|
self.stats_section.set_vram_clock_ratio(vram_clock_ratio);
|
||||||
|
self.clocks_frame.set_vram_clock_ratio(vram_clock_ratio);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_clocks_table(&self, table: Option<ClocksTableGen>) {
|
pub fn set_clocks_table(&self, table: Option<ClocksTableGen>) {
|
||||||
match table {
|
match table {
|
||||||
Some(table) => match self.clocks_frame.set_table(table) {
|
Some(table) => match self.clocks_frame.set_table(table) {
|
||||||
|
37
lact-gui/ui/oc_page/clocks_frame/adjustment_row.blp
Normal file
37
lact-gui/ui/oc_page/clocks_frame/adjustment_row.blp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
|
||||||
|
template $AdjustmentRow: Widget {
|
||||||
|
Label label {
|
||||||
|
label: bind template.title;
|
||||||
|
visible: bind template.visible;
|
||||||
|
halign: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale scale {
|
||||||
|
adjustment: adjustment;
|
||||||
|
orientation: horizontal;
|
||||||
|
hexpand: true;
|
||||||
|
digits: 0;
|
||||||
|
round-digits: 0;
|
||||||
|
value-pos: right;
|
||||||
|
margin-start: 5;
|
||||||
|
margin-end: 5;
|
||||||
|
visible: bind template.visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuButton value_button {
|
||||||
|
popover: Popover {
|
||||||
|
child: SpinButton value_spinbutton {
|
||||||
|
adjustment: adjustment;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
direction: none;
|
||||||
|
visible: bind template.visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$OcAdjustment adjustment {
|
||||||
|
step-increment: 1;
|
||||||
|
page-increment: 10;
|
||||||
|
}
|
@ -100,6 +100,7 @@ pub struct DrmInfo {
|
|||||||
pub chip_class: String,
|
pub chip_class: String,
|
||||||
pub compute_units: u32,
|
pub compute_units: u32,
|
||||||
pub vram_type: String,
|
pub vram_type: String,
|
||||||
|
pub vram_clock_ratio: f64,
|
||||||
pub vram_bit_width: u32,
|
pub vram_bit_width: u32,
|
||||||
pub vram_max_bw: String,
|
pub vram_max_bw: String,
|
||||||
pub l1_cache_per_cu: u32,
|
pub l1_cache_per_cu: u32,
|
||||||
|
Loading…
Reference in New Issue
Block a user