Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_post_process/src/auto_exposure/node.rs
6596 views
1
use super::{
2
buffers::AutoExposureBuffers,
3
compensation_curve::GpuAutoExposureCompensationCurve,
4
pipeline::{AutoExposurePipeline, ViewAutoExposurePipeline},
5
AutoExposureResources,
6
};
7
use bevy_ecs::{
8
query::QueryState,
9
system::lifetimeless::Read,
10
world::{FromWorld, World},
11
};
12
use bevy_render::{
13
diagnostic::RecordDiagnostics,
14
globals::GlobalsBuffer,
15
render_asset::RenderAssets,
16
render_graph::*,
17
render_resource::*,
18
renderer::RenderContext,
19
texture::{FallbackImage, GpuImage},
20
view::{ExtractedView, ViewTarget, ViewUniform, ViewUniformOffset, ViewUniforms},
21
};
22
23
#[derive(RenderLabel, Debug, Clone, Hash, PartialEq, Eq)]
24
pub struct AutoExposure;
25
26
pub struct AutoExposureNode {
27
query: QueryState<(
28
Read<ViewUniformOffset>,
29
Read<ViewTarget>,
30
Read<ViewAutoExposurePipeline>,
31
Read<ExtractedView>,
32
)>,
33
}
34
35
impl FromWorld for AutoExposureNode {
36
fn from_world(world: &mut World) -> Self {
37
Self {
38
query: QueryState::new(world),
39
}
40
}
41
}
42
43
impl Node for AutoExposureNode {
44
fn update(&mut self, world: &mut World) {
45
self.query.update_archetypes(world);
46
}
47
48
fn run(
49
&self,
50
graph: &mut RenderGraphContext,
51
render_context: &mut RenderContext,
52
world: &World,
53
) -> Result<(), NodeRunError> {
54
let view_entity = graph.view_entity();
55
let pipeline_cache = world.resource::<PipelineCache>();
56
let pipeline = world.resource::<AutoExposurePipeline>();
57
let resources = world.resource::<AutoExposureResources>();
58
59
let view_uniforms_resource = world.resource::<ViewUniforms>();
60
let view_uniforms = &view_uniforms_resource.uniforms;
61
let view_uniforms_buffer = view_uniforms.buffer().unwrap();
62
63
let globals_buffer = world.resource::<GlobalsBuffer>();
64
65
let auto_exposure_buffers = world.resource::<AutoExposureBuffers>();
66
67
let (
68
Ok((view_uniform_offset, view_target, auto_exposure, view)),
69
Some(auto_exposure_buffers),
70
) = (
71
self.query.get_manual(world, view_entity),
72
auto_exposure_buffers.buffers.get(&view_entity),
73
)
74
else {
75
return Ok(());
76
};
77
78
let (Some(histogram_pipeline), Some(average_pipeline)) = (
79
pipeline_cache.get_compute_pipeline(auto_exposure.histogram_pipeline),
80
pipeline_cache.get_compute_pipeline(auto_exposure.mean_luminance_pipeline),
81
) else {
82
return Ok(());
83
};
84
85
let source = view_target.main_texture_view();
86
87
let fallback = world.resource::<FallbackImage>();
88
let mask = world
89
.resource::<RenderAssets<GpuImage>>()
90
.get(&auto_exposure.metering_mask);
91
let mask = mask
92
.map(|i| &i.texture_view)
93
.unwrap_or(&fallback.d2.texture_view);
94
95
let Some(compensation_curve) = world
96
.resource::<RenderAssets<GpuAutoExposureCompensationCurve>>()
97
.get(&auto_exposure.compensation_curve)
98
else {
99
return Ok(());
100
};
101
102
let diagnostics = render_context.diagnostic_recorder();
103
104
let compute_bind_group = render_context.render_device().create_bind_group(
105
None,
106
&pipeline.histogram_layout,
107
&BindGroupEntries::sequential((
108
&globals_buffer.buffer,
109
&auto_exposure_buffers.settings,
110
source,
111
mask,
112
&compensation_curve.texture_view,
113
&compensation_curve.extents,
114
resources.histogram.as_entire_buffer_binding(),
115
&auto_exposure_buffers.state,
116
BufferBinding {
117
buffer: view_uniforms_buffer,
118
size: Some(ViewUniform::min_size()),
119
offset: 0,
120
},
121
)),
122
);
123
124
let mut compute_pass =
125
render_context
126
.command_encoder()
127
.begin_compute_pass(&ComputePassDescriptor {
128
label: Some("auto_exposure"),
129
timestamp_writes: None,
130
});
131
let pass_span = diagnostics.time_span(&mut compute_pass, "auto_exposure");
132
133
compute_pass.set_bind_group(0, &compute_bind_group, &[view_uniform_offset.offset]);
134
compute_pass.set_pipeline(histogram_pipeline);
135
compute_pass.dispatch_workgroups(
136
view.viewport.z.div_ceil(16),
137
view.viewport.w.div_ceil(16),
138
1,
139
);
140
compute_pass.set_pipeline(average_pipeline);
141
compute_pass.dispatch_workgroups(1, 1, 1);
142
143
pass_span.end(&mut compute_pass);
144
145
Ok(())
146
}
147
}
148
149