Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_solari/src/pathtracer/node.rs
9353 views
1
use super::{prepare::PathtracerAccumulationTexture, Pathtracer};
2
use crate::scene::RaytracingSceneBindings;
3
use bevy_asset::{load_embedded_asset, AssetServer};
4
use bevy_ecs::{prelude::*, resource::Resource, system::Commands};
5
use bevy_render::{
6
camera::ExtractedCamera,
7
render_resource::{
8
binding_types::{texture_storage_2d, uniform_buffer},
9
BindGroupEntries, BindGroupLayoutDescriptor, BindGroupLayoutEntries,
10
CachedComputePipelineId, ComputePassDescriptor, ComputePipelineDescriptor,
11
ImageSubresourceRange, PipelineCache, ShaderStages, StorageTextureAccess, TextureFormat,
12
},
13
renderer::{RenderContext, RenderDevice, ViewQuery},
14
view::{ViewTarget, ViewUniform, ViewUniformOffset, ViewUniforms},
15
};
16
use bevy_utils::default;
17
18
/// Resource holding the pathtracer pipeline configuration.
19
#[derive(Resource)]
20
pub struct PathtracerPipelines {
21
bind_group_layout: BindGroupLayoutDescriptor,
22
pipeline: CachedComputePipelineId,
23
}
24
25
/// Initializes the pathtracer pipelines at render startup.
26
pub fn init_pathtracer_pipelines(
27
mut commands: Commands,
28
pipeline_cache: Res<PipelineCache>,
29
scene_bindings: Res<RaytracingSceneBindings>,
30
asset_server: Res<AssetServer>,
31
) {
32
let bind_group_layout = BindGroupLayoutDescriptor::new(
33
"pathtracer_bind_group_layout",
34
&BindGroupLayoutEntries::sequential(
35
ShaderStages::COMPUTE,
36
(
37
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::ReadWrite),
38
texture_storage_2d(
39
ViewTarget::TEXTURE_FORMAT_HDR,
40
StorageTextureAccess::WriteOnly,
41
),
42
uniform_buffer::<ViewUniform>(true),
43
),
44
),
45
);
46
47
let pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
48
label: Some("pathtracer_pipeline".into()),
49
layout: vec![
50
scene_bindings.bind_group_layout.clone(),
51
bind_group_layout.clone(),
52
],
53
shader: load_embedded_asset!(asset_server.as_ref(), "pathtracer.wgsl"),
54
..default()
55
});
56
57
commands.insert_resource(PathtracerPipelines {
58
bind_group_layout,
59
pipeline,
60
});
61
}
62
63
pub fn pathtracer(
64
view: ViewQuery<(
65
&Pathtracer,
66
&PathtracerAccumulationTexture,
67
&ExtractedCamera,
68
&ViewTarget,
69
&ViewUniformOffset,
70
)>,
71
pathtracer_pipelines: Option<Res<PathtracerPipelines>>,
72
pipeline_cache: Res<PipelineCache>,
73
scene_bindings: Res<RaytracingSceneBindings>,
74
view_uniforms: Res<ViewUniforms>,
75
render_device: Res<RenderDevice>,
76
mut ctx: RenderContext,
77
) {
78
let (pathtracer_settings, accumulation_texture, camera, view_target, view_uniform_offset) =
79
view.into_inner();
80
81
let Some(pathtracer_pipelines) = pathtracer_pipelines else {
82
return;
83
};
84
85
let (Some(pipeline), Some(scene_bind_group), Some(viewport), Some(view_uniforms_binding)) = (
86
pipeline_cache.get_compute_pipeline(pathtracer_pipelines.pipeline),
87
&scene_bindings.bind_group,
88
camera.physical_viewport_size,
89
view_uniforms.uniforms.binding(),
90
) else {
91
return;
92
};
93
94
let bind_group = render_device.create_bind_group(
95
"pathtracer_bind_group",
96
&pipeline_cache.get_bind_group_layout(&pathtracer_pipelines.bind_group_layout),
97
&BindGroupEntries::sequential((
98
&accumulation_texture.0.default_view,
99
view_target.get_unsampled_color_attachment().view,
100
view_uniforms_binding,
101
)),
102
);
103
104
let command_encoder = ctx.command_encoder();
105
106
if pathtracer_settings.reset {
107
command_encoder.clear_texture(
108
&accumulation_texture.0.texture,
109
&ImageSubresourceRange::default(),
110
);
111
}
112
113
let mut pass = command_encoder.begin_compute_pass(&ComputePassDescriptor {
114
label: Some("pathtracer"),
115
timestamp_writes: None,
116
});
117
pass.set_pipeline(pipeline);
118
pass.set_bind_group(0, scene_bind_group, &[]);
119
pass.set_bind_group(1, &bind_group, &[view_uniform_offset.offset]);
120
pass.dispatch_workgroups(viewport.x.div_ceil(8), viewport.y.div_ceil(8), 1);
121
}
122
123