From 548011ba6316e83c95b327768581d7d53d49a63e Mon Sep 17 00:00:00 2001 From: Sakarias Johansson Date: Fri, 3 Mar 2023 15:56:26 +0100 Subject: =?UTF-8?q?=F0=9F=9B=A0=20Cleanup=20error=20handling=20&=20functio?= =?UTF-8?q?nalize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- racer-tracer/src/render.rs | 220 +++++++++++++++++++++++++-------------------- 1 file changed, 122 insertions(+), 98 deletions(-) (limited to 'racer-tracer/src/render.rs') diff --git a/racer-tracer/src/render.rs b/racer-tracer/src/render.rs index 8e01acb..fefafce 100644 --- a/racer-tracer/src/render.rs +++ b/racer-tracer/src/render.rs @@ -6,6 +6,7 @@ use synchronoise::SignalEvent; use crate::{ camera::Camera, config::RenderData, + error::TracerError, geometry::Hittable, image::{Image, SubImage}, ray::Ray, @@ -41,7 +42,7 @@ pub fn raytrace_scaled( image: &SubImage, data: &RenderData, scale: (usize, usize), -) { +) -> Result<(), TracerError> { let (scale_width, scale_height) = scale; let scaled_width = image.width / scale_width; let scaled_height = image.height / scale_height; @@ -63,33 +64,36 @@ pub fn raytrace_scaled( } if do_cancel(cancel_event) { - return; + return Ok(()); } } - if do_cancel(cancel_event) { - return; - } - - let mut buf = buffer - .write() - .expect("Failed to get write guard when flushing data."); - - let offset = image.y * image.screen_width + image.x; - for scaled_row in 0..scaled_height { - for scaled_col in 0..scaled_width { - let color = colors[scaled_row * scaled_width + scaled_col] - .scale_sqrt(data.samples) - .as_color(); - let row = scaled_row * scale_height; - let col = scaled_col * scale_width; - for scale_h in 0..scale_height { - for scale_w in 0..scale_width { - buf[offset + (row + scale_h) * image.screen_width + col + scale_w] = color; + (!do_cancel(cancel_event)) + .then_some(|| ()) + .ok_or(TracerError::CancelEvent) + .and_then(|_| { + buffer + .write() + .map_err(|e| TracerError::FailedToAcquireLock(e.to_string())) + }) + .map(|mut buf| { + let offset = image.y * image.screen_width + image.x; + for scaled_row in 0..scaled_height { + for scaled_col in 0..scaled_width { + let color = colors[scaled_row * scaled_width + scaled_col] + .scale_sqrt(data.samples) + .as_color(); + let row = scaled_row * scale_height; + let col = scaled_col * scale_width; + for scale_h in 0..scale_height { + for scale_w in 0..scale_width { + buf[offset + (row + scale_h) * image.screen_width + col + scale_w] = + color; + } + } } } - } - } + }) } pub fn raytrace( @@ -99,7 +103,7 @@ pub fn raytrace( camera: Camera, image: &SubImage, data: &RenderData, -) { +) -> Result<(), TracerError> { let mut colors: Vec = vec![Vec3::default(); image.height * image.width]; for row in 0..image.height { for column in 0..image.width { @@ -117,27 +121,29 @@ pub fn raytrace( } if do_cancel(cancel_event) { - return; + return Ok(()); } } - if do_cancel(cancel_event) { - return; - } - - let mut buf = buffer - .write() - .expect("Failed to get write guard when flushing data."); - - let offset = image.y * image.screen_width + image.x; - for row in 0..image.height { - for col in 0..image.width { - let color = colors[row * image.width + col] - .scale_sqrt(data.samples) - .as_color(); - buf[offset + row * image.screen_width + col] = color; - } - } + (!do_cancel(cancel_event)) + .then_some(|| ()) + .ok_or(TracerError::CancelEvent) + .and_then(|_| { + buffer + .write() + .map_err(|e| TracerError::FailedToAcquireLock(e.to_string())) + }) + .map(|mut buf| { + let offset = image.y * image.screen_width + image.x; + for row in 0..image.height { + for col in 0..image.width { + let color = colors[row * image.width + col] + .scale_sqrt(data.samples) + .as_color(); + buf[offset + row * image.screen_width + col] = color; + } + } + }) } fn do_cancel(cancel_event: Option<&SignalEvent>) -> bool { @@ -163,70 +169,88 @@ pub fn render( data: &RenderData, cancel_event: Option<&SignalEvent>, scale: Option, -) { +) -> Result<(), TracerError> { if do_cancel(cancel_event) { - return; + return Ok(()); } - let cam = camera.read().expect("TODO").clone(); + let width_step = image.width / data.num_threads_width; let height_step = image.height / data.num_threads_height; - let scaled_width = scale.map_or(1, |s| get_highest_divdable(width_step, s)); let scaled_height = scale.map_or(1, |s| get_highest_divdable(height_step, s)); - (0..data.num_threads_width) - .flat_map(|ws| { - let subs: Vec = (0..data.num_threads_height) - .map(|hs| SubImage { - x: width_step * ws, - y: height_step * hs, - screen_width: image.width, - screen_height: image.height, - - // Neccesary in case the threads width is not - // evenly divisible by the image width. - width: if ws == data.num_threads_width - 1 { - image.width - width_step * ws - } else { - width_step - }, - - // Neccesary in case the threads height is not - // evenly divisible by the image height. - height: if hs == data.num_threads_height - 1 { - image.height - height_step * hs - } else { - height_step - }, + (!do_cancel(cancel_event)) + .then_some(|| ()) + .ok_or(TracerError::CancelEvent) + .and_then(|_| { + camera + .read() + .map_err(|e| TracerError::FailedToAcquireLock(e.to_string())) + // We make a clone of it as it's not very important to + // have the latest camera angle etc. Better to keep + // the lock to a minimum. + .map(|cam| cam.clone()) + }) + .map(|cam| { + let images = (0..data.num_threads_width) + .flat_map(|ws| { + (0..data.num_threads_height) + .map(|hs| SubImage { + x: width_step * ws, + y: height_step * hs, + screen_width: image.width, + screen_height: image.height, + + // Neccesary in case the threads width is not + // evenly divisible by the image width. + width: if ws == data.num_threads_width - 1 { + image.width - width_step * ws + } else { + width_step + }, + + // Neccesary in case the threads height is not + // evenly divisible by the image height. + height: if hs == data.num_threads_height - 1 { + image.height - height_step * hs + } else { + height_step + }, + }) + .collect::>() }) - .collect(); - subs + .collect::>(); + + (cam, images) }) - .collect::>() - .into_par_iter() - .for_each(|image| { - scale.map_or_else( - || { - raytrace( - buffer, - cancel_event, - (*scene).borrow(), - cam.clone(), - &image, - data, + .and_then(|(cam, sub_images)| { + sub_images + .into_par_iter() + .map(|image| { + scale.map_or_else( + || { + raytrace( + buffer, + cancel_event, + (*scene).borrow(), + cam.clone(), + &image, + data, + ) + }, + |_| { + raytrace_scaled( + buffer, + cancel_event, + (*scene).borrow(), + cam.clone(), + &image, + data, + (scaled_width, scaled_height), + ) + }, ) - }, - |_| { - raytrace_scaled( - buffer, - cancel_event, - (*scene).borrow(), - cam.clone(), - &image, - data, - (scaled_width, scaled_height), - ) - }, - ); - }); + }) + .collect::>() + }) } -- cgit v1.2.3