performance improvement
This commit is contained in:
250
simu/src/main.rs
250
simu/src/main.rs
@@ -1,130 +1,192 @@
|
||||
#![feature(likely_unlikely, widening_mul)]
|
||||
#![feature(likely_unlikely, widening_mul, sync_unsafe_cell)]
|
||||
#![deny(clippy::all)]
|
||||
|
||||
use std::env::args;
|
||||
use std::process::exit;
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Arc;
|
||||
use std::thread::{scope, sleep};
|
||||
use std::time::Duration;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use pixels::{Error, Pixels, SurfaceTexture};
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::dpi::LogicalSize;
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use winit::event::WindowEvent;
|
||||
use winit::event_loop::EventLoop;
|
||||
use winit::platform::scancode::PhysicalKeyExtScancode;
|
||||
use winit::window::Window;
|
||||
use winit_input_helper::WinitInputHelper;
|
||||
// use winit_input_helper::WinitInputHelper;
|
||||
|
||||
use crate::cpu::Computer;
|
||||
|
||||
mod cpu;
|
||||
use cpu::SHARED;
|
||||
|
||||
const WIDTH: u32 = 640;
|
||||
const HEIGHT: u32 = 480;
|
||||
|
||||
mod cpu;
|
||||
struct App<'a> {
|
||||
w: Option<Arc<Window>>,
|
||||
pixels: Option<Pixels<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> ApplicationHandler for App<'a> {
|
||||
fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||
let window = {
|
||||
let size = LogicalSize::new(WIDTH as f64, HEIGHT as f64);
|
||||
Arc::new(
|
||||
event_loop
|
||||
.create_window(
|
||||
Window::default_attributes()
|
||||
.with_title("bisare screen")
|
||||
.with_min_inner_size(size)
|
||||
.with_maximized(true),
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
};
|
||||
self.w = Some(window.clone());
|
||||
let size = window.inner_size();
|
||||
let surface_texture = SurfaceTexture::new(size.width, size.height, window);
|
||||
self.pixels = Some(Pixels::new(WIDTH, HEIGHT, surface_texture).unwrap());
|
||||
}
|
||||
|
||||
fn window_event(
|
||||
&mut self,
|
||||
elwt: &winit::event_loop::ActiveEventLoop,
|
||||
_: winit::window::WindowId,
|
||||
event: WindowEvent,
|
||||
) {
|
||||
// Draw the current frame
|
||||
match event {
|
||||
WindowEvent::KeyboardInput { event, .. } => match event.state {
|
||||
winit::event::ElementState::Pressed => {
|
||||
if let Some(val) = event.physical_key.to_scancode() {
|
||||
cpu::SHARED
|
||||
.keyboard
|
||||
.store(val + 8, std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
winit::event::ElementState::Released => SHARED
|
||||
.keyboard
|
||||
.store(0, std::sync::atomic::Ordering::Relaxed),
|
||||
},
|
||||
WindowEvent::CursorMoved {
|
||||
device_id,
|
||||
position,
|
||||
} => {}
|
||||
WindowEvent::MouseWheel {
|
||||
device_id,
|
||||
delta,
|
||||
phase,
|
||||
} => {}
|
||||
WindowEvent::MouseInput {
|
||||
device_id,
|
||||
state,
|
||||
button,
|
||||
} => {}
|
||||
WindowEvent::ScaleFactorChanged {
|
||||
scale_factor,
|
||||
inner_size_writer,
|
||||
} => {}
|
||||
//handling redraws and other graphical events
|
||||
WindowEvent::RedrawRequested => {
|
||||
let pix = self.pixels.as_mut().unwrap();
|
||||
|
||||
let screen = pix.frame_mut();
|
||||
for (addr, ubgr) in { cpu::SHARED.screen_buf.iter().enumerate() } {
|
||||
let ubgr = ubgr.load(std::sync::atomic::Ordering::Relaxed);
|
||||
let rgba = [ubgr as u8, (ubgr >> 8) as u8, (ubgr >> 16) as u8, 0xff];
|
||||
for i in 0..4 {
|
||||
screen[addr * 4 + i] = rgba[i];
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(_) = pix.render() {
|
||||
elwt.exit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
WindowEvent::Resized(size) => {
|
||||
if self
|
||||
.pixels
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.resize_surface(size.width, size.height)
|
||||
.is_err()
|
||||
{
|
||||
println!("Error while resising pixels, exiting!");
|
||||
elwt.exit();
|
||||
return;
|
||||
}
|
||||
self.w.as_ref().unwrap().request_redraw();
|
||||
}
|
||||
WindowEvent::CloseRequested => {
|
||||
elwt.exit();
|
||||
return;
|
||||
}
|
||||
WindowEvent::Destroyed => {
|
||||
println!("Windows destroyed, exiting!");
|
||||
elwt.exit();
|
||||
return;
|
||||
}
|
||||
//do nothing for the other events
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
fn new_events(
|
||||
&mut self,
|
||||
event_loop: &winit::event_loop::ActiveEventLoop,
|
||||
cause: winit::event::StartCause,
|
||||
) {
|
||||
match cause {
|
||||
winit::event::StartCause::ResumeTimeReached {
|
||||
requested_resume, ..
|
||||
} => {
|
||||
let mut next = requested_resume + Duration::from_secs_f64(1. / 60.);
|
||||
let now = Instant::now();
|
||||
if next < now {
|
||||
next = now + Duration::from_secs_f64(1. / 30.);
|
||||
}
|
||||
event_loop.set_control_flow(winit::event_loop::ControlFlow::WaitUntil(next));
|
||||
if let Some(w) = self.w.as_ref() {
|
||||
w.request_redraw();
|
||||
}
|
||||
}
|
||||
winit::event::StartCause::WaitCancelled { .. } => {}
|
||||
winit::event::StartCause::Poll => {
|
||||
let next = Instant::now() + Duration::from_secs_f64(1. / 60.);
|
||||
event_loop.set_control_flow(winit::event_loop::ControlFlow::WaitUntil(next));
|
||||
}
|
||||
winit::event::StartCause::Init => {
|
||||
let next = Instant::now() + Duration::from_secs_f64(1. / 60.);
|
||||
event_loop.set_control_flow(winit::event_loop::ControlFlow::WaitUntil(next));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
let event_loop = EventLoop::new().unwrap();
|
||||
let mut input = WinitInputHelper::new();
|
||||
let window = {
|
||||
let size = LogicalSize::new((WIDTH * 3) as f64, (HEIGHT * 3) as f64);
|
||||
#[allow(deprecated)]
|
||||
Arc::new(
|
||||
event_loop
|
||||
.create_window(
|
||||
Window::default_attributes()
|
||||
.with_title("bisare screen")
|
||||
.with_inner_size(size)
|
||||
.with_min_inner_size(size),
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
// let mut input = WinitInputHelper::new();
|
||||
|
||||
let mut app = App {
|
||||
w: None,
|
||||
pixels: None,
|
||||
};
|
||||
|
||||
let pixels = Mutex::new({
|
||||
let window_size = window.inner_size();
|
||||
let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, &window);
|
||||
Pixels::new(WIDTH, HEIGHT, surface_texture)?
|
||||
});
|
||||
|
||||
let keyboard = AtomicU32::new(0);
|
||||
let program = args()
|
||||
.nth(1)
|
||||
.expect("you must supply the exec name as the first argument");
|
||||
let kbref = &keyboard;
|
||||
let pixelref = &pixels;
|
||||
scope(|sc| {
|
||||
sc.spawn(|| {
|
||||
let mut simulation = Computer::new(program, pixelref, kbref);
|
||||
let mut simulation = Computer::new(program);
|
||||
loop {
|
||||
simulation.step();
|
||||
}
|
||||
});
|
||||
|
||||
#[allow(deprecated)]
|
||||
let res = event_loop.run(|event, elwt| {
|
||||
match event {
|
||||
Event::Resumed => {}
|
||||
Event::NewEvents(_) => input.step(),
|
||||
Event::AboutToWait => input.end_step(),
|
||||
Event::DeviceEvent { event, .. } => {
|
||||
input.process_device_event(&event);
|
||||
}
|
||||
Event::WindowEvent { event, .. } => {
|
||||
// Draw the current frame
|
||||
if event == WindowEvent::RedrawRequested {
|
||||
if let Err(_) = pixels.lock().unwrap().render() {
|
||||
elwt.exit();
|
||||
return;
|
||||
}
|
||||
sleep(Duration::from_millis(30));
|
||||
}
|
||||
|
||||
if let WindowEvent::KeyboardInput {
|
||||
device_id: _,
|
||||
ref event,
|
||||
is_synthetic: _,
|
||||
} = event
|
||||
{
|
||||
match event.state {
|
||||
winit::event::ElementState::Pressed => {
|
||||
if let Some(val) = event.physical_key.to_scancode() {
|
||||
kbref.store(val + 8, std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
winit::event::ElementState::Released => {
|
||||
kbref.store(0, std::sync::atomic::Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle input events
|
||||
if input.process_window_event(&event) {
|
||||
// Close events
|
||||
if input.close_requested() {
|
||||
elwt.exit();
|
||||
return;
|
||||
}
|
||||
|
||||
// Resize the window
|
||||
if let Some(size) = input.window_resized() {
|
||||
if let Err(_) = pixels
|
||||
.lock()
|
||||
.unwrap()
|
||||
.resize_surface(size.width, size.height)
|
||||
{
|
||||
elwt.exit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Update internal state and request a redraw
|
||||
window.request_redraw();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
let res = event_loop.run_app(&mut app);
|
||||
match res {
|
||||
Ok(_) => exit(0),
|
||||
Err(e) => {
|
||||
|
||||
Reference in New Issue
Block a user