Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_anti_alias/src/contrast_adaptive_sharpening/node.rs
6596 views
1
use std::sync::Mutex;
2
3
use crate::contrast_adaptive_sharpening::ViewCasPipeline;
4
use bevy_ecs::prelude::*;
5
use bevy_render::{
6
diagnostic::RecordDiagnostics,
7
extract_component::{ComponentUniforms, DynamicUniformIndex},
8
render_graph::{Node, NodeRunError, RenderGraphContext},
9
render_resource::{
10
BindGroup, BindGroupEntries, BufferId, Operations, PipelineCache,
11
RenderPassColorAttachment, RenderPassDescriptor, TextureViewId,
12
},
13
renderer::RenderContext,
14
view::{ExtractedView, ViewTarget},
15
};
16
17
use super::{CasPipeline, CasUniform};
18
19
pub struct CasNode {
20
query: QueryState<
21
(
22
&'static ViewTarget,
23
&'static ViewCasPipeline,
24
&'static DynamicUniformIndex<CasUniform>,
25
),
26
With<ExtractedView>,
27
>,
28
cached_bind_group: Mutex<Option<(BufferId, TextureViewId, BindGroup)>>,
29
}
30
31
impl FromWorld for CasNode {
32
fn from_world(world: &mut World) -> Self {
33
Self {
34
query: QueryState::new(world),
35
cached_bind_group: Mutex::new(None),
36
}
37
}
38
}
39
40
impl Node for CasNode {
41
fn update(&mut self, world: &mut World) {
42
self.query.update_archetypes(world);
43
}
44
45
fn run(
46
&self,
47
graph: &mut RenderGraphContext,
48
render_context: &mut RenderContext,
49
world: &World,
50
) -> Result<(), NodeRunError> {
51
let view_entity = graph.view_entity();
52
let pipeline_cache = world.resource::<PipelineCache>();
53
let sharpening_pipeline = world.resource::<CasPipeline>();
54
let uniforms = world.resource::<ComponentUniforms<CasUniform>>();
55
56
let Ok((target, pipeline, uniform_index)) = self.query.get_manual(world, view_entity)
57
else {
58
return Ok(());
59
};
60
61
let uniforms_id = uniforms.buffer().unwrap().id();
62
let Some(uniforms) = uniforms.binding() else {
63
return Ok(());
64
};
65
66
let Some(pipeline) = pipeline_cache.get_render_pipeline(pipeline.0) else {
67
return Ok(());
68
};
69
70
let diagnostics = render_context.diagnostic_recorder();
71
72
let view_target = target.post_process_write();
73
let source = view_target.source;
74
let destination = view_target.destination;
75
76
let mut cached_bind_group = self.cached_bind_group.lock().unwrap();
77
let bind_group = match &mut *cached_bind_group {
78
Some((buffer_id, texture_id, bind_group))
79
if source.id() == *texture_id && uniforms_id == *buffer_id =>
80
{
81
bind_group
82
}
83
cached_bind_group => {
84
let bind_group = render_context.render_device().create_bind_group(
85
"cas_bind_group",
86
&sharpening_pipeline.texture_bind_group,
87
&BindGroupEntries::sequential((
88
view_target.source,
89
&sharpening_pipeline.sampler,
90
uniforms,
91
)),
92
);
93
94
let (_, _, bind_group) =
95
cached_bind_group.insert((uniforms_id, source.id(), bind_group));
96
bind_group
97
}
98
};
99
100
let pass_descriptor = RenderPassDescriptor {
101
label: Some("contrast_adaptive_sharpening"),
102
color_attachments: &[Some(RenderPassColorAttachment {
103
view: destination,
104
depth_slice: None,
105
resolve_target: None,
106
ops: Operations::default(),
107
})],
108
depth_stencil_attachment: None,
109
timestamp_writes: None,
110
occlusion_query_set: None,
111
};
112
113
let mut render_pass = render_context
114
.command_encoder()
115
.begin_render_pass(&pass_descriptor);
116
let pass_span = diagnostics.time_span(&mut render_pass, "contrast_adaptive_sharpening");
117
118
render_pass.set_pipeline(pipeline);
119
render_pass.set_bind_group(0, bind_group, &[uniform_index.index()]);
120
render_pass.draw(0..3, 0..1);
121
122
pass_span.end(&mut render_pass);
123
124
Ok(())
125
}
126
}
127
128