Compare commits

...

2 Commits

Author SHA1 Message Date
Simon Gellis 99d6970323 Block the emulator thread when idle 2024-11-10 18:19:25 -05:00
Simon Gellis e8b706df20 Use high-priority thread for emulation 2024-11-10 18:19:25 -05:00
4 changed files with 53 additions and 12 deletions

21
Cargo.lock generated
View File

@ -1892,6 +1892,12 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "rustversion"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
[[package]] [[package]]
name = "same-file" name = "same-file"
version = "1.0.6" version = "1.0.6"
@ -1972,6 +1978,7 @@ dependencies = [
"pollster", "pollster",
"rtrb", "rtrb",
"rubato", "rubato",
"thread-priority",
"wgpu", "wgpu",
"winit", "winit",
] ]
@ -2118,6 +2125,20 @@ dependencies = [
"syn 2.0.87", "syn 2.0.87",
] ]
[[package]]
name = "thread-priority"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfe075d7053dae61ac5413a34ea7d4913b6e6207844fd726bdd858b37ff72bf5"
dependencies = [
"bitflags 2.6.0",
"cfg-if",
"libc",
"log",
"rustversion",
"winapi",
]
[[package]] [[package]]
name = "tiny-skia" name = "tiny-skia"
version = "0.11.4" version = "0.11.4"

View File

@ -19,6 +19,7 @@ num-traits = "0.2"
pollster = "0.4" pollster = "0.4"
rtrb = "0.3" rtrb = "0.3"
rubato = "0.16" rubato = "0.16"
thread-priority = "1"
wgpu = "22.1" wgpu = "22.1"
winit = "0.30" winit = "0.30"

View File

@ -3,7 +3,7 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
mpsc::{self, TryRecvError}, mpsc::{self, RecvError, TryRecvError},
Arc, Arc,
}, },
}; };
@ -94,19 +94,33 @@ impl Emulator {
let mut eye_contents = vec![0u8; 384 * 224 * 2]; let mut eye_contents = vec![0u8; 384 * 224 * 2];
let mut audio_samples = vec![]; let mut audio_samples = vec![];
loop { loop {
let mut idle = true;
if self.running.load(Ordering::Acquire) { if self.running.load(Ordering::Acquire) {
idle = false;
self.sim.emulate_frame(); self.sim.emulate_frame();
} }
if let Some(renderer) = &mut self.renderer { if let Some(renderer) = &mut self.renderer {
if self.sim.read_pixels(&mut eye_contents) { if self.sim.read_pixels(&mut eye_contents) {
idle = false;
renderer.render(&eye_contents); renderer.render(&eye_contents);
} }
} }
self.sim.read_samples(&mut audio_samples); self.sim.read_samples(&mut audio_samples);
if !audio_samples.is_empty() { if !audio_samples.is_empty() {
idle = false;
self.audio.update(&audio_samples); self.audio.update(&audio_samples);
audio_samples.clear(); audio_samples.clear();
} }
if idle {
// The game is paused, and we have output all the video/audio we have.
// Block the thread until a new command comes in.
match self.commands.recv() {
Ok(command) => self.handle_command(command),
Err(RecvError) => {
return;
}
}
}
loop { loop {
match self.commands.try_recv() { match self.commands.try_recv() {
Ok(command) => self.handle_command(command), Ok(command) => self.handle_command(command),

View File

@ -1,9 +1,10 @@
use std::{path::PathBuf, process, thread}; use std::{path::PathBuf, process};
use anyhow::Result; use anyhow::Result;
use app::App; use app::App;
use clap::Parser; use clap::Parser;
use emulator::EmulatorBuilder; use emulator::EmulatorBuilder;
use thread_priority::{ThreadBuilder, ThreadPriority};
use winit::event_loop::{ControlFlow, EventLoop}; use winit::event_loop::{ControlFlow, EventLoop};
mod app; mod app;
@ -26,16 +27,20 @@ fn main() -> Result<()> {
if let Some(path) = args.rom { if let Some(path) = args.rom {
builder = builder.with_rom(&path); builder = builder.with_rom(&path);
} }
thread::spawn(move || {
let mut emulator = match builder.build() { ThreadBuilder::default()
Ok(e) => e, .name("Emulator".to_owned())
Err(err) => { .priority(ThreadPriority::Max)
eprintln!("Error initializing emulator: {err}"); .spawn_careless(move || {
process::exit(1); let mut emulator = match builder.build() {
} Ok(e) => e,
}; Err(err) => {
emulator.run(); eprintln!("Error initializing emulator: {err}");
}); process::exit(1);
}
};
emulator.run();
})?;
let event_loop = EventLoop::with_user_event().build().unwrap(); let event_loop = EventLoop::with_user_event().build().unwrap();
event_loop.set_control_flow(ControlFlow::Poll); event_loop.set_control_flow(ControlFlow::Poll);