Improve memory clock selection for #140, fix dpm_performance enforcement check for GPU

This commit is contained in:
NGnius (Graham) 2024-01-27 18:44:43 -05:00
parent 622f161560
commit a1c44cdea7
19 changed files with 285 additions and 113 deletions

View file

@ -43,5 +43,5 @@ pub struct Gpu {
pub tdp: Option<u64>,
pub tdp_boost: Option<u64>,
pub clock_limits: Option<MinMax<u64>>,
pub slow_memory: bool,
pub memory_clock: Option<u64>,
}

View file

@ -16,35 +16,11 @@ impl Default for Base {
fn default() -> Self {
Base {
configs: vec![
super::Config {
name: "Steam Deck Custom".to_owned(),
conditions: super::Conditions {
dmi: None,
cpuinfo: Some("model name\t: AMD Custom APU (0405)|(0932)\n".to_owned()),
os: None,
command: None,
file_exists: Some("./limits_override.json".into()),
},
limits: super::Limits {
cpu: super::Limit {
provider: super::CpuLimitType::SteamDeckAdvance,
limits: super::GenericCpusLimit::default_for(super::CpuLimitType::SteamDeckAdvance),
},
gpu: super::Limit {
provider: super::GpuLimitType::SteamDeckAdvance,
limits: super::GenericGpuLimit::default_for(super::GpuLimitType::SteamDeckAdvance),
},
battery: super::Limit {
provider: super::BatteryLimitType::SteamDeckAdvance,
limits: super::GenericBatteryLimit::default_for(super::BatteryLimitType::SteamDeckAdvance),
},
}
},
super::Config {
name: "Steam Deck".to_owned(),
conditions: super::Conditions {
dmi: None,
cpuinfo: Some("model name\t: AMD Custom APU (0405)|(0932)\n".to_owned()),
cpuinfo: Some("model name\t: AMD Custom APU 0405\n".to_owned()),
os: None,
command: None,
file_exists: None,
@ -64,6 +40,30 @@ impl Default for Base {
},
}
},
super::Config {
name: "Steam Deck OLED".to_owned(),
conditions: super::Conditions {
dmi: None,
cpuinfo: Some("model name\t: AMD Custom APU 0932\n".to_owned()),
os: None,
command: None,
file_exists: None,
},
limits: super::Limits {
cpu: super::Limit {
provider: super::CpuLimitType::SteamDeck,
limits: super::GenericCpusLimit::default_for(super::CpuLimitType::SteamDeck),
},
gpu: super::Limit {
provider: super::GpuLimitType::SteamDeck,
limits: super::GenericGpuLimit::default_for(super::GpuLimitType::SteamDeckOLED),
},
battery: super::Limit {
provider: super::BatteryLimitType::SteamDeck,
limits: super::GenericBatteryLimit::default_for(super::BatteryLimitType::SteamDeck),
},
}
},
super::Config {
name: "AMD R3 2300U".to_owned(),
conditions: super::Conditions {

View file

@ -8,6 +8,8 @@ pub enum GpuLimitType {
SteamDeck,
#[serde(rename = "GabeBoyAdvance", alias = "SteamDeckAdvance")]
SteamDeckAdvance,
#[serde(rename = "GabeBoy101", alias = "SteamDeckOLED")]
SteamDeckOLED,
Generic,
GenericAMD,
Unknown,
@ -27,6 +29,8 @@ pub struct GenericGpuLimit {
pub clock_min: Option<RangeLimit<u64>>,
pub clock_max: Option<RangeLimit<u64>>,
pub clock_step: Option<u64>,
pub memory_clock: Option<RangeLimit<u64>>,
pub memory_clock_step: Option<u64>,
pub skip_resume_reclock: bool,
}
@ -34,6 +38,7 @@ impl GenericGpuLimit {
pub fn default_for(t: GpuLimitType) -> Self {
match t {
GpuLimitType::SteamDeck | GpuLimitType::SteamDeckAdvance => Self::default_steam_deck(),
GpuLimitType::SteamDeckOLED => Self::default_steam_deck_oled(),
_t => Self::default(),
}
}
@ -64,10 +69,24 @@ impl GenericGpuLimit {
max: Some(1600),
}),
clock_step: Some(100),
// Disabled for now since LCD version is a bit broken on sysfs right now
/*memory_clock: Some(RangeLimit {
min: Some(400),
max: Some(800),
}),
memory_clock_step: Some(400),*/
memory_clock: None,
memory_clock_step: None,
skip_resume_reclock: false,
}
}
fn default_steam_deck_oled() -> Self {
let mut sd = Self::default_steam_deck();
sd.memory_clock_step = Some(200);
sd
}
pub fn apply_override(&mut self, limit_override: Self) {
if let Some(range) = limit_override.fast_ppt {
if range.min.is_none() && range.max.is_none() {

View file

@ -59,7 +59,8 @@ pub struct GpuLimits {
pub clock_min_limits: Option<RangeLimit<u64>>,
pub clock_max_limits: Option<RangeLimit<u64>>,
pub clock_step: u64,
pub memory_control_capable: bool,
pub memory_control: Option<RangeLimit<u64>>,
pub memory_step: u64,
}
#[derive(Serialize, Deserialize)]

View file

@ -160,17 +160,17 @@ pub fn set_slow_memory(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |value: bool| {
let setter = move |value: u64| {
sender
.lock()
.unwrap()
.send(ApiMessage::Gpu(GpuMessage::SetSlowMemory(value)))
.send(ApiMessage::Gpu(GpuMessage::SetMemoryClock(Some(value))))
.expect("unset_clock_limits send failed")
};
move |params_in: super::ApiParameterType| {
if let Some(&Primitive::Bool(memory_is_slow)) = params_in.get(0) {
setter(memory_is_slow);
vec![memory_is_slow.into()]
if let Some(&Primitive::F64(mem_clock)) = params_in.get(0) {
setter(mem_clock as _);
vec![mem_clock.into()]
} else {
vec!["set_slow_memory missing parameter 0".into()]
}
@ -183,14 +183,14 @@ pub fn get_slow_memory(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
let callback = move |value: bool| {
let callback = move |value: Option<u64>| {
tx.send(value)
.expect("get_slow_memory callback send failed")
};
sender2
.lock()
.unwrap()
.send(ApiMessage::Gpu(GpuMessage::GetSlowMemory(Box::new(
.send(ApiMessage::Gpu(GpuMessage::GetMemoryClock(Box::new(
callback,
))))
.expect("get_slow_memory send failed");
@ -199,6 +199,23 @@ pub fn get_slow_memory(sender: Sender<ApiMessage>) -> impl AsyncCallable {
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |value: bool| vec![value.into()],
trans_getter: |value: Option<u64>| vec![super::utility::map_optional(value)],
}
}
pub fn unset_slow_memory(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move || {
sender
.lock()
.unwrap()
.send(ApiMessage::Gpu(GpuMessage::SetMemoryClock(None)))
.expect("unset_slow_memory send failed")
};
move |_: super::ApiParameterType| {
setter();
vec![true.into()]
}
}

View file

@ -198,8 +198,8 @@ pub enum GpuMessage {
GetPpt(Callback<(Option<u64>, Option<u64>)>),
SetClockLimits(Option<MinMax<u64>>),
GetClockLimits(Callback<Option<MinMax<u64>>>),
SetSlowMemory(bool),
GetSlowMemory(Callback<bool>),
SetMemoryClock(Option<u64>),
GetMemoryClock(Callback<Option<u64>>),
}
impl GpuMessage {
@ -210,8 +210,8 @@ impl GpuMessage {
Self::GetPpt(cb) => cb(settings.get_ppt()),
Self::SetClockLimits(clocks) => settings.clock_limits(clocks),
Self::GetClockLimits(cb) => cb(settings.get_clock_limits().map(|x| x.to_owned())),
Self::SetSlowMemory(val) => *settings.slow_memory() = val,
Self::GetSlowMemory(cb) => cb(*settings.slow_memory()),
Self::SetMemoryClock(val) => settings.memory_clock(val),
Self::GetMemoryClock(cb) => cb(settings.get_memory_clock()),
}
dirty
}
@ -219,7 +219,7 @@ impl GpuMessage {
fn is_modify(&self) -> bool {
matches!(
self,
Self::SetPpt(_, _) | Self::SetClockLimits(_) | Self::SetSlowMemory(_)
Self::SetPpt(_, _) | Self::SetClockLimits(_) | Self::SetMemoryClock(_)
)
}
}

View file

@ -70,7 +70,7 @@ fn web_config_to_settings_json(meta: community_settings_core::v1::Metadata) -> c
min: lim.min,
max: lim.max,
}),
slow_memory: meta.config.gpu.slow_memory,
memory_clock: meta.config.gpu.memory_clock,
root: None,
},
battery: crate::persist::BatteryJson {
@ -138,7 +138,7 @@ fn settings_to_web_config(app_id: u32, user_id: u64, username: String, settings:
min: lim.min,
max: lim.max,
}),
slow_memory: settings.gpu.slow_memory,
memory_clock: settings.gpu.memory_clock,
},
battery: community_settings_core::v1::Battery {
charge_rate: settings.battery.charge_rate,

View file

@ -243,6 +243,10 @@ fn main() -> Result<(), ()> {
"GPU_get_slow_memory",
api::gpu::get_slow_memory(api_sender.clone()),
)
.register(
"GPU_unset_slow_memory",
api::gpu::unset_slow_memory(api_sender.clone()),
)
// general API functions
.register(
"GENERAL_set_persistent",

View file

@ -11,7 +11,7 @@ pub struct GpuJson {
pub tdp: Option<u64>,
pub tdp_boost: Option<u64>,
pub clock_limits: Option<MinMaxJson<u64>>,
pub slow_memory: bool,
pub memory_clock: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub root: Option<String>,
}
@ -24,7 +24,7 @@ impl Default for GpuJson {
tdp: None,
tdp_boost: None,
clock_limits: None,
slow_memory: false,
memory_clock: None,
root: None,
}
}

View file

@ -203,6 +203,13 @@ pub fn auto_detect0(
relevant_limits.gpu.limits,
))
}
GpuLimitType::SteamDeckOLED => {
Box::new(crate::settings::steam_deck::Gpu::from_json_and_limits(
settings.gpu.clone(),
settings.version,
relevant_limits.gpu.limits,
))
}
GpuLimitType::Generic => {
Box::new(crate::settings::generic::Gpu::from_json_and_limits(
settings.gpu.clone(),
@ -289,6 +296,9 @@ pub fn auto_detect0(
GpuLimitType::SteamDeckAdvance => {
Box::new(crate::settings::steam_deck::Gpu::from_limits(relevant_limits.gpu.limits))
}
GpuLimitType::SteamDeckOLED => {
Box::new(crate::settings::steam_deck::Gpu::from_limits(relevant_limits.gpu.limits))
}
GpuLimitType::Generic => {
Box::new(crate::settings::generic::Gpu::from_limits(relevant_limits.gpu.limits))
}

View file

@ -111,7 +111,7 @@ impl Into<GpuJson> for Gpu {
tdp: self.tdp,
tdp_boost: self.tdp_boost,
clock_limits: self.clock_limits.map(|x| x.into()),
slow_memory: false,
memory_clock: None,
root: self.sysfs.root().and_then(|p| p.as_ref().to_str().map(|s| s.to_owned()))
}
}
@ -177,7 +177,8 @@ impl TGpu for Gpu {
.clone()
.map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(3_000))),
clock_step: self.limits.clock_step.unwrap_or(100),
memory_control_capable: false,
memory_control: None,
memory_step: 100,
}
}
@ -227,8 +228,10 @@ impl TGpu for Gpu {
self.clock_limits.as_ref()
}
fn slow_memory(&mut self) -> &mut bool {
&mut self.slow_memory
fn memory_clock(&mut self, _speed: Option<u64>) {}
fn get_memory_clock(&self) -> Option<u64> {
None
}
fn provider(&self) -> crate::persist::DriverJson {

View file

@ -299,7 +299,8 @@ fn bad_gpu_limits() -> crate::api::GpuLimits {
clock_min_limits: None,
clock_max_limits: None,
clock_step: 100,
memory_control_capable: false,
memory_control: None,
memory_step: 400,
}
}
@ -333,8 +334,12 @@ impl TGpu for Gpu {
self.generic.get_clock_limits()
}
fn slow_memory(&mut self) -> &mut bool {
self.generic.slow_memory()
fn memory_clock(&mut self, speed: Option<u64>) {
self.generic.memory_clock(speed)
}
fn get_memory_clock(&self) -> Option<u64> {
self.generic.get_memory_clock()
}
fn provider(&self) -> crate::persist::DriverJson {

View file

@ -1,6 +1,6 @@
use std::convert::Into;
use sysfuss::{BasicEntityPath, HwMonPath, SysEntity, capability::attributes, SysEntityAttributesExt, SysAttribute};
use sysfuss::{BasicEntityPath, HwMonPath, SysEntity, capability::attributes, SysEntityAttributes, SysEntityAttributesExt, SysAttribute};
use limits_core::json_v2::GenericGpuLimit;
@ -20,7 +20,7 @@ pub struct Gpu {
pub fast_ppt: Option<u64>,
pub slow_ppt: Option<u64>,
pub clock_limits: Option<MinMax<u64>>,
pub slow_memory: bool,
pub memory_clock: Option<u64>,
limits: GenericGpuLimit,
state: crate::state::steam_deck::Gpu,
sysfs_card: BasicEntityPath,
@ -47,6 +47,8 @@ enum ClockType {
const MAX_CLOCK: u64 = 1600;
const MIN_CLOCK: u64 = 200;
const MAX_MEMORY_CLOCK: u64 = 800;
const MIN_MEMORY_CLOCK: u64 = 400;
const MAX_FAST_PPT: u64 = 30_000_000;
const MIN_FAST_PPT: u64 = 1_000_000;
const MAX_SLOW_PPT: u64 = 29_000_000;
@ -108,6 +110,63 @@ impl Gpu {
})
}
fn is_memory_clock_maxed(&self) -> bool {
if let Some(clock) = &self.memory_clock {
if let Some(limit) = &self.limits.memory_clock {
if let Some(limit) = &limit.max {
if let Some(step) = &self.limits.memory_clock_step {
log::debug!("chosen_clock: {}, limit_clock: {}, step: {}", clock, limit, step);
return clock > &(limit - step);
} else {
log::debug!("chosen_clock: {}, limit_clock: {}", clock, limit);
return clock == limit;
}
}
}
}
true
}
fn quantize_memory_clock(&self, clock: u64) -> u64 {
if let Ok(f) = self.sysfs_card.read_value(GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.to_owned()) {
let options = parse_pp_dpm_fclk(&String::from_utf8_lossy(&f));
// round (and find) nearest valid clock step
// roughly price is right strategy (clock step will always be lower or equal to chosen)
for i in 0..options.len() {
let (current_val_opt, current_speed_opt) = &options[i];
let current_speed_opt = *current_speed_opt as u64;
if clock == current_speed_opt {
return *current_val_opt as _;
} else if current_speed_opt > clock {
if i == 0 {
return *current_val_opt as _;
} else {
return options[i-1].0 as _;
}
}
}
options[options.len() - 1].0 as _
} else {
self.is_memory_clock_maxed() as u64
}
}
fn build_memory_clock_payload(&self, clock: u64) -> String {
let max_val = self.quantize_memory_clock(clock);
match max_val {
0 => "0\n".to_owned(),
max_val => {
use std::fmt::Write;
let mut payload = String::from("0");
for i in 1..max_val {
write!(payload, " {}", i).expect("Failed to write to memory payload (should be infallible!?)");
}
write!(payload, " {}\n", max_val).expect("Failed to write to memory payload (should be infallible!?)");
payload
}
}
}
fn set_clocks(&mut self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new();
if let Some(clock_limits) = &self.clock_limits {
@ -130,7 +189,7 @@ impl Gpu {
|| POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual()
{
self.state.clock_limits_set = false;
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(self.slow_memory);
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(!self.is_memory_clock_maxed());
if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() {
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level(&self.sysfs_card)?;
// disable manual clock limits
@ -155,47 +214,36 @@ impl Gpu {
}
}
fn set_slow_memory(&self, slow: bool) -> Result<(), SettingError> {
fn set_memory_speed(&self, clock: u64) -> Result<(), SettingError> {
let path = GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.path(&self.sysfs_card);
if slow {
self.sysfs_card.set(GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.to_owned(), slow as u8).map_err(|e| {
SettingError {
msg: format!("Failed to write to `{}`: {}", path.display(), e),
setting: crate::settings::SettingVariant::Gpu,
}
})
} else {
// NOTE: there is a GPU driver/hardware bug that prevents this from working
self.sysfs_card.set(GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.to_owned(), "0 1\n").map_err(|e| {
SettingError {
msg: format!("Failed to write to `{}`: {}", path.display(), e),
setting: crate::settings::SettingVariant::Gpu,
}
})
}
let payload = self.build_memory_clock_payload(clock);
log::debug!("Generated payload for gpu fclk (memory): `{}` (is maxed? {})", payload, self.is_memory_clock_maxed());
self.sysfs_card.set(GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.to_owned(), payload).map_err(|e| {
SettingError {
msg: format!("Failed to write to `{}`: {}", path.display(), e),
setting: crate::settings::SettingVariant::Gpu,
}
})
}
fn set_force_performance_related(&mut self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new();
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(!self.is_memory_clock_maxed() || self.clock_limits.is_some());
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT
.enforce_level(&self.sysfs_card)
.unwrap_or_else(|mut e| errors.append(&mut e));
// enable/disable downclock of GPU memory (to 400Mhz?)
if self.slow_memory {
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(true);
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT
.enforce_level(&self.sysfs_card)
.unwrap_or_else(|mut e| errors.append(&mut e));
self.set_slow_memory(self.slow_memory).unwrap_or_else(|e| errors.push(e));
} else if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() {
self.set_slow_memory(self.slow_memory).unwrap_or_else(|e| errors.push(e));
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(self.clock_limits.is_some());
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT
.enforce_level(&self.sysfs_card)
.unwrap_or_else(|mut e| errors.append(&mut e));
}
self.set_memory_speed(
self.memory_clock
.or_else(|| self.limits.memory_clock
.map(|lim| lim.max.unwrap_or(MAX_MEMORY_CLOCK))
).unwrap_or(MAX_MEMORY_CLOCK)
).unwrap_or_else(|e| errors.push(e));
self.set_clocks()
.unwrap_or_else(|mut e| errors.append(&mut e));
// commit changes (if no errors have already occured)
if errors.is_empty() {
if self.slow_memory || self.clock_limits.is_some() {
if !self.is_memory_clock_maxed() || self.clock_limits.is_some() {
self.set_confirm().map_err(|e| {
errors.push(e);
errors
@ -294,6 +342,9 @@ impl Gpu {
Some(max.clamp(self.limits.clock_max.and_then(|lim| lim.min).unwrap_or(MIN_CLOCK), self.limits.clock_max.and_then(|lim| lim.max).unwrap_or(MAX_CLOCK)));
}
}
if let Some(mem_clock) = self.memory_clock {
self.memory_clock = Some(mem_clock.clamp(self.limits.memory_clock.and_then(|lim| lim.min).unwrap_or(MIN_MEMORY_CLOCK), self.limits.memory_clock.and_then(|lim| lim.max).unwrap_or(MAX_MEMORY_CLOCK)));
}
}
}
@ -306,7 +357,7 @@ impl Into<GpuJson> for Gpu {
tdp: None,
tdp_boost: None,
clock_limits: self.clock_limits.map(|x| x.into()),
slow_memory: self.slow_memory,
memory_clock: self.memory_clock,
root: self.sysfs_card.root().or(self.sysfs_hwmon.root()).and_then(|p| p.as_ref().to_str().map(|r| r.to_owned()))
}
}
@ -319,7 +370,7 @@ impl ProviderBuilder<GpuJson, GenericGpuLimit> for Gpu {
fast_ppt: persistent.fast_ppt,
slow_ppt: persistent.slow_ppt,
clock_limits: persistent.clock_limits.map(|x| min_max_from_json(x, version)),
slow_memory: persistent.slow_memory,
memory_clock: persistent.memory_clock,
limits: limits,
state: crate::state::steam_deck::Gpu::default(),
sysfs_card: Self::find_card_sysfs(persistent.root.clone()),
@ -329,7 +380,7 @@ impl ProviderBuilder<GpuJson, GenericGpuLimit> for Gpu {
fast_ppt: persistent.fast_ppt,
slow_ppt: persistent.slow_ppt,
clock_limits: persistent.clock_limits.map(|x| min_max_from_json(x, version)),
slow_memory: persistent.slow_memory,
memory_clock: persistent.memory_clock,
limits: limits,
state: crate::state::steam_deck::Gpu::default(),
sysfs_card: Self::find_card_sysfs(persistent.root.clone()),
@ -343,7 +394,7 @@ impl ProviderBuilder<GpuJson, GenericGpuLimit> for Gpu {
fast_ppt: None,
slow_ppt: None,
clock_limits: None,
slow_memory: false,
memory_clock: None,
limits: limits,
state: crate::state::steam_deck::Gpu::default(),
sysfs_card: Self::find_card_sysfs(None::<&'static str>),
@ -393,7 +444,11 @@ impl TGpu for Gpu {
max: super::util::range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK),
}),
clock_step: self.limits.clock_step.unwrap_or(100),
memory_control_capable: true,
memory_control: Some(RangeLimit {
min: super::util::range_min_or_fallback(&self.limits.memory_clock, MIN_MEMORY_CLOCK),
max: super::util::range_max_or_fallback(&self.limits.memory_clock, MAX_MEMORY_CLOCK),
}),
memory_step: self.limits.memory_clock_step.unwrap_or(400),
}
}
@ -421,11 +476,35 @@ impl TGpu for Gpu {
self.clock_limits.as_ref()
}
fn slow_memory(&mut self) -> &mut bool {
&mut self.slow_memory
fn memory_clock(&mut self, speed: Option<u64>) {
self.memory_clock = speed;
}
fn get_memory_clock(&self) -> Option<u64> {
self.memory_clock
}
fn provider(&self) -> crate::persist::DriverJson {
crate::persist::DriverJson::SteamDeck
}
}
fn parse_pp_dpm_fclk(s: &str) -> Vec<(usize, usize)> { // (value, MHz)
let mut result = Vec::new();
for line in s.split('\n') {
if !line.is_empty() {
if let Some((val, freq_mess)) = line.split_once(':') {
if let Ok(val) = val.parse::<usize>() {
if let Some((freq, _unit)) = freq_mess.trim().split_once(|c: char| !c.is_digit(10)) {
if let Ok(freq) = freq.parse::<usize>() {
result.push((val, freq));
}
}
}
}
} else {
break;
}
}
result
}

View file

@ -96,7 +96,7 @@ impl PDFPLManager {
if let Ok(mode_now) =
entity.attribute::<String, _>(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned())
{
log::debug!("Mode for `{}` is now `{}`", path.display(), mode_now);
log::debug!("Mode for `{}` is now `{}` ({:#b})", path.display(), mode_now, self.get());
} else {
log::debug!("Error getting new mode for debugging purposes");
}

View file

@ -59,7 +59,9 @@ pub trait TGpu: OnSet + OnResume + OnPowerEvent + Debug + Send {
fn get_clock_limits(&self) -> Option<&MinMax<u64>>;
fn slow_memory(&mut self) -> &mut bool;
fn memory_clock(&mut self, speed: Option<u64>);
fn get_memory_clock(&self) -> Option<u64>;
fn provider(&self) -> crate::persist::DriverJson {
crate::persist::DriverJson::AutoDetect

View file

@ -8,13 +8,11 @@ use crate::settings::{TGpu, ProviderBuilder};
use crate::settings::{OnResume, OnSet, SettingError};
#[derive(Debug, Clone)]
pub struct Gpu {
slow_memory: bool, // ignored
}
pub struct Gpu {}
impl Gpu {
pub fn system_default() -> Self {
Self { slow_memory: false }
Self { }
}
}
@ -37,7 +35,7 @@ impl Into<GpuJson> for Gpu {
tdp: None,
tdp_boost: None,
clock_limits: None,
slow_memory: false,
memory_clock: None,
root: None,
}
}
@ -69,7 +67,8 @@ impl TGpu for Gpu {
clock_min_limits: None,
clock_max_limits: None,
clock_step: 100,
memory_control_capable: false,
memory_control: None,
memory_step: 400,
}
}
@ -89,8 +88,10 @@ impl TGpu for Gpu {
None
}
fn slow_memory(&mut self) -> &mut bool {
&mut self.slow_memory
fn memory_clock(&mut self, _speed: Option<u64>) {}
fn get_memory_clock(&self) -> Option<u64> {
None
}
fn provider(&self) -> crate::persist::DriverJson {

View file

@ -90,7 +90,8 @@ export type GpuLimits = {
clock_min_limits: RangeLimit | null;
clock_max_limits: RangeLimit | null;
clock_step: number;
memory_control_capable: boolean;
memory_control: RangeLimit | null,
memory_step: number,
};
// API
@ -229,14 +230,18 @@ export async function unsetGpuClockLimits(): Promise<any[]> {
return (await call_backend("GPU_unset_clock_limits", []));
}
export async function setGpuSlowMemory(val: boolean): Promise<boolean> {
return (await call_backend("GPU_set_slow_memory", [val]))[0];
export async function setGpuSlowMemory(clock: number): Promise<number> {
return (await call_backend("GPU_set_slow_memory", [clock]))[0];
}
export async function getGpuSlowMemory(): Promise<boolean> {
export async function getGpuSlowMemory(): Promise<number> {
return (await call_backend("GPU_get_slow_memory", []))[0];
}
export async function unsetGpuSlowMemory(): Promise<any[]> {
return (await call_backend("GPU_unset_slow_memory", []));
}
// general
export async function setGeneralPersistent(val: boolean): Promise<boolean> {

View file

@ -180,16 +180,42 @@ export class Gpu extends Component<backend.IdcProps> {
}}
/>}
</PanelSectionRow>
{(get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.memory_control_capable && <PanelSectionRow>
{((get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.memory_control) && <PanelSectionRow>
<ToggleField
checked={get_value(SLOW_MEMORY_GPU)}
checked={get_value(SLOW_MEMORY_GPU) != null}
label={tr("Downclock Memory")}
description={tr("Force RAM into low-power mode")}
onChange={(value: boolean) => {
backend.resolve(backend.setGpuSlowMemory(value), (val: boolean) => {
set_value(SLOW_MEMORY_GPU, val);
reloadGUI("GPUSlowMemory");
})
if (value) {
set_value(SLOW_MEMORY_GPU, (get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.memory_control!.max);
reloadGUI("GPUMemFreqToggle");
} else {
set_value(SLOW_MEMORY_GPU, null);
backend.resolve(backend.unsetGpuSlowMemory(), (_: any[]) => {
reloadGUI("GPUUnsetMemFreq");
});
}
}}
/>
</PanelSectionRow>}
{get_value(SLOW_MEMORY_GPU) != null && <PanelSectionRow>
<SliderField
label={tr("Maximum (MHz)")}
value={get_value(SLOW_MEMORY_GPU)}
max={(get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.memory_control!.max}
min={(get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.memory_control!.min}
step={(get_value(LIMITS_INFO) as backend.SettingsLimits).gpu.memory_step}
showValue={true}
disabled={get_value(SLOW_MEMORY_GPU) == null}
onChange={(val: number) => {
backend.log(backend.LogLevel.Debug, "GPU memory clock Max is now " + val.toString());
backend.resolve(
backend.setGpuSlowMemory(val),
(val: number) => {
set_value(SLOW_MEMORY_GPU, val);
reloadGUI("GPUSetMemFreq");
}
);
}}
/>
</PanelSectionRow>}

View file

@ -170,7 +170,7 @@ const reload = function() {
set_value(CLOCK_MIN_GPU, limits[0]);
set_value(CLOCK_MAX_GPU, limits[1]);
});
backend.resolve(backend.getGpuSlowMemory(), (status: boolean) => { set_value(SLOW_MEMORY_GPU, status) });
backend.resolve(backend.getGpuSlowMemory(), (status: number) => { set_value(SLOW_MEMORY_GPU, status) });
backend.resolve(backend.getGeneralPersistent(), (value: boolean) => { set_value(PERSISTENT_GEN, value) });
backend.resolve(backend.getGeneralSettingsName(), (name: string) => { set_value(NAME_GEN, name) });