Threads pass back small images instead of sharing large image

This commit is contained in:
Matthew Gordon 2020-02-28 21:42:19 -05:00
parent a04f51998c
commit 0574dff685
4 changed files with 39 additions and 44 deletions

View File

@ -6,10 +6,11 @@ use super::integrators::{DirectionalLight, Integrator, WhittedIntegrator};
use super::raycasting::Ray; use super::raycasting::Ray;
use super::sampler::Sampler; use super::sampler::Sampler;
use super::scene::Scene; use super::scene::Scene;
use super::util::Tile;
use crate::Real; use crate::Real;
use std::sync::{Arc, Mutex}; use std::sync::Arc;
struct ImageSampler<T: Real> { struct ImageSampler<T: Real> {
image_height_pixels: usize, image_height_pixels: usize,
@ -66,22 +67,13 @@ impl<T: Real> ImageSampler<T> {
} }
} }
pub fn render_scene<T: Real>(output_image: Arc<Mutex<ImageRgbF<T>>>, scene: Arc<Scene<T>>) {
let height = output_image.lock().unwrap().get_height();
let width = output_image.lock().unwrap().get_width();
partial_render_scene(output_image, scene, 0, height, 0, width, height, width)
}
pub fn partial_render_scene<T: Real>( pub fn partial_render_scene<T: Real>(
output_image: Arc<Mutex<ImageRgbF<T>>>,
scene: Arc<Scene<T>>, scene: Arc<Scene<T>>,
row_start: usize, tile: Tile,
row_end: usize,
column_start: usize,
column_end: usize,
height: usize, height: usize,
width: usize, width: usize,
) { ) -> (Tile, ImageRgbF<T>) {
let mut output_image_tile = ImageRgbF::new(tile.width(), tile.height());
let image_sampler = ImageSampler::new(width, height, scene.camera_location); let image_sampler = ImageSampler::new(width, height, scene.camera_location);
let ambient_intensity: T = convert(0.0); let ambient_intensity: T = convert(0.0);
let directional_intensity1: T = convert(7.0); let directional_intensity1: T = convert(7.0);
@ -105,18 +97,18 @@ pub fn partial_render_scene<T: Real>(
], ],
}; };
let sampler = Sampler { scene: &scene }; let sampler = Sampler { scene: &scene };
for column in column_start..column_end { for column in 0..tile.width() {
for row in row_start..row_end { for row in 0..tile.height() {
let ray = image_sampler.ray_for_pixel(row, column); let ray = image_sampler.ray_for_pixel(tile.start_row + row, tile.end_column + column);
let hit = sampler.sample(&ray); let hit = sampler.sample(&ray);
let colour = match hit { let colour = match hit {
None => ColourRgbF::from_named(NamedColour::Black), None => ColourRgbF::from_named(NamedColour::Black),
Some(intersection_info) => integrator.integrate(&sampler, &intersection_info), Some(intersection_info) => integrator.integrate(&sampler, &intersection_info),
}; };
let mut locked_image = output_image.lock().unwrap(); output_image_tile.set_colour(row, column, colour);
locked_image.set_colour(row, column, colour);
} }
} }
(tile, output_image_tile)
} }
#[cfg(test)] #[cfg(test)]

View File

@ -3,6 +3,7 @@ use rayon::prelude::*;
use sdl2::event::Event; use sdl2::event::Event;
use sdl2::keyboard::Keycode; use sdl2::keyboard::Keycode;
use sdl2::pixels::PixelFormatEnum; use sdl2::pixels::PixelFormatEnum;
use sdl2::rect::Rect;
use sdl2::render::{Canvas, Texture}; use sdl2::render::{Canvas, Texture};
use sdl2::Sdl; use sdl2::Sdl;
use std::time::Duration; use std::time::Duration;
@ -11,21 +12,26 @@ use nalgebra::{Point3, Vector3};
use std::path::Path; use std::path::Path;
use std::sync::mpsc; use std::sync::mpsc;
use std::sync::{Arc, Mutex}; use std::sync::Arc;
use vanrijn::camera::partial_render_scene; use vanrijn::camera::partial_render_scene;
use vanrijn::colour::{ColourRgbF, NamedColour}; use vanrijn::colour::{ColourRgbF, NamedColour};
use vanrijn::image::{ClampingToneMapper, ImageRgbF, ImageRgbU8, ToneMapper}; use vanrijn::image::{ClampingToneMapper, ImageRgbU8, ToneMapper};
use vanrijn::materials::{LambertianMaterial, PhongMaterial, ReflectiveMaterial}; use vanrijn::materials::{LambertianMaterial, PhongMaterial, ReflectiveMaterial};
use vanrijn::mesh::load_obj; use vanrijn::mesh::load_obj;
use vanrijn::raycasting::{Plane, Primitive, Sphere}; use vanrijn::raycasting::{Plane, Primitive, Sphere};
use vanrijn::scene::Scene; use vanrijn::scene::Scene;
use vanrijn::util::TileIterator; use vanrijn::util::{Tile, TileIterator};
fn update_texture(image: &ImageRgbU8, texture: &mut Texture) { fn update_texture(tile: &Tile, image: &ImageRgbU8, texture: &mut Texture) {
texture texture
.update( .update(
None, Rect::new(
tile.start_column as i32,
texture.query().height as i32 - (tile.start_row as i32 + tile.height() as i32),
tile.width() as u32,
tile.height() as u32,
),
image.get_pixel_data().as_slice(), image.get_pixel_data().as_slice(),
(image.get_width() * ImageRgbU8::num_channels()) as usize, (image.get_width() * ImageRgbU8::num_channels()) as usize,
) )
@ -61,7 +67,6 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
image_width as u32, image_width as u32,
image_height as u32, image_height as u32,
)?; )?;
let output_image = Arc::new(Mutex::new(ImageRgbF::<f64>::new(image_width, image_height)));
let scene = Arc::new(Scene { let scene = Arc::new(Scene {
camera_location: Point3::new(-2.0, 1.0, -5.0), camera_location: Point3::new(-2.0, 1.0, -5.0),
@ -121,38 +126,27 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
let (tile_tx, tile_rx) = mpsc::channel(); let (tile_tx, tile_rx) = mpsc::channel();
let mut tile_rx = Some(tile_rx); let mut tile_rx = Some(tile_rx);
let output_image_workers = Arc::clone(&output_image);
let worker_boss = std::thread::spawn(move || { let worker_boss = std::thread::spawn(move || {
TileIterator::new(image_width as usize, image_height as usize, 16) TileIterator::new(image_width as usize, image_height as usize, 8)
.map(move |tile| (tile, tile_tx.clone())) .map(move |tile| (tile, tile_tx.clone()))
.par_bridge() .par_bridge()
.try_for_each(|(tile, tx)| { .try_for_each(|(tile, tx)| {
let image_ptr = Arc::clone(&output_image_workers);
let scene_ptr = scene.clone(); let scene_ptr = scene.clone();
partial_render_scene( let rendered_tile =
image_ptr, partial_render_scene(scene_ptr, tile, image_height, image_width);
scene_ptr,
tile.start_row,
tile.end_row,
tile.start_column,
tile.end_column,
image_height,
image_width,
);
// There's nothing we can do if this fails, and we're already // There's nothing we can do if this fails, and we're already
// at the end of the function anyway, so just ignore result. // at the end of the function anyway, so just ignore result.
tx.send(tile).ok() tx.send(rendered_tile).ok()
}); });
}); });
'running: loop { 'running: loop {
if let Some(ref tile_rx) = tile_rx { if let Some(ref tile_rx) = tile_rx {
for tile in tile_rx.try_iter() { for (tile, tile_image) in tile_rx.try_iter() {
let locked_image = output_image.lock().unwrap(); let mut tile_image_rgbu8 = ImageRgbU8::new(tile.width(), tile.height());
let mut output_image_rgbu8 = ImageRgbU8::new(image_width, image_height); ClampingToneMapper {}.apply_tone_mapping(&tile_image, &mut tile_image_rgbu8);
ClampingToneMapper {}.apply_tone_mapping(&locked_image, &mut output_image_rgbu8); update_texture(&tile, &tile_image_rgbu8, &mut rendered_image_texture);
update_texture(&output_image_rgbu8, &mut rendered_image_texture);
canvas.copy(&rendered_image_texture, None, None).unwrap(); canvas.copy(&rendered_image_texture, None, None).unwrap();
canvas.present(); canvas.present();
} }

View File

@ -1,4 +1,4 @@
use nalgebra::{Point2, Point3}; use nalgebra::Point3;
use crate::Real; use crate::Real;

View File

@ -6,6 +6,15 @@ pub struct Tile {
pub end_row: usize, pub end_row: usize,
} }
impl Tile {
pub fn width(&self) -> usize {
self.end_column - self.start_column
}
pub fn height(&self) -> usize {
self.end_row - self.start_row
}
}
pub struct TileIterator { pub struct TileIterator {
tile_size: usize, tile_size: usize,
total_height: usize, total_height: usize,