Path: blob/main/crates/bevy_solari/src/pathtracer/node.rs
6596 views
use super::{prepare::PathtracerAccumulationTexture, Pathtracer};1use crate::scene::RaytracingSceneBindings;2use bevy_asset::load_embedded_asset;3use bevy_ecs::{4query::QueryItem,5world::{FromWorld, World},6};7use bevy_render::{8camera::ExtractedCamera,9render_graph::{NodeRunError, RenderGraphContext, ViewNode},10render_resource::{11binding_types::{texture_storage_2d, uniform_buffer},12BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries, CachedComputePipelineId,13ComputePassDescriptor, ComputePipelineDescriptor, ImageSubresourceRange, PipelineCache,14ShaderStages, StorageTextureAccess, TextureFormat,15},16renderer::{RenderContext, RenderDevice},17view::{ViewTarget, ViewUniform, ViewUniformOffset, ViewUniforms},18};19use bevy_utils::default;2021pub mod graph {22use bevy_render::render_graph::RenderLabel;2324#[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)]25pub struct PathtracerNode;26}2728pub struct PathtracerNode {29bind_group_layout: BindGroupLayout,30pipeline: CachedComputePipelineId,31}3233impl ViewNode for PathtracerNode {34type ViewQuery = (35&'static Pathtracer,36&'static PathtracerAccumulationTexture,37&'static ExtractedCamera,38&'static ViewTarget,39&'static ViewUniformOffset,40);4142fn run(43&self,44_graph: &mut RenderGraphContext,45render_context: &mut RenderContext,46(pathtracer, accumulation_texture, camera, view_target, view_uniform_offset): QueryItem<47Self::ViewQuery,48>,49world: &World,50) -> Result<(), NodeRunError> {51let pipeline_cache = world.resource::<PipelineCache>();52let scene_bindings = world.resource::<RaytracingSceneBindings>();53let view_uniforms = world.resource::<ViewUniforms>();54let (Some(pipeline), Some(scene_bindings), Some(viewport), Some(view_uniforms)) = (55pipeline_cache.get_compute_pipeline(self.pipeline),56&scene_bindings.bind_group,57camera.physical_viewport_size,58view_uniforms.uniforms.binding(),59) else {60return Ok(());61};6263let bind_group = render_context.render_device().create_bind_group(64"pathtracer_bind_group",65&self.bind_group_layout,66&BindGroupEntries::sequential((67&accumulation_texture.0.default_view,68view_target.get_unsampled_color_attachment().view,69view_uniforms,70)),71);7273let command_encoder = render_context.command_encoder();7475if pathtracer.reset {76command_encoder.clear_texture(77&accumulation_texture.0.texture,78&ImageSubresourceRange::default(),79);80}8182let mut pass = command_encoder.begin_compute_pass(&ComputePassDescriptor {83label: Some("pathtracer"),84timestamp_writes: None,85});86pass.set_pipeline(pipeline);87pass.set_bind_group(0, scene_bindings, &[]);88pass.set_bind_group(1, &bind_group, &[view_uniform_offset.offset]);89pass.dispatch_workgroups(viewport.x.div_ceil(8), viewport.y.div_ceil(8), 1);9091Ok(())92}93}9495impl FromWorld for PathtracerNode {96fn from_world(world: &mut World) -> Self {97let render_device = world.resource::<RenderDevice>();98let pipeline_cache = world.resource::<PipelineCache>();99let scene_bindings = world.resource::<RaytracingSceneBindings>();100101let bind_group_layout = render_device.create_bind_group_layout(102"pathtracer_bind_group_layout",103&BindGroupLayoutEntries::sequential(104ShaderStages::COMPUTE,105(106texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::ReadWrite),107texture_storage_2d(108ViewTarget::TEXTURE_FORMAT_HDR,109StorageTextureAccess::WriteOnly,110),111uniform_buffer::<ViewUniform>(true),112),113),114);115116let pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {117label: Some("pathtracer_pipeline".into()),118layout: vec![119scene_bindings.bind_group_layout.clone(),120bind_group_layout.clone(),121],122shader: load_embedded_asset!(world, "pathtracer.wgsl"),123..default()124});125126Self {127bind_group_layout,128pipeline,129}130}131}132133134