[oden] Move graphics thread off main thread

So we can do frame pacing a little bit better maybe.
This commit is contained in:
John Doty 2023-06-30 16:54:16 -07:00
parent 26bfcc7a94
commit b1b97cee75
2 changed files with 79 additions and 106 deletions

View file

@ -23,4 +23,5 @@ export function draw() {
use_texture(the_texture); use_texture(the_texture);
spr((320 - 256) / 2, 0, 256, 240, 0, 0); spr((320 - 256) / 2, 0, 256, 240, 0, 0);
} }
// print("FRAME TIME:", since_last_frame());
} }

View file

@ -1,12 +1,9 @@
use bytemuck; use bytemuck;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::mpsc::Receiver;
use std::time::Instant;
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
use winit::{ use winit::{event::*, event_loop::EventLoop, window::Window, window::WindowBuilder};
event::*,
event_loop::{ControlFlow, EventLoop},
window::Window,
window::WindowBuilder,
};
mod script; mod script;
use script::graphics::GraphicsCommand; use script::graphics::GraphicsCommand;
@ -142,17 +139,12 @@ impl State {
format: surface_format, format: surface_format,
width: size.width, width: size.width,
height: size.height, height: size.height,
present_mode: surface_caps.present_modes[0], present_mode: wgpu::PresentMode::Fifo,
alpha_mode: surface_caps.alpha_modes[0], alpha_mode: surface_caps.alpha_modes[0],
view_formats: vec![], view_formats: vec![],
}; };
surface.configure(&device, &config); surface.configure(&device, &config);
// TODO: DELETE THIS
// let diffuse_bytes = include_bytes!("happy-tree.png");
// let diffuse_texture =
// texture::Texture::from_bytes(&device, &queue, diffuse_bytes, "happy-tree.png").unwrap();
let sprite_bind_group_layout = let sprite_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[ entries: &[
@ -475,78 +467,37 @@ impl State {
self.queue.submit(std::iter::once(encoder.finish())); self.queue.submit(std::iter::once(encoder.finish()));
} }
// {
// // BEGIN GARBAGE
// let r: f64 = (self.mouse_x / f64::from(self.size.width)).clamp(0.0, 1.0) * 0.1;
// let g: f64 = (self.mouse_y / f64::from(self.size.height)).clamp(0.0, 1.0) * 0.2;
// // END GARBAGE
// let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
// label: Some("Render Pass"),
// color_attachments: &[Some(wgpu::RenderPassColorAttachment {
// view: &view,
// resolve_target: None,
// ops: wgpu::Operations {
// load: wgpu::LoadOp::Clear(wgpu::Color {
// r, //0.1,
// g, //0.2,
// b: 0.3,
// a: 1.0,
// }),
// store: true,
// },
// })],
// depth_stencil_attachment: None,
// });
// render_pass.set_pipeline(&self.render_pipeline);
// render_pass.set_bind_group(0, &self.diffuse_bind_group, &[]);
// render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
// render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
// render_pass.draw_indexed(0..self.num_indices, 0, 0..1);
// }
output.present(); output.present();
Ok(()) Ok(())
} }
} }
pub async fn run() { struct UIEvent {
env_logger::init(); winit: Event<'static, ()>,
let event_loop = EventLoop::new(); #[allow(unused)]
let window = WindowBuilder::new().build(&event_loop).unwrap(); time: Instant,
}
let mut state = State::new(window).await; // TODO: flume? (https://docs.rs/flume/latest/flume/)
fn main_thread(state: State, reciever: Receiver<UIEvent>) {
let mut state = state;
let mut context = script::ScriptContext::new(); let mut context = script::ScriptContext::new();
context.init(); context.init();
event_loop.run(move |event, _, control_flow| { loop {
control_flow.set_poll(); while let Ok(event) = reciever.try_recv() {
match event.winit {
match event {
Event::WindowEvent { Event::WindowEvent {
ref event, ref event,
window_id, window_id,
} if window_id == state.window().id() => { } if window_id == state.window().id() => {
if !state.input(event) { if !state.input(event) {
match event { match event {
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::Escape),
..
},
..
} => *control_flow = ControlFlow::Exit,
WindowEvent::CursorMoved { position, .. } => { WindowEvent::CursorMoved { position, .. } => {
state.mouse_x = position.x; state.mouse_x = position.x;
state.mouse_y = position.y; state.mouse_y = position.y;
state.window().request_redraw();
} }
WindowEvent::Resized(physical_size) => { WindowEvent::Resized(physical_size) => {
@ -563,7 +514,10 @@ pub async fn run() {
} }
} }
Event::RedrawRequested(window_id) if window_id == state.window().id() => { _ => {}
}
}
context.update(); context.update();
state.update(); state.update();
@ -572,19 +526,37 @@ pub async fn run() {
// Reconfigure the surface if lost // Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size), Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit // The system is out of memory, we should probably quit
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, Err(wgpu::SurfaceError::OutOfMemory) => panic!("Out of memory"),
// All other errors (Outdated, Timeout) should be resolved by the next frame // All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e), Err(e) => eprintln!("{:?}", e),
} }
// TODO: FRAME PACING.
}
} }
Event::MainEventsCleared => { pub async fn run() {
// RedrawRequested will only trigger once, unless we manually env_logger::init();
// request it. let event_loop = EventLoop::new();
state.window().request_redraw(); let window = WindowBuilder::new().build(&event_loop).unwrap();
}
_ => {} let state = State::new(window).await;
let (sender, reciever) = std::sync::mpsc::channel();
std::thread::spawn(move || {
main_thread(state, reciever);
});
event_loop.run(move |event, _, control_flow| {
control_flow.set_poll();
if let Some(e) = event.to_static() {
sender
.send(UIEvent {
winit: e,
time: Instant::now(),
})
.unwrap();
} }
}); });
} }