mirror of
https://github.com/gopher64/gopher64.git
synced 2026-10-01 00:36:42 +02:00
dynamically calculate speed limit frequency (#245)
* dynamically calculate speed limit frequency * dynamically calculate speed limit frequency * dynamically calculate speed limit frequency * more
This commit is contained in:
@@ -438,6 +438,10 @@ impl Device {
|
||||
vi_counter: 0,
|
||||
last_origin: 0,
|
||||
internal_frame_counter: 0,
|
||||
min_wait_time: std::time::Duration::from_secs(1),
|
||||
frame_time: 0.0,
|
||||
limit_freq: 2,
|
||||
limit_freq_check: std::time::Instant::now(),
|
||||
},
|
||||
vru_window: controller::vru::VruWindow {
|
||||
window_notifier: None,
|
||||
|
||||
+48
-10
@@ -29,24 +29,37 @@ pub struct Vi {
|
||||
pub vi_counter: u64,
|
||||
pub last_origin: u32,
|
||||
pub internal_frame_counter: u64,
|
||||
pub min_wait_time: std::time::Duration,
|
||||
pub frame_time: f64,
|
||||
pub limit_freq: u64,
|
||||
#[serde(skip)]
|
||||
#[serde(default = "std::time::Instant::now")]
|
||||
pub limit_freq_check: std::time::Instant,
|
||||
}
|
||||
|
||||
const LIMIT_BUFFER: u64 = 3;
|
||||
const MAX_LIMIT_FREQ: u64 = 3;
|
||||
|
||||
pub fn set_expected_refresh_rate(device: &mut device::Device) {
|
||||
let expected_refresh_rate = device.vi.clock as f64
|
||||
/ (device.vi.regs[VI_V_SYNC_REG as usize] + 1) as f64
|
||||
/ ((device.vi.regs[VI_H_SYNC_REG as usize] & 0xFFF) + 1) as f64
|
||||
* 2.0;
|
||||
device.vi.frame_time = 1.0 / expected_refresh_rate;
|
||||
device.vi.delay = (device.cpu.clock_rate as f64 / expected_refresh_rate) as u64;
|
||||
device.vi.count_per_scanline =
|
||||
device.vi.delay / (device.vi.regs[VI_V_SYNC_REG as usize] + 1) as u64;
|
||||
|
||||
create_limiter(device);
|
||||
}
|
||||
|
||||
fn create_limiter(device: &mut device::Device) {
|
||||
let quota = governor::Quota::with_period(std::time::Duration::from_secs_f64(
|
||||
(1.0 / expected_refresh_rate) * LIMIT_BUFFER as f64,
|
||||
device.vi.frame_time * device.vi.limit_freq as f64,
|
||||
))
|
||||
.unwrap();
|
||||
device.vi.limiter = Some(governor::RateLimiter::direct(quota))
|
||||
device.vi.limiter = Some(governor::RateLimiter::direct(quota));
|
||||
let _ = device.vi.limiter.as_ref().unwrap().check();
|
||||
//println!("new limit freq: {}", device.vi.limit_freq);
|
||||
}
|
||||
|
||||
fn set_vertical_interrupt(device: &mut device::Device) {
|
||||
@@ -134,16 +147,16 @@ pub fn vertical_interrupt_event(device: &mut device::Device) {
|
||||
}
|
||||
|
||||
device.vi.vi_counter += 1;
|
||||
if device.vi.vi_counter % LIMIT_BUFFER == 0 && enable_speed_limiter {
|
||||
if device.vi.vi_counter % device.vi.limit_freq == 0 && enable_speed_limiter {
|
||||
speed_limiter(device);
|
||||
}
|
||||
|
||||
/*
|
||||
let vis = if device.cart.pal { 50 } else { 60 };
|
||||
if device.vi.vi_counter % vis == 0 {
|
||||
println!("FPS: {}", device.vi.internal_frame_counter);
|
||||
device.vi.internal_frame_counter = 0;
|
||||
}
|
||||
let vis = if device.cart.pal { 50 } else { 60 };
|
||||
if device.vi.vi_counter % vis == 0 {
|
||||
println!("FPS: {}", device.vi.internal_frame_counter);
|
||||
device.vi.internal_frame_counter = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/* toggle vi field if in interlaced mode */
|
||||
@@ -166,13 +179,38 @@ pub fn init(device: &mut device::Device) {
|
||||
}
|
||||
}
|
||||
|
||||
fn speed_limiter(device: &device::Device) {
|
||||
fn speed_limiter(device: &mut device::Device) {
|
||||
let result = device.vi.limiter.as_ref().unwrap().check();
|
||||
if result.is_err() {
|
||||
let outcome = result.unwrap_err();
|
||||
let dur = outcome.wait_time_from(governor::clock::DefaultClock::default().now());
|
||||
spin_sleep::sleep(dur);
|
||||
if dur < device.vi.min_wait_time {
|
||||
device.vi.min_wait_time = dur;
|
||||
}
|
||||
|
||||
let _ = device.vi.limiter.as_ref().unwrap().check();
|
||||
} else {
|
||||
device.vi.min_wait_time = std::time::Duration::from_secs(0);
|
||||
}
|
||||
|
||||
if std::time::Instant::now()
|
||||
.duration_since(device.vi.limit_freq_check)
|
||||
.as_secs_f64()
|
||||
> 1.0
|
||||
{
|
||||
if device.vi.min_wait_time.as_secs_f64() == 0.0 && device.vi.limit_freq < MAX_LIMIT_FREQ {
|
||||
device.vi.limit_freq += 1;
|
||||
create_limiter(device);
|
||||
} else if device.vi.min_wait_time.as_secs_f64() > device.vi.frame_time
|
||||
&& device.vi.limit_freq > 1
|
||||
{
|
||||
device.vi.limit_freq -= 1;
|
||||
create_limiter(device);
|
||||
}
|
||||
|
||||
//println!("limit freq: {}", device.vi.limit_freq);
|
||||
device.vi.min_wait_time = std::time::Duration::from_secs(1);
|
||||
device.vi.limit_freq_check = std::time::Instant::now();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user