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