diff --git a/Cargo.toml b/Cargo.toml index 010ae82..e4bd088 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ itertools = "0.8" obj = "0.9" quickcheck = "0.9" quickcheck_macros = "0.8" +rayon = "1.3" sdl2 = "0.32" [dependencies.nalgebra] diff --git a/src/main.rs b/src/main.rs index 7ee9ccc..885633f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +use rayon::prelude::*; + use sdl2::event::Event; use sdl2::keyboard::Keycode; use sdl2::pixels::PixelFormatEnum; @@ -8,6 +10,7 @@ use std::time::Duration; use nalgebra::{Point3, Vector3}; use std::path::Path; +use std::sync::mpsc; use std::sync::{Arc, Mutex}; use vanrijn::camera::partial_render_scene; @@ -47,8 +50,8 @@ fn init_canvas( } pub fn main() -> Result<(), Box> { - let image_width = 320usize; - let image_height = 240usize; + let image_width = 640usize; + let image_height = 480usize; let (sdl_context, mut canvas) = init_canvas(image_width, image_height)?; @@ -115,42 +118,46 @@ pub fn main() -> Result<(), Box> { let mut event_pump = sdl_context.event_pump()?; - 'running: for tile in TileIterator::new(image_width as usize, image_height as usize, 16) { - let image_ptr = output_image.clone(); - let scene_ptr = scene.clone(); - partial_render_scene( - image_ptr, - scene_ptr, - tile.start_row, - tile.end_row, - tile.start_column, - tile.end_column, - image_height, - image_width, - ); + let (tile_tx, tile_rx) = mpsc::channel(); + let mut tile_rx = Some(tile_rx); - let locked_image = output_image.lock().unwrap(); - let mut output_image_rgbu8 = ImageRgbU8::new(image_width, image_height); - ClampingToneMapper {}.apply_tone_mapping(&locked_image, &mut output_image_rgbu8); - update_texture(&output_image_rgbu8, &mut rendered_image_texture); - canvas.copy(&rendered_image_texture, None, None)?; - canvas.present(); + let output_image_workers = Arc::clone(&output_image); + let worker_boss = std::thread::spawn(move || { + TileIterator::new(image_width as usize, image_height as usize, 16) + .map(move |tile| (tile, tile_tx.clone())) + .par_bridge() + .try_for_each(|(tile, tx)| { + let image_ptr = Arc::clone(&output_image_workers); + let scene_ptr = scene.clone(); + partial_render_scene( + image_ptr, + scene_ptr, + tile.start_row, + tile.end_row, + tile.start_column, + tile.end_column, + image_height, + image_width, + ); - for event in event_pump.poll_iter() { - match event { - Event::Quit { .. } - | Event::KeyDown { - keycode: Some(Keycode::Escape), - .. - } => break 'running, - _ => {} + // There's nothing we can do if this fails, and we're already + // at the end of the function anyway, so just ignore result. + tx.send(tile).ok() + }); + }); + + 'running: loop { + if let Some(ref tile_rx) = tile_rx { + for tile in tile_rx.try_iter() { + let locked_image = output_image.lock().unwrap(); + let mut output_image_rgbu8 = ImageRgbU8::new(image_width, image_height); + ClampingToneMapper {}.apply_tone_mapping(&locked_image, &mut output_image_rgbu8); + update_texture(&output_image_rgbu8, &mut rendered_image_texture); + canvas.copy(&rendered_image_texture, None, None).unwrap(); + canvas.present(); } } - } - let mut i = 0; - 'running: loop { - i = (i + 1) % 255; for event in event_pump.poll_iter() { match event { Event::Quit { .. } @@ -164,5 +171,7 @@ pub fn main() -> Result<(), Box> { ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60)); } + drop(tile_rx.take()); + worker_boss.join().expect("Couldn't join worker threads."); Ok(()) } diff --git a/src/util/mod.rs b/src/util/mod.rs index dcb0c72..1914db3 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -6,4 +6,4 @@ pub mod axis_aligned_bounding_box; pub mod morton; pub mod normalizer; mod tile_iterator; -pub use tile_iterator::TileIterator; +pub use tile_iterator::{Tile, TileIterator}; diff --git a/src/util/tile_iterator.rs b/src/util/tile_iterator.rs index c8aca36..f941a73 100644 --- a/src/util/tile_iterator.rs +++ b/src/util/tile_iterator.rs @@ -1,4 +1,4 @@ -#[derive(Debug)] +#[derive(Copy, Clone, Debug)] pub struct Tile { pub start_column: usize, pub end_column: usize,