diff --git a/Cargo.lock b/Cargo.lock index eba2235..3de2d9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -59,6 +59,51 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +dependencies = [ + "cfg-if", + "lazy_static", +] + [[package]] name = "deflate" version = "1.0.0" @@ -68,6 +113,12 @@ dependencies = [ "adler32", ] +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + [[package]] name = "getrandom" version = "0.2.6" @@ -79,6 +130,15 @@ dependencies = [ "wasi", ] +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "image" version = "0.24.2" @@ -101,12 +161,27 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.5.3" @@ -157,6 +232,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "png" version = "0.17.5" @@ -205,14 +290,45 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "renderer" version = "0.1.0" dependencies = [ "image", "rand", + "rayon", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 0e31dc3..d994160 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ edition = "2021" [dependencies] image = { version = "0.24.2", default-features = false, features = ["jpeg", "png", "pnm"] } -rand = { version = "0.8.5", features = ["small_rng"] } \ No newline at end of file +rand = { version = "0.8.5", features = ["small_rng"] } +rayon = "1.5.3" \ No newline at end of file diff --git a/src/hittable.rs b/src/hittable.rs index f77a8de..708f514 100644 --- a/src/hittable.rs +++ b/src/hittable.rs @@ -14,7 +14,7 @@ pub struct Sphere { radius: f64, } -pub trait Hittable { +pub trait Hittable: Sync+Send { fn hit(&self, r: &Ray, t_min: f64, t_max: f64, rec: &mut HitRecord) -> bool; } diff --git a/src/main.rs b/src/main.rs index e525991..769c145 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ mod utility; mod vec3; use std::env; +use std::sync::atomic::AtomicU32; //use std::fs::File; //use std::io::BufWriter; //use std::io::Write; @@ -18,6 +19,7 @@ use hittable_list::HittableList; use image::{Rgb, RgbImage}; use ray::Ray; use vec3::{Color, Point3, Vec3}; +use rayon::prelude::*; fn ray_color(r: &Ray, world: &HittableList, depth: u32) -> Color { let mut rec = HitRecord::empty(); @@ -91,27 +93,38 @@ fn main() { //let mut file = BufWriter::new(File::create(default_file).unwrap()); //writeln!(&mut file, "P3\n{image_width} {image_height}\n255\n").unwrap(); - for j in (0..image_height).rev() { - eprint!("\rScanlines remaining: {j:5}"); + let mut atomic_counter = AtomicU32::new(image_height); + let color_lines: Vec<_> = (0..image_height).into_par_iter().rev().map(|j| { + eprint!("\rScanlines remaining: {:5}", *atomic_counter.get_mut()); + let mut colors = Vec::new(); for i in 0..image_width { let mut pixel_color = Color::new(0.0, 0.0, 0.0); for _ in 0..samples_per_pixel { let u = (i as f64 + utility::random_f64()) / (image_width - 1) as f64; let v = (j as f64 + utility::random_f64()) / (image_height - 1) as f64; let r = cam.get_ray(u, v); - pixel_color += ray_color(&r, &mut world, max_depth); + pixel_color += ray_color(&r, &world, max_depth); } + colors.push(pixel_color); + } + *atomic_counter.get_mut() -= 1; + return colors; + } ).collect(); + + (0..image_height).into_iter().rev().for_each(|j| { + (0..image_width).into_iter().for_each(|i| { //color::write_color(&mut file, &pixel_color); color::put_color( &mut image, - &pixel_color, + &color_lines[(image_height - j - 1) as usize][i as usize], i, image_height - j - 1, samples_per_pixel, ); - } - } + }) + }); + image.save(default_file).unwrap(); eprintln!("\nDone!"); }