mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
Implement clock settings
This commit is contained in:
@@ -231,6 +231,31 @@ impl DaemonConnection {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_gpu_max_power_state(
|
||||
&self,
|
||||
gpu_id: u32,
|
||||
clockspeed: i64,
|
||||
voltage: Option<i64>,
|
||||
) -> Result<(), DaemonError> {
|
||||
let mut s = UnixStream::connect(SOCK_PATH).unwrap();
|
||||
s.write_all(
|
||||
&bincode::serialize(&Action::SetGPUMaxPowerState(gpu_id, clockspeed, voltage))
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
s.shutdown(std::net::Shutdown::Write)
|
||||
.expect("Could not shut down");
|
||||
let mut buffer = Vec::<u8>::new();
|
||||
s.read_to_end(&mut buffer).unwrap();
|
||||
|
||||
let result: Result<DaemonResponse, DaemonError> = bincode::deserialize(&buffer).unwrap();
|
||||
|
||||
match result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_vram_power_state(
|
||||
&self,
|
||||
gpu_id: u32,
|
||||
@@ -257,6 +282,30 @@ impl DaemonConnection {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_vram_max_clock(
|
||||
&self,
|
||||
gpu_id: u32,
|
||||
clockspeed: i64,
|
||||
) -> Result<(), DaemonError> {
|
||||
let mut s = UnixStream::connect(SOCK_PATH).unwrap();
|
||||
s.write_all(
|
||||
&bincode::serialize(&Action::SetVRAMMaxClock(gpu_id, clockspeed))
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
s.shutdown(std::net::Shutdown::Write)
|
||||
.expect("Could not shut down");
|
||||
let mut buffer = Vec::<u8>::new();
|
||||
s.read_to_end(&mut buffer).unwrap();
|
||||
|
||||
let result: Result<DaemonResponse, DaemonError> = bincode::deserialize(&buffer).unwrap();
|
||||
|
||||
match result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn commit_gpu_power_states(&self, gpu_id: u32) -> Result<(), DaemonError> {
|
||||
let mut s = UnixStream::connect(SOCK_PATH).unwrap();
|
||||
s.write_all(&bincode::serialize(&Action::CommitGPUPowerStates(gpu_id)).unwrap())
|
||||
|
||||
@@ -132,7 +132,6 @@ pub struct GpuInfo {
|
||||
pub clocks_table: Option<ClocksTable>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct GpuController {
|
||||
pub hw_path: PathBuf,
|
||||
@@ -199,10 +198,10 @@ impl GpuController {
|
||||
path: self.hw_path.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn get_info(&self) -> GpuInfo {
|
||||
let mut info = self.gpu_info.clone();
|
||||
|
||||
|
||||
info.power_profile = match self.get_power_profile() {
|
||||
Ok(p) => Some(p),
|
||||
Err(_) => None,
|
||||
@@ -601,6 +600,34 @@ impl GpuController {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_gpu_max_power_state(
|
||||
&mut self,
|
||||
clockspeed: i64,
|
||||
voltage: Option<i64>,
|
||||
) -> Result<(), GpuControllerError> {
|
||||
let profile = {
|
||||
let gpu_power_levels = self.get_clocks_table()?.gpu_power_levels;
|
||||
*gpu_power_levels.iter().next_back().unwrap().0
|
||||
};
|
||||
|
||||
let mut line = format!("s {} {}", profile, clockspeed);
|
||||
|
||||
if let Some(voltage) = voltage {
|
||||
line.push_str(&format!(" {}", voltage));
|
||||
}
|
||||
line.push_str("\n");
|
||||
|
||||
log::info!("Writing {} to pp_od_clk_voltage", line);
|
||||
|
||||
fs::write(self.hw_path.join("pp_od_clk_voltage"), line)?;
|
||||
|
||||
self.config
|
||||
.gpu_power_states
|
||||
.insert(profile, (clockspeed, voltage.unwrap()));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_vram_power_state(
|
||||
&mut self,
|
||||
num: u32,
|
||||
@@ -626,6 +653,26 @@ impl GpuController {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_vram_max_clockspeed(&mut self, clockspeed: i64) -> Result<(), GpuControllerError> {
|
||||
let (profile, voltage) = {
|
||||
let mem_power_levels = self.get_clocks_table().unwrap().mem_power_levels;
|
||||
let level = mem_power_levels.iter().next_back().unwrap();
|
||||
(*level.0, level.1.1)
|
||||
};
|
||||
|
||||
let line = format!("m {} {} {}\n", profile, clockspeed, voltage);
|
||||
|
||||
log::info!("Writing {} to pp_od_clk_voltage", line);
|
||||
|
||||
fs::write(self.hw_path.join("pp_od_clk_voltage"), line)?;
|
||||
|
||||
self.config
|
||||
.vram_power_states
|
||||
.insert(profile, (clockspeed, voltage));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn commit_gpu_power_states(&mut self) -> Result<(), GpuControllerError> {
|
||||
fs::write(self.hw_path.join("pp_od_clk_voltage"), b"c\n")?;
|
||||
Ok(())
|
||||
|
||||
@@ -5,15 +5,18 @@ pub mod hw_mon;
|
||||
|
||||
use config::{Config, GpuConfig};
|
||||
use gpu_controller::PowerProfile;
|
||||
use rand::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::{BTreeMap, HashMap}, fs};
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
use std::process::Command;
|
||||
use std::{
|
||||
collections::{BTreeMap, HashMap},
|
||||
fs,
|
||||
};
|
||||
use std::{
|
||||
io::{Read, Write},
|
||||
path::PathBuf,
|
||||
};
|
||||
use rand::prelude::*;
|
||||
|
||||
use crate::gpu_controller::GpuController;
|
||||
|
||||
@@ -40,6 +43,8 @@ pub enum Action {
|
||||
SetPowerProfile(u32, PowerProfile),
|
||||
SetGPUPowerState(u32, u32, i64, Option<i64>),
|
||||
SetVRAMPowerState(u32, u32, i64, Option<i64>),
|
||||
SetGPUMaxPowerState(u32, i64, Option<i64>),
|
||||
SetVRAMMaxClock(u32, i64),
|
||||
CommitGPUPowerStates(u32),
|
||||
ResetGPUPowerStates(u32),
|
||||
Shutdown,
|
||||
@@ -58,7 +63,7 @@ impl Daemon {
|
||||
.arg(SOCK_PATH)
|
||||
.output()
|
||||
.expect("Failed to chmod");
|
||||
|
||||
|
||||
Command::new("chown")
|
||||
.arg("nobody:wheel")
|
||||
.arg(SOCK_PATH)
|
||||
@@ -91,17 +96,23 @@ impl Daemon {
|
||||
}
|
||||
}*/
|
||||
|
||||
'entries: for entry in fs::read_dir("/sys/class/drm").expect("Could not open /sys/class/drm") {
|
||||
'entries: for entry in
|
||||
fs::read_dir("/sys/class/drm").expect("Could not open /sys/class/drm")
|
||||
{
|
||||
let entry = entry.unwrap();
|
||||
if entry.file_name().len() == 5 {
|
||||
if entry.file_name().to_str().unwrap().split_at(4).0 == "card" {
|
||||
log::info!("Initializing {:?}", entry.path());
|
||||
|
||||
let mut controller = GpuController::new(entry.path().join("device"), GpuConfig::new());
|
||||
let mut controller =
|
||||
GpuController::new(entry.path().join("device"), GpuConfig::new());
|
||||
let gpu_info = &controller.get_info();
|
||||
|
||||
for (id, (gpu_identifier, gpu_config)) in &config.gpu_configs {
|
||||
if gpu_info.pci_slot == gpu_identifier.pci_id && gpu_info.vendor_data.card_model == gpu_identifier.card_model && gpu_info.vendor_data.gpu_model == gpu_identifier.gpu_model {
|
||||
if gpu_info.pci_slot == gpu_identifier.pci_id
|
||||
&& gpu_info.vendor_data.card_model == gpu_identifier.card_model
|
||||
&& gpu_info.vendor_data.gpu_model == gpu_identifier.gpu_model
|
||||
{
|
||||
controller.load_config(&gpu_config);
|
||||
gpu_controllers.insert(id.clone(), controller);
|
||||
log::info!("already known");
|
||||
@@ -113,7 +124,9 @@ impl Daemon {
|
||||
|
||||
let id: u32 = random();
|
||||
|
||||
config.gpu_configs.insert(id, (controller.get_identifier(), controller.get_config()));
|
||||
config
|
||||
.gpu_configs
|
||||
.insert(id, (controller.get_identifier(), controller.get_config()));
|
||||
gpu_controllers.insert(id, controller);
|
||||
}
|
||||
}
|
||||
@@ -166,7 +179,7 @@ impl Daemon {
|
||||
gpus.insert(*id, controller.get_info().vendor_data.gpu_model.clone());
|
||||
}
|
||||
Ok(DaemonResponse::Gpus(gpus))
|
||||
},
|
||||
}
|
||||
Action::GetStats(i) => match self.gpu_controllers.get(&i) {
|
||||
Some(controller) => match controller.get_stats() {
|
||||
Ok(stats) => Ok(DaemonResponse::GpuStats(stats)),
|
||||
@@ -175,27 +188,35 @@ impl Daemon {
|
||||
None => Err(DaemonError::InvalidID),
|
||||
},
|
||||
Action::GetInfo(i) => match self.gpu_controllers.get(&i) {
|
||||
Some(controller) => Ok(DaemonResponse::GpuInfo(controller.get_info().clone())),
|
||||
Some(controller) => {
|
||||
Ok(DaemonResponse::GpuInfo(controller.get_info().clone()))
|
||||
}
|
||||
None => Err(DaemonError::InvalidID),
|
||||
},
|
||||
Action::StartFanControl(i) => match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => match controller.start_fan_control() {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(i, (controller.get_identifier(), controller.get_config()));
|
||||
self.config.gpu_configs.insert(
|
||||
i,
|
||||
(controller.get_identifier(), controller.get_config()),
|
||||
);
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
},
|
||||
}
|
||||
Err(_) => Err(DaemonError::HWMonError),
|
||||
}
|
||||
},
|
||||
None => Err(DaemonError::InvalidID),
|
||||
},
|
||||
Action::StopFanControl(i) => match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => match controller.stop_fan_control() {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(i, (controller.get_identifier(), controller.get_config()));
|
||||
self.config.gpu_configs.insert(
|
||||
i,
|
||||
(controller.get_identifier(), controller.get_config()),
|
||||
);
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
},
|
||||
}
|
||||
Err(_) => Err(DaemonError::HWMonError),
|
||||
},
|
||||
None => Err(DaemonError::InvalidID),
|
||||
@@ -204,109 +225,158 @@ impl Daemon {
|
||||
Some(controller) => match controller.get_fan_control() {
|
||||
Ok(info) => Ok(DaemonResponse::FanControlInfo(info)),
|
||||
Err(_) => Err(DaemonError::HWMonError),
|
||||
}
|
||||
},
|
||||
None => Err(DaemonError::InvalidID),
|
||||
}
|
||||
},
|
||||
Action::SetFanCurve(i, curve) => match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => {
|
||||
|
||||
match controller.set_fan_curve(curve) {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(i, (controller.get_identifier(), controller.get_config()));
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
},
|
||||
Err(_) => Err(DaemonError::HWMonError),
|
||||
Some(controller) => match controller.set_fan_curve(curve) {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(
|
||||
i,
|
||||
(controller.get_identifier(), controller.get_config()),
|
||||
);
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
}
|
||||
|
||||
Err(_) => Err(DaemonError::HWMonError),
|
||||
},
|
||||
None => Err(DaemonError::InvalidID),
|
||||
}
|
||||
},
|
||||
Action::SetPowerCap(i, cap) => match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => {
|
||||
match controller.set_power_cap(cap) {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(i, (controller.get_identifier(), controller.get_config()));
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
},
|
||||
Err(_) => Err(DaemonError::HWMonError),
|
||||
Some(controller) => match controller.set_power_cap(cap) {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(
|
||||
i,
|
||||
(controller.get_identifier(), controller.get_config()),
|
||||
);
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
}
|
||||
Err(_) => Err(DaemonError::HWMonError),
|
||||
},
|
||||
None => Err(DaemonError::InvalidID),
|
||||
}
|
||||
},
|
||||
Action::GetPowerCap(i) => match self.gpu_controllers.get(&i) {
|
||||
Some(controller) => match controller.get_power_cap() {
|
||||
Ok(cap) => Ok(DaemonResponse::PowerCap(cap)),
|
||||
Err(_) => Err(DaemonError::HWMonError),
|
||||
}
|
||||
},
|
||||
None => Err(DaemonError::InvalidID),
|
||||
}
|
||||
},
|
||||
Action::SetPowerProfile(i, profile) => match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => {
|
||||
match controller.set_power_profile(profile) {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(i, (controller.get_identifier(), controller.get_config()));
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
},
|
||||
Err(_) => Err(DaemonError::ControllerError)
|
||||
Some(controller) => match controller.set_power_profile(profile) {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(
|
||||
i,
|
||||
(controller.get_identifier(), controller.get_config()),
|
||||
);
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
}
|
||||
Err(_) => Err(DaemonError::ControllerError),
|
||||
},
|
||||
None => Err(DaemonError::InvalidID),
|
||||
}
|
||||
Action::SetGPUPowerState(i, num, clockspeed, voltage) => match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => {
|
||||
match controller.set_gpu_power_state(num, clockspeed, voltage) {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(i, (controller.get_identifier(), controller.get_config()));
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
},
|
||||
Err(_) => Err(DaemonError::ControllerError)
|
||||
},
|
||||
Action::SetGPUPowerState(i, num, clockspeed, voltage) => {
|
||||
match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => {
|
||||
match controller.set_gpu_power_state(num, clockspeed, voltage) {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(
|
||||
i,
|
||||
(controller.get_identifier(), controller.get_config()),
|
||||
);
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
}
|
||||
Err(_) => Err(DaemonError::ControllerError),
|
||||
}
|
||||
}
|
||||
},
|
||||
None => Err(DaemonError::InvalidID)
|
||||
None => Err(DaemonError::InvalidID),
|
||||
}
|
||||
}
|
||||
Action::SetVRAMPowerState(i, num, clockspeed, voltage) => match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => {
|
||||
match controller.set_vram_power_state(num, clockspeed, voltage) {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(i, (controller.get_identifier(), controller.get_config()));
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
},
|
||||
Err(_) => Err(DaemonError::ControllerError)
|
||||
Action::SetVRAMPowerState(i, num, clockspeed, voltage) => {
|
||||
match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => {
|
||||
match controller.set_vram_power_state(num, clockspeed, voltage) {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(
|
||||
i,
|
||||
(controller.get_identifier(), controller.get_config()),
|
||||
);
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
}
|
||||
Err(_) => Err(DaemonError::ControllerError),
|
||||
}
|
||||
}
|
||||
},
|
||||
None => Err(DaemonError::InvalidID)
|
||||
None => Err(DaemonError::InvalidID),
|
||||
}
|
||||
}
|
||||
Action::SetGPUMaxPowerState(i, clockspeed, voltage) => {
|
||||
match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => {
|
||||
match controller.set_gpu_max_power_state(clockspeed, voltage) {
|
||||
Ok(()) => {
|
||||
self.config.gpu_configs.insert(
|
||||
i,
|
||||
(controller.get_identifier(), controller.get_config()),
|
||||
);
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
}
|
||||
Err(_) => Err(DaemonError::ControllerError),
|
||||
}
|
||||
}
|
||||
None => Err(DaemonError::InvalidID),
|
||||
}
|
||||
}
|
||||
Action::SetVRAMMaxClock(i, clockspeed) => {
|
||||
match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => {
|
||||
match controller.set_vram_max_clockspeed(clockspeed) {
|
||||
Ok(()) => {
|
||||
self.config.gpu_configs.insert(
|
||||
i,
|
||||
(controller.get_identifier(), controller.get_config()),
|
||||
);
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
}
|
||||
Err(_) => Err(DaemonError::ControllerError),
|
||||
}
|
||||
}
|
||||
None => Err(DaemonError::InvalidID),
|
||||
}
|
||||
}
|
||||
Action::CommitGPUPowerStates(i) => match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => {
|
||||
match controller.commit_gpu_power_states() {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(i, (controller.get_identifier(), controller.get_config()));
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
},
|
||||
Err(_) => Err(DaemonError::ControllerError)
|
||||
Some(controller) => match controller.commit_gpu_power_states() {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(
|
||||
i,
|
||||
(controller.get_identifier(), controller.get_config()),
|
||||
);
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
}
|
||||
Err(_) => Err(DaemonError::ControllerError),
|
||||
},
|
||||
None => Err(DaemonError::InvalidID)
|
||||
}
|
||||
None => Err(DaemonError::InvalidID),
|
||||
},
|
||||
Action::ResetGPUPowerStates(i) => match self.gpu_controllers.get_mut(&i) {
|
||||
Some(controller) => {
|
||||
match controller.reset_gpu_power_states() {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(i, (controller.get_identifier(), controller.get_config()));
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
},
|
||||
Err(_) => Err(DaemonError::ControllerError)
|
||||
Some(controller) => match controller.reset_gpu_power_states() {
|
||||
Ok(_) => {
|
||||
self.config.gpu_configs.insert(
|
||||
i,
|
||||
(controller.get_identifier(), controller.get_config()),
|
||||
);
|
||||
self.config.save().unwrap();
|
||||
Ok(DaemonResponse::OK)
|
||||
}
|
||||
Err(_) => Err(DaemonError::ControllerError),
|
||||
},
|
||||
None => Err(DaemonError::InvalidID)
|
||||
}
|
||||
None => Err(DaemonError::InvalidID),
|
||||
},
|
||||
Action::Shutdown => {
|
||||
for (id, controller) in &mut self.gpu_controllers {
|
||||
#[allow(unused_must_use)]
|
||||
@@ -315,7 +385,14 @@ impl Daemon {
|
||||
controller.commit_gpu_power_states();
|
||||
controller.set_power_profile(PowerProfile::Auto);
|
||||
|
||||
if self.config.gpu_configs.get(id).unwrap().1.fan_control_enabled {
|
||||
if self
|
||||
.config
|
||||
.gpu_configs
|
||||
.get(id)
|
||||
.unwrap()
|
||||
.1
|
||||
.fan_control_enabled
|
||||
{
|
||||
controller.stop_fan_control();
|
||||
}
|
||||
}
|
||||
@@ -326,17 +403,18 @@ impl Daemon {
|
||||
};
|
||||
|
||||
log::trace!("Responding");
|
||||
stream.write_all(&bincode::serialize(&response).unwrap()).expect("Failed writing response");
|
||||
stream
|
||||
.write_all(&bincode::serialize(&response).unwrap())
|
||||
.expect("Failed writing response");
|
||||
//stream
|
||||
// .shutdown(std::net::Shutdown::Write)
|
||||
// .expect("Could not shut down");
|
||||
log::trace!("Finished responding");
|
||||
},
|
||||
}
|
||||
Err(_) => {
|
||||
println!("Failed deserializing action");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,6 +105,25 @@ impl App {
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let app = self.clone();
|
||||
let current_gpu_id = current_gpu_id.clone();
|
||||
|
||||
self.root_stack.oc_page.connect_clocks_reset(move || {
|
||||
log::info!("Resetting clocks, but not applying");
|
||||
|
||||
let gpu_id = current_gpu_id.load(Ordering::SeqCst);
|
||||
|
||||
app.daemon_connection
|
||||
.reset_gpu_power_states(gpu_id)
|
||||
.expect("Failed to reset clocks");
|
||||
|
||||
app.set_info(gpu_id);
|
||||
|
||||
app.apply_revealer.show();
|
||||
})
|
||||
}
|
||||
|
||||
// Apply settings
|
||||
{
|
||||
let current_gpu_id = current_gpu_id.clone();
|
||||
@@ -133,14 +152,28 @@ impl App {
|
||||
.expect("Failed to set fan curve");
|
||||
}
|
||||
|
||||
{
|
||||
let power_profile = app.root_stack.oc_page.get_power_profile();
|
||||
if let Some(clocks_settings) = app.root_stack.oc_page.get_clocks() {
|
||||
app.daemon_connection
|
||||
.set_gpu_max_power_state(
|
||||
gpu_id,
|
||||
clocks_settings.gpu_clock,
|
||||
Some(clocks_settings.gpu_voltage),
|
||||
)
|
||||
.expect("Failed to set GPU clockspeed/voltage");
|
||||
|
||||
if let Some(profile) = power_profile {
|
||||
app.daemon_connection
|
||||
.set_power_profile(gpu_id, profile)
|
||||
.expect("Failed to set power profile");
|
||||
}
|
||||
app.daemon_connection
|
||||
.set_vram_max_clock(gpu_id, clocks_settings.vram_clock)
|
||||
.expect("Failed to set VRAM Clock");
|
||||
|
||||
app.daemon_connection
|
||||
.commit_gpu_power_states(gpu_id)
|
||||
.expect("Failed to commit power states");
|
||||
}
|
||||
|
||||
if let Some(profile) = app.root_stack.oc_page.get_power_profile() {
|
||||
app.daemon_connection
|
||||
.set_power_profile(gpu_id, profile)
|
||||
.expect("Failed to set power profile");
|
||||
}
|
||||
|
||||
app.set_info(gpu_id);
|
||||
@@ -158,6 +191,9 @@ impl App {
|
||||
|
||||
self.root_stack.info_page.set_info(&gpu_info);
|
||||
|
||||
log::trace!("Setting clocks");
|
||||
self.root_stack.oc_page.set_clocks(&gpu_info.clocks_table);
|
||||
|
||||
log::trace!("Setting power profile {:?}", gpu_info.power_profile);
|
||||
self.root_stack
|
||||
.oc_page
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
mod clocks_frame;
|
||||
mod power_profile_frame;
|
||||
mod stats_grid;
|
||||
|
||||
use daemon::gpu_controller::{GpuStats, PowerProfile};
|
||||
use clocks_frame::ClocksSettings;
|
||||
use daemon::gpu_controller::{ClocksTable, GpuStats, PowerProfile};
|
||||
use gtk::*;
|
||||
|
||||
use power_profile_frame::PowerProfileFrame;
|
||||
use stats_grid::StatsGrid;
|
||||
|
||||
use self::clocks_frame::ClocksFrame;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OcPage {
|
||||
pub container: Box,
|
||||
stats_grid: StatsGrid,
|
||||
power_profile_frame: PowerProfileFrame,
|
||||
clocks_frame: ClocksFrame,
|
||||
}
|
||||
|
||||
impl OcPage {
|
||||
@@ -20,28 +25,49 @@ impl OcPage {
|
||||
|
||||
let stats_grid = StatsGrid::new();
|
||||
|
||||
container.pack_start(&stats_grid.container, false, true, 10);
|
||||
container.pack_start(&stats_grid.container, false, true, 5);
|
||||
|
||||
let power_profile_frame = PowerProfileFrame::new();
|
||||
|
||||
container.pack_start(&power_profile_frame.container, false, true, 10);
|
||||
container.pack_start(&power_profile_frame.container, false, true, 0);
|
||||
|
||||
let clocks_frame = ClocksFrame::new();
|
||||
|
||||
container.pack_start(&clocks_frame.container, false, true, 0);
|
||||
|
||||
Self {
|
||||
container,
|
||||
stats_grid,
|
||||
power_profile_frame,
|
||||
clocks_frame,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_stats(&self, stats: &GpuStats) {
|
||||
self.stats_grid.set_stats(stats);
|
||||
}
|
||||
|
||||
|
||||
pub fn connect_clocks_reset<F: Fn() + 'static + Clone>(&self, f: F) {
|
||||
self.clocks_frame.connect_clocks_reset(move || {
|
||||
f();
|
||||
});
|
||||
}
|
||||
|
||||
pub fn connect_settings_changed<F: Fn() + 'static>(&self, f: F) {
|
||||
self.power_profile_frame
|
||||
.connect_power_profile_changed(move || {
|
||||
|
||||
pub fn connect_settings_changed<F: Fn() + 'static + Clone>(&self, f: F) {
|
||||
{
|
||||
let f = f.clone();
|
||||
self.power_profile_frame
|
||||
.connect_power_profile_changed(move || {
|
||||
f();
|
||||
});
|
||||
}
|
||||
{
|
||||
self.clocks_frame.connect_clocks_changed(move || {
|
||||
f();
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_power_profile(&self, profile: &Option<PowerProfile>) {
|
||||
@@ -59,5 +85,20 @@ impl OcPage {
|
||||
true => Some(self.power_profile_frame.get_selected_power_profile()),
|
||||
false => None,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn set_clocks(&self, clocks_table: &Option<ClocksTable>) {
|
||||
match clocks_table {
|
||||
Some(clocks_table) => self.clocks_frame.set_clocks(clocks_table),
|
||||
None => self.clocks_frame.hide(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_clocks(&self) -> Option<ClocksSettings> {
|
||||
match self.clocks_frame.get_visibility() {
|
||||
true => Some(self.clocks_frame.get_settings()),
|
||||
false => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
193
gui/src/app/root_stack/oc_page/clocks_frame.rs
Normal file
193
gui/src/app/root_stack/oc_page/clocks_frame.rs
Normal file
@@ -0,0 +1,193 @@
|
||||
use daemon::gpu_controller::ClocksTable;
|
||||
use gtk::*;
|
||||
|
||||
pub struct ClocksSettings {
|
||||
pub gpu_clock: i64,
|
||||
pub vram_clock: i64,
|
||||
pub gpu_voltage: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ClocksFrame {
|
||||
pub container: Frame,
|
||||
gpu_clock_adjustment: Adjustment,
|
||||
gpu_voltage_adjustment: Adjustment,
|
||||
vram_clock_adjustment: Adjustment,
|
||||
apply_button: Button,
|
||||
}
|
||||
|
||||
impl ClocksFrame {
|
||||
pub fn new() -> Self {
|
||||
let container = Frame::new(None);
|
||||
|
||||
container.set_margin_start(10);
|
||||
container.set_margin_end(10);
|
||||
|
||||
container.set_shadow_type(ShadowType::None);
|
||||
|
||||
container.set_label_widget(Some(&{
|
||||
let label = Label::new(None);
|
||||
label.set_markup("<span font_desc='11'><b>Maximum Clocks</b></span>");
|
||||
label
|
||||
}));
|
||||
container.set_label_align(0.2, 0.0);
|
||||
|
||||
let gpu_clock_adjustment = Adjustment::new(0.0, 0.0, 0.0, 1.0, 0.0, 0.0);
|
||||
|
||||
let gpu_voltage_adjustment = Adjustment::new(1.0, 0.0, 0.0, 0.05, 0.0, 0.0);
|
||||
|
||||
let vram_clock_adjustment = Adjustment::new(0.0, 0.0, 0.0, 1.0, 0.0, 0.0);
|
||||
|
||||
let root_grid = Grid::new();
|
||||
|
||||
root_grid.set_row_spacing(5);
|
||||
root_grid.set_column_spacing(10);
|
||||
|
||||
{
|
||||
let gpu_clock_scale = Scale::new(Orientation::Horizontal, Some(&gpu_clock_adjustment));
|
||||
|
||||
gpu_clock_scale.set_hexpand(true); // Affects the grid column and all scales
|
||||
|
||||
gpu_clock_scale.set_value_pos(PositionType::Right);
|
||||
|
||||
root_grid.attach(&gpu_clock_scale, 1, 0, 1, 1);
|
||||
|
||||
root_grid.attach_next_to(
|
||||
&Label::new(Some("GPU Clock (MHz)")),
|
||||
Some(&gpu_clock_scale),
|
||||
PositionType::Left,
|
||||
1,
|
||||
1,
|
||||
);
|
||||
|
||||
let gpu_voltage_scale =
|
||||
Scale::new(Orientation::Horizontal, Some(&gpu_voltage_adjustment));
|
||||
|
||||
gpu_voltage_scale.set_value_pos(PositionType::Right);
|
||||
|
||||
gpu_voltage_scale.set_digits(3);
|
||||
gpu_voltage_scale.set_round_digits(3);
|
||||
|
||||
root_grid.attach(&gpu_voltage_scale, 1, 1, 1, 1);
|
||||
|
||||
root_grid.attach_next_to(
|
||||
&Label::new(Some("GPU Voltage (V)")),
|
||||
Some(&gpu_voltage_scale),
|
||||
PositionType::Left,
|
||||
1,
|
||||
1,
|
||||
);
|
||||
|
||||
let vram_clock_scale =
|
||||
Scale::new(Orientation::Horizontal, Some(&vram_clock_adjustment));
|
||||
|
||||
vram_clock_scale.set_value_pos(PositionType::Right);
|
||||
|
||||
root_grid.attach(&vram_clock_scale, 1, 2, 1, 1);
|
||||
|
||||
root_grid.attach_next_to(
|
||||
&Label::new(Some("VRAM Clock (MHz)")),
|
||||
Some(&vram_clock_scale),
|
||||
PositionType::Left,
|
||||
1,
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
let apply_button = Button::new();
|
||||
|
||||
{
|
||||
apply_button.set_label("Reset");
|
||||
|
||||
root_grid.attach(&apply_button, 0, 3, 2, 1);
|
||||
|
||||
container.add(&root_grid);
|
||||
}
|
||||
|
||||
Self {
|
||||
container,
|
||||
gpu_clock_adjustment,
|
||||
gpu_voltage_adjustment,
|
||||
vram_clock_adjustment,
|
||||
apply_button,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_visibility(&self) -> bool {
|
||||
self.container.get_visible()
|
||||
}
|
||||
|
||||
pub fn set_clocks(&self, clocks_table: &ClocksTable) {
|
||||
self.gpu_clock_adjustment
|
||||
.set_lower(clocks_table.gpu_clocks_range.0 as f64);
|
||||
self.gpu_clock_adjustment
|
||||
.set_upper(clocks_table.gpu_clocks_range.1 as f64);
|
||||
|
||||
self.gpu_voltage_adjustment
|
||||
.set_lower(clocks_table.voltage_range.0 as f64 / 1000.0);
|
||||
self.gpu_voltage_adjustment
|
||||
.set_upper(clocks_table.voltage_range.1 as f64 / 1000.0);
|
||||
|
||||
self.vram_clock_adjustment
|
||||
.set_lower(clocks_table.mem_clocks_range.0 as f64);
|
||||
self.vram_clock_adjustment
|
||||
.set_upper(clocks_table.mem_clocks_range.1 as f64);
|
||||
|
||||
let (gpu_clockspeed, gpu_voltage) =
|
||||
clocks_table.gpu_power_levels.iter().next_back().unwrap().1;
|
||||
|
||||
self.gpu_clock_adjustment.set_value(*gpu_clockspeed as f64);
|
||||
|
||||
self.gpu_voltage_adjustment
|
||||
.set_value(*gpu_voltage as f64 / 1000.0);
|
||||
|
||||
let (vram_clockspeed, _) = clocks_table.mem_power_levels.iter().next_back().unwrap().1;
|
||||
|
||||
self.vram_clock_adjustment
|
||||
.set_value(*vram_clockspeed as f64);
|
||||
}
|
||||
|
||||
pub fn get_settings(&self) -> ClocksSettings {
|
||||
let gpu_clock = self.gpu_clock_adjustment.get_value() as i64;
|
||||
|
||||
let vram_clock = self.vram_clock_adjustment.get_value() as i64;
|
||||
|
||||
let gpu_voltage = (self.gpu_voltage_adjustment.get_value() * 1000.0) as i64;
|
||||
|
||||
ClocksSettings {
|
||||
gpu_clock,
|
||||
vram_clock,
|
||||
gpu_voltage,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect_clocks_reset<F: Fn() + 'static + Clone>(&self, f: F) {
|
||||
self.apply_button.connect_clicked(move |_| {
|
||||
f();
|
||||
});
|
||||
}
|
||||
|
||||
pub fn connect_clocks_changed<F: Fn() + 'static + Clone>(&self, f: F) {
|
||||
{
|
||||
let f = f.clone();
|
||||
self.gpu_clock_adjustment.connect_value_changed(move |_| {
|
||||
f();
|
||||
});
|
||||
}
|
||||
{
|
||||
let f = f.clone();
|
||||
self.vram_clock_adjustment.connect_value_changed(move |_| {
|
||||
f();
|
||||
});
|
||||
}
|
||||
{
|
||||
self.gpu_voltage_adjustment.connect_value_changed(move |_| {
|
||||
f();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hide(&self) {
|
||||
self.container.set_visible(false);
|
||||
}
|
||||
}
|
||||
@@ -30,9 +30,9 @@ impl StatsGrid {
|
||||
|
||||
{
|
||||
vram_usage_bar.set_orientation(Orientation::Horizontal);
|
||||
vram_usage_bar.set_value(0.5);
|
||||
vram_usage_bar.set_value(1.0);
|
||||
|
||||
vram_usage_label.set_text("512/1024 MiB");
|
||||
vram_usage_label.set_text("0/0 MiB");
|
||||
|
||||
vram_usage_overlay.add(&vram_usage_bar);
|
||||
vram_usage_overlay.add_overlay(&vram_usage_label);
|
||||
@@ -46,7 +46,7 @@ impl StatsGrid {
|
||||
|
||||
gpu_clock_box.pack_start(&Label::new(Some("GPU Clock:")), false, false, 2);
|
||||
|
||||
gpu_clock_label.set_markup("<b>0000MHz</b>");
|
||||
gpu_clock_label.set_markup("<b>0MHz</b>");
|
||||
|
||||
gpu_clock_box.pack_start(&gpu_clock_label, false, false, 2);
|
||||
|
||||
@@ -61,7 +61,7 @@ impl StatsGrid {
|
||||
|
||||
vram_clock_box.pack_start(&Label::new(Some("VRAM Clock:")), false, false, 2);
|
||||
|
||||
vram_clock_label.set_markup("<b>0000MHz</b>");
|
||||
vram_clock_label.set_markup("<b>0MHz</b>");
|
||||
|
||||
vram_clock_box.pack_start(&vram_clock_label, false, false, 2);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user