From dd5ac7c5fe336e9cac794cfa72d139613a99b466 Mon Sep 17 00:00:00 2001 From: Yann Herklotz Date: Thu, 30 Apr 2020 15:11:21 +0100 Subject: Add threads using Rayon --- Cargo.lock | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/hittable.rs | 5 ++- src/main.rs | 9 ++-- src/render.rs | 37 ++++++++++++----- src/scene.rs | 4 +- src/sphere.rs | 4 +- 7 files changed, 163 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 700c46b..3416654 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,6 +53,59 @@ dependencies = [ "bitflags", ] +[[package]] +name = "crossbeam-deque" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +dependencies = [ + "autocfg 1.0.0", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg 1.0.0", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "either" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -70,12 +123,28 @@ dependencies = [ "wasi", ] +[[package]] +name = "hermit-abi" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4" +dependencies = [ + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "leela" version = "0.1.0" dependencies = [ "cgmath", "rand 0.7.3", + "rayon", ] [[package]] @@ -84,6 +153,21 @@ version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + +[[package]] +name = "memoffset" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" +dependencies = [ + "autocfg 1.0.0", +] + [[package]] name = "num-traits" version = "0.2.11" @@ -93,6 +177,16 @@ dependencies = [ "autocfg 1.0.0", ] +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "ppv-lite86" version = "0.2.6" @@ -246,6 +340,30 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "rayon" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" +dependencies = [ + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" +dependencies = [ + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "lazy_static", + "num_cpus", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -255,6 +373,12 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 530abd3..3c094a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ edition = "2018" [dependencies] cgmath = "0.17.0" rand = "0.7.3" +rayon = "1.3.0" diff --git a/src/hittable.rs b/src/hittable.rs index 1c61872..dcc5006 100644 --- a/src/hittable.rs +++ b/src/hittable.rs @@ -7,11 +7,12 @@ pub struct Hit<'a> { pub p: Vector3, pub normal: Vector3, pub front_face: bool, - pub material: &'a (dyn Material) + pub material: &'a (dyn Material + std::marker::Sync) } impl<'a> Hit<'a> { - pub fn new(ray: &Ray, t: f64, out_normal: Vector3, material: &'a(dyn Material)) -> Hit<'a> { + pub fn new(ray: &Ray, t: f64, out_normal: Vector3, material: &'a(dyn Material + std::marker::Sync)) + -> Hit<'a> { let front_face = dot(ray.dir, out_normal) < 0.0; let normal = if front_face { out_normal } else { -out_normal }; let p = ray.at(t); diff --git a/src/main.rs b/src/main.rs index 1a0b001..f1a627f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,9 +59,10 @@ pub fn random_scene(rng: &mut ThreadRng) -> scene::Scene { } fn main() { - let image_width = 1200; - let image_height = 800; - let samples = 100; + let image_width = 400; + let image_height = 200; + let samples = 50; + let threads = 1; let max_depth = 50; let aspect_ratio = image_width as f64 / image_height as f64; @@ -78,7 +79,7 @@ fn main() { let camera = camera::Camera::new(&lookfrom, &lookat, &vup, 20.0 * PI / 180.0, aspect_ratio, aperture, dist_to_focus); - render::render(&scene, camera, image_height, image_width, samples, max_depth, &mut rng); + render::render(&scene, &camera, image_height, image_width, samples, max_depth, threads); eprintln!("\nDone") } diff --git a/src/render.rs b/src/render.rs index 740c3eb..47c6698 100644 --- a/src/render.rs +++ b/src/render.rs @@ -1,6 +1,7 @@ use cgmath::prelude::*; use cgmath::{Vector3, vec3}; use rand::prelude::*; +use rayon::prelude::*; use std::f64::INFINITY; use crate::camera::Camera; use crate::scene::Scene; @@ -23,20 +24,34 @@ fn ray_colour(rng: &mut ThreadRng, ray: &Ray, scene: &Scene, depth: i32) -> Vect } } -pub fn render(world: &Scene, camera: Camera, image_height: i32, image_width: i32, - samples: i32, max_depth: i32, rng: &mut ThreadRng) { +pub fn thread_render(world: &Scene, camera: &Camera, rng: &mut ThreadRng, image_height: i32, + image_width: i32, samples: i32, max_depth: i32, i: i32, j: i32) -> Vector3 { + let mut colour = vec3(0.0, 0.0, 0.0); + for _ in 0 .. samples { + let ru: f64 = rng.gen(); + let rv: f64 = rng.gen(); + let u = (i as f64 + ru) / image_width as f64; + let v = ((image_height - 1 - j) as f64 + rv) / image_height as f64; + let ray = camera.get_ray(rng, u, v); + colour += ray_colour(rng, &ray, &world, max_depth); + } + colour +} + +pub fn render(world: &Scene, camera: &Camera, image_height: i32, image_width: i32, + samples: i32, max_depth: i32, threads: i32) { for j in 0 .. image_height { eprint!("\rScanlines: {:3} / {:3}", j+1, image_height); for i in 0 .. image_width { - let mut colour = vec3(0.0, 0.0, 0.0); - for _ in 0 .. samples { - let ru: f64 = rng.gen(); - let rv: f64 = rng.gen(); - let u = (i as f64 + ru) / image_width as f64; - let v = ((image_height - 1 - j) as f64 + rv) / image_height as f64; - let ray = camera.get_ray(rng, u, v); - colour += ray_colour(rng, &ray, &world, max_depth); - } + let colours = (0 .. threads) + .into_par_iter() + .map(|_| { + let mut trng = thread_rng(); + thread_render( + world, camera, &mut trng, image_height, image_width, + samples / threads, max_depth, i, j) + }); + let colour = colours.sum::>(); print_colour(&colour, samples); } } diff --git a/src/scene.rs b/src/scene.rs index 368c784..0aa775c 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -2,7 +2,7 @@ use crate::hittable::{Hittable, Hit}; use crate::ray::Ray; pub struct Scene { - objects: Vec> + objects: Vec> } impl Scene { @@ -10,7 +10,7 @@ impl Scene { Scene { objects: Vec::new() } } - pub fn add(&mut self, obj: Box) { + pub fn add(&mut self, obj: Box) { self.objects.push(obj) } diff --git a/src/sphere.rs b/src/sphere.rs index 9ea9081..f1c88b6 100644 --- a/src/sphere.rs +++ b/src/sphere.rs @@ -8,11 +8,11 @@ use crate::ray::Ray; pub struct Sphere { center: Vector3, radius: f64, - material: Box + material: Box } impl Sphere { - pub fn new(center: Vector3, radius: f64, material: Box) -> Sphere { + pub fn new(center: Vector3, radius: f64, material: Box) -> Sphere { Sphere { center, radius, material } } } -- cgit