From c42b04321683fb8979941c845a84d32592b6e279 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 3 Oct 2024 22:55:14 -0700 Subject: [PATCH] Ensure previous light diffuse isn't used if not initialized --- blade-render/code/ray-trace.wgsl | 13 +++++----- blade-render/src/render/mod.rs | 44 ++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/blade-render/code/ray-trace.wgsl b/blade-render/code/ray-trace.wgsl index 27e41ba..e5ecec9 100644 --- a/blade-render/code/ray-trace.wgsl +++ b/blade-render/code/ray-trace.wgsl @@ -350,6 +350,8 @@ fn produce_canonical(surface: Surface, position: vec3, rng: ptr, pixel: vec2, rng: ptr ) -> Neighborhood { - if (surface.depth == 0.0) { + if (surface.depth == 0.0 || parameters.temporal_tap == 0u) { return Neighborhood(); } @@ -409,7 +411,7 @@ fn gather_neighborhood_temporal( fn gather_neighborhood_spatial( surface: Surface, pixel: vec2, rng: ptr ) -> Neighborhood { - if (surface.depth == 0.0) { + if (surface.depth == 0.0 || parameters.spatial_taps == 0u) { return Neighborhood(); } @@ -574,9 +576,9 @@ fn main(@builtin(global_invocation_id) global_id: vec3) { let neighborhood = gather_neighborhood_temporal(surface, position, pixel, &rng); let canonical = produce_canonical(surface, position, &rng, enable_debug); let ro = compute_restir(surface, ray_dir, canonical, neighborhood, parameters.temporal_history, &rng, enable_debug); + let pixel_index = get_reservoir_index(pixel, camera); reservoirs[pixel_index] = ro.reservoir; - textureStore(out_diffuse, pixel, vec4(ro.radiance, 1.0)); } @@ -586,9 +588,6 @@ fn main_spatial(@builtin(global_invocation_id) global_id: vec3) { return; } - let global_index = global_id.y * camera.target_size.x + global_id.x; - var rng = random_init(global_index, parameters.frame_index * 2u); - let surface = read_surface(vec2(global_id.xy)); let pixel = vec2(global_id.xy); let pixel_index = get_reservoir_index(pixel, camera); @@ -601,6 +600,8 @@ fn main_spatial(@builtin(global_invocation_id) global_id: vec3) { } let enable_debug = DEBUG_MODE && all(global_id.xy == debug.mouse_pos); + let global_index = global_id.y * camera.target_size.x + global_id.x; + var rng = random_init(global_index, parameters.frame_index * 2u); let neighborhood = gather_neighborhood_spatial(surface, pixel, &rng); let old_reservoir = prev_reservoirs[pixel_index]; diff --git a/blade-render/src/render/mod.rs b/blade-render/src/render/mod.rs index 9df66c6..67952b7 100644 --- a/blade-render/src/render/mod.rs +++ b/blade-render/src/render/mod.rs @@ -341,6 +341,7 @@ pub struct Renderer { surface_info: blade_graphics::SurfaceInfo, frame_index: usize, frame_scene_built: usize, + frame_resize: usize, is_frozen: bool, //TODO: refactor `ResourceArray` to not carry the freelist logic // This way we can embed user info into the allocator. @@ -752,6 +753,7 @@ impl Renderer { surface_info: config.surface_info, frame_index: 0, frame_scene_built: 0, + frame_resize: 0, is_frozen: false, texture_resource_lookup: HashMap::default(), } @@ -877,6 +879,7 @@ impl Renderer { self.surface_size = size; self.targets.destroy(gpu); self.targets = RestirTargets::new(size, self.reservoir_size, encoder, gpu); + self.frame_resize = self.frame_index + 1; } #[profiling::function] @@ -1117,7 +1120,7 @@ impl Renderer { } self.debug.update_entry(&mut transfer); - if config.reset_reservoirs { + if config.reset_reservoirs || self.frame_resize == self.frame_index { if !config.debug_draw { self.debug.reset_lines(&mut transfer); } @@ -1143,7 +1146,7 @@ impl Renderer { /// The result is stored internally in an HDR render target. #[profiling::function] pub fn ray_trace( - &self, + &mut self, command_encoder: &mut blade_graphics::CommandEncoder, debug_config: DebugConfig, ray_config: RayConfig, @@ -1233,9 +1236,10 @@ impl Renderer { ); pc.dispatch(groups); } + //Note: output reservoirs and lighting is in [1] - //TODO: control by `ray_config.spatial_pass` - if let mut pass = command_encoder.compute("ray-trace-spatial") { + if ray_config.spatial_pass { + let mut pass = command_encoder.compute("ray-trace-spatial"); let mut pc = pass.with(&self.spatial_pipeline); let groups = self.spatial_pipeline.get_dispatch_for(self.surface_size); pc.bind( @@ -1267,19 +1271,27 @@ impl Renderer { }, ); pc.dispatch(groups); + } else { + self.targets.reservoir_buf.swap(0, 1); + self.targets.light_diffuse.views.swap(0, 1); } + //Note: output reservoirs and lighting is in [0] } /// Perform noise reduction using SVGF. #[profiling::function] pub fn denoise( - &mut self, //TODO: borrow immutably + &mut self, command_encoder: &mut blade_graphics::CommandEncoder, denoiser_config: DenoiserConfig, ) { let mut params = BlurParams { extent: [self.surface_size.width, self.surface_size.height], - temporal_weight: denoiser_config.temporal_weight, + temporal_weight: if self.frame_resize < self.frame_index { + denoiser_config.temporal_weight + } else { + 1.0 + }, iteration: 0, use_motion_vectors: (self.frame_scene_built >= self.frame_index) as u32, pad: 0, @@ -1305,16 +1317,18 @@ impl Renderer { t_flat_normal: self.targets.flat_normal.views[cur], t_prev_flat_normal: self.targets.flat_normal.views[prev], t_motion: self.targets.motion.views[0], - output: self.targets.light_diffuse.views[1], + output: self.targets.light_diffuse.views[0], }, ); pc.dispatch(groups); - //Note: making `2` contain the latest reprojection output - self.targets.light_diffuse.views.swap(1, 2); } + // Make sure the accumulated result is in [2] + self.targets.light_diffuse.views.swap(0, 2); + + let mut input_index = 2; for _ in 0..denoiser_config.num_passes { - self.targets.light_diffuse.views.swap(0, 1); + let output_index = if input_index == 0 { 1 } else { 0 }; let mut pass = command_encoder.compute("a-trous"); let mut pc = pass.with(&self.blur.a_trous_pipeline); let groups = self @@ -1325,16 +1339,20 @@ impl Renderer { 0, &ATrousData { params, - input: self.targets.light_diffuse.views - [if params.iteration == 0 { 2 } else { 1 }], + input: self.targets.light_diffuse.views[input_index], t_depth: self.targets.depth.views[cur], t_flat_normal: self.targets.flat_normal.views[cur], - output: self.targets.light_diffuse.views[0], + output: self.targets.light_diffuse.views[output_index], }, ); pc.dispatch(groups); params.iteration += 1; + input_index = output_index; + } + if input_index != 0 { + self.targets.light_diffuse.views.swap(0, input_index); } + //Note: output lighting is in [0] } /// Blit the rendering result into a specified render pass.