diff options
author | Julian T <julian@jtle.dk> | 2021-02-12 23:33:50 +0100 |
---|---|---|
committer | Julian T <julian@jtle.dk> | 2021-02-12 23:34:09 +0100 |
commit | 14f7b47f2c2315d0de5e52d31c57fe07a15d08ad (patch) | |
tree | f512e7e0939fd151cf9196004611e3cd82a95773 | |
parent | 49c6adb0db70ffc30eaac33b66eacf7574b34e26 (diff) |
Implement multithreaded compiling of tiles
-rw-r--r-- | Cargo.lock | 25 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/main.rs | 12 | ||||
-rw-r--r-- | src/render/coordinator.rs | 14 | ||||
-rw-r--r-- | src/sample/mod.rs | 2 | ||||
-rw-r--r-- | src/sample/uniform.rs | 6 | ||||
-rw-r--r-- | src/world/mod.rs | 8 |
7 files changed, 57 insertions, 11 deletions
@@ -64,6 +64,20 @@ dependencies = [ ] [[package]] +name = "crossbeam" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd01a6eb3daaafa260f6fc94c3a6c36390abc2080e38e3e34ced87393fb77d80" +dependencies = [ + "cfg-if", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] name = "crossbeam-channel" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -99,6 +113,16 @@ dependencies = [ ] [[package]] +name = "crossbeam-queue" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f6cb3c7f5b8e51bc3ebb73a2327ad4abdbd119dc13223f14f961d2f38486756" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] name = "crossbeam-utils" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -370,6 +394,7 @@ dependencies = [ name = "rendering" version = "0.1.0" dependencies = [ + "crossbeam", "image", "rand", "rand_pcg", @@ -10,3 +10,4 @@ edition = "2018" image = "0.23.12" rand = "0.8.3" rand_pcg = "0.3.0" +crossbeam = "0.8.0" diff --git a/src/main.rs b/src/main.rs index 215e0d4..0f6502e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ use rendering::render::{RenderContext, RenderCoord}; use rendering::sample::UniformSampler; use rendering::material::{Reflectant, Lambertian}; -use std::rc::Rc; +use std::sync::Arc; fn main() { let res = Vector2i::new_xy(500, 500); @@ -21,9 +21,9 @@ fn main() { aperture: Some(20.0), }); - let brown = Rc::new(Lambertian::new(Spectrum::new_rgb(0.5, 0.3, 0.0))); - let blue = Rc::new(Lambertian::new(Spectrum::new_rgb(0.0, 0.3, 0.7))); - let metal = Rc::new(Reflectant::new(Spectrum::new_rgb(0.75, 0.75, 0.75), None)); + let brown = Arc::new(Lambertian::new(Spectrum::new_rgb(0.5, 0.3, 0.0))); + let blue = Arc::new(Lambertian::new(Spectrum::new_rgb(0.0, 0.3, 0.7))); + let metal = Arc::new(Reflectant::new(Spectrum::new_rgb(0.75, 0.75, 0.75), None)); let mut scn = Scene::new(); scn.add_objects(vec![ @@ -40,9 +40,9 @@ fn main() { let mut film = Film::new(res); { - let coord = RenderCoord::new(&mut film, Vector2i::new_xy(32, 32), 100); + let coord = RenderCoord::new(&mut film, Vector2i::new_xy(32, 32), 300); - coord.work(&ctx, &mut sampler); + coord.run_threaded(&ctx, &mut sampler, 8); } let image = film.finalize_image(); diff --git a/src/render/coordinator.rs b/src/render/coordinator.rs index a9a7d06..a8d8afb 100644 --- a/src/render/coordinator.rs +++ b/src/render/coordinator.rs @@ -7,7 +7,8 @@ use crate::camera::Film; use crate::core::{Bound2i, Vector2i}; use crate::sample::Sampler; -use std::sync::Mutex; +use std::sync::{Arc, Mutex}; +use std::thread; struct Tiler { tilesize: Vector2i, @@ -112,4 +113,15 @@ impl<'a> RenderCoord<'a> { self.finish_task(&task); } } + + pub fn run_threaded(&self, ctx: &RenderContext, sampler: &mut (dyn Sampler + Send), threads: u32) { + crossbeam::scope(|scope| { + for _ in 0..threads { + let mut sampler = sampler.clone_and_seed(); + scope.spawn(move |_| { + self.work(ctx, sampler.as_mut()); + }); + } + }).unwrap(); + } } diff --git a/src/sample/mod.rs b/src/sample/mod.rs index 88e1aa9..1a53921 100644 --- a/src/sample/mod.rs +++ b/src/sample/mod.rs @@ -16,6 +16,8 @@ pub trait Sampler { Vector2f::new_xy(self.get_sample(), self.get_sample()) } + fn clone_and_seed(&mut self) -> Box<dyn Sampler + Send>; + fn get_unit_vector(&mut self) -> Vector3f { let s2d = self.get_sample_2d(); diff --git a/src/sample/uniform.rs b/src/sample/uniform.rs index 2cd3156..c144f27 100644 --- a/src/sample/uniform.rs +++ b/src/sample/uniform.rs @@ -30,4 +30,10 @@ impl Sampler for UniformSampler { fn get_sample(&mut self) -> Float { self.d.sample(&mut self.r) } + + fn clone_and_seed(&mut self) -> Box<dyn Sampler + Send> { + let mut n = self.clone(); + n.r = Pcg32::seed_from_u64(self.r.next_u64()); + Box::new(n) + } } diff --git a/src/world/mod.rs b/src/world/mod.rs index ef239db..f0ba8d2 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -4,17 +4,17 @@ pub mod shapes; mod scene; pub use scene::*; -use std::rc::Rc; +use std::sync::Arc; use crate::core::Hittable; use crate::material::Material; pub struct Object { - pub shape: Box<dyn Hittable>, - pub mat: Rc<dyn Material>, + pub shape: Box<dyn Hittable + Sync>, + pub mat: Arc<dyn Material + Sync + Send>, } impl Object { - pub fn new(mat: Rc<dyn Material>, shape: Box<dyn Hittable>) -> Self { + pub fn new(mat: Arc<dyn Material + Sync + Send>, shape: Box<dyn Hittable + Sync>) -> Self { Object { mat, shape, |