From 14f7b47f2c2315d0de5e52d31c57fe07a15d08ad Mon Sep 17 00:00:00 2001 From: Julian T Date: Fri, 12 Feb 2021 23:33:50 +0100 Subject: Implement multithreaded compiling of tiles --- Cargo.lock | 25 +++++++++++++++++++++++++ Cargo.toml | 1 + src/main.rs | 12 ++++++------ src/render/coordinator.rs | 14 +++++++++++++- src/sample/mod.rs | 2 ++ src/sample/uniform.rs | 6 ++++++ src/world/mod.rs | 8 ++++---- 7 files changed, 57 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c9f49c0..370504f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,6 +63,20 @@ dependencies = [ "cfg-if", ] +[[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" @@ -98,6 +112,16 @@ dependencies = [ "scopeguard", ] +[[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" @@ -370,6 +394,7 @@ dependencies = [ name = "rendering" version = "0.1.0" dependencies = [ + "crossbeam", "image", "rand", "rand_pcg", diff --git a/Cargo.toml b/Cargo.toml index 09f2c2e..629e22f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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; + 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 { + 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, - pub mat: Rc, + pub shape: Box, + pub mat: Arc, } impl Object { - pub fn new(mat: Rc, shape: Box) -> Self { + pub fn new(mat: Arc, shape: Box) -> Self { Object { mat, shape, -- cgit v1.2.3