bevy_render/render_graph/
node.rs1use crate::{
2 render_graph::{
3 Edge, InputSlotError, OutputSlotError, RenderGraphContext, RenderGraphError,
4 RunSubGraphError, SlotInfo, SlotInfos,
5 },
6 render_phase::DrawError,
7 renderer::RenderContext,
8};
9pub use bevy_ecs::label::DynEq;
10use bevy_ecs::{
11 define_label,
12 intern::Interned,
13 query::{QueryItem, QueryState, ReadOnlyQueryData},
14 world::{FromWorld, World},
15};
16use bevy_utils::all_tuples_with_size;
17use core::fmt::Debug;
18use derive_more::derive::{Display, Error, From};
19use downcast_rs::{impl_downcast, Downcast};
20
21pub use bevy_render_macros::RenderLabel;
22
23use super::{InternedRenderSubGraph, RenderSubGraph};
24
25define_label!(
26 RenderLabel,
28 RENDER_LABEL_INTERNER
29);
30
31pub type InternedRenderLabel = Interned<dyn RenderLabel>;
33
34pub trait IntoRenderNodeArray<const N: usize> {
35 fn into_array(self) -> [InternedRenderLabel; N];
36}
37
38macro_rules! impl_render_label_tuples {
39 ($N: expr, $(#[$meta:meta])* $(($T: ident, $I: ident)),*) => {
40 $(#[$meta])*
41 impl<$($T: RenderLabel),*> IntoRenderNodeArray<$N> for ($($T,)*) {
42 #[inline]
43 fn into_array(self) -> [InternedRenderLabel; $N] {
44 let ($($I,)*) = self;
45 [$($I.intern(), )*]
46 }
47 }
48 }
49}
50
51all_tuples_with_size!(
52 #[doc(fake_variadic)]
53 impl_render_label_tuples,
54 1,
55 32,
56 T,
57 l
58);
59
60pub trait Node: Downcast + Send + Sync + 'static {
73 fn input(&self) -> Vec<SlotInfo> {
76 Vec::new()
77 }
78
79 fn output(&self) -> Vec<SlotInfo> {
82 Vec::new()
83 }
84
85 fn update(&mut self, _world: &mut World) {}
87
88 fn run<'w>(
92 &self,
93 graph: &mut RenderGraphContext,
94 render_context: &mut RenderContext<'w>,
95 world: &'w World,
96 ) -> Result<(), NodeRunError>;
97}
98
99impl_downcast!(Node);
100
101#[derive(Error, Display, Debug, Eq, PartialEq, From)]
102pub enum NodeRunError {
103 #[display("encountered an input slot error")]
104 InputSlotError(InputSlotError),
105 #[display("encountered an output slot error")]
106 OutputSlotError(OutputSlotError),
107 #[display("encountered an error when running a sub-graph")]
108 RunSubGraphError(RunSubGraphError),
109 #[display("encountered an error when executing draw command")]
110 DrawError(DrawError),
111}
112
113#[derive(Debug)]
115pub struct Edges {
116 label: InternedRenderLabel,
117 input_edges: Vec<Edge>,
118 output_edges: Vec<Edge>,
119}
120
121impl Edges {
122 #[inline]
124 pub fn input_edges(&self) -> &[Edge] {
125 &self.input_edges
126 }
127
128 #[inline]
130 pub fn output_edges(&self) -> &[Edge] {
131 &self.output_edges
132 }
133
134 #[inline]
136 pub fn label(&self) -> InternedRenderLabel {
137 self.label
138 }
139
140 pub(crate) fn add_input_edge(&mut self, edge: Edge) -> Result<(), RenderGraphError> {
142 if self.has_input_edge(&edge) {
143 return Err(RenderGraphError::EdgeAlreadyExists(edge));
144 }
145 self.input_edges.push(edge);
146 Ok(())
147 }
148
149 pub(crate) fn remove_input_edge(&mut self, edge: Edge) -> Result<(), RenderGraphError> {
151 if let Some(index) = self.input_edges.iter().position(|e| *e == edge) {
152 self.input_edges.swap_remove(index);
153 Ok(())
154 } else {
155 Err(RenderGraphError::EdgeDoesNotExist(edge))
156 }
157 }
158
159 pub(crate) fn add_output_edge(&mut self, edge: Edge) -> Result<(), RenderGraphError> {
161 if self.has_output_edge(&edge) {
162 return Err(RenderGraphError::EdgeAlreadyExists(edge));
163 }
164 self.output_edges.push(edge);
165 Ok(())
166 }
167
168 pub(crate) fn remove_output_edge(&mut self, edge: Edge) -> Result<(), RenderGraphError> {
170 if let Some(index) = self.output_edges.iter().position(|e| *e == edge) {
171 self.output_edges.swap_remove(index);
172 Ok(())
173 } else {
174 Err(RenderGraphError::EdgeDoesNotExist(edge))
175 }
176 }
177
178 pub fn has_input_edge(&self, edge: &Edge) -> bool {
180 self.input_edges.contains(edge)
181 }
182
183 pub fn has_output_edge(&self, edge: &Edge) -> bool {
185 self.output_edges.contains(edge)
186 }
187
188 pub fn get_input_slot_edge(&self, index: usize) -> Result<&Edge, RenderGraphError> {
191 self.input_edges
192 .iter()
193 .find(|e| {
194 if let Edge::SlotEdge { input_index, .. } = e {
195 *input_index == index
196 } else {
197 false
198 }
199 })
200 .ok_or(RenderGraphError::UnconnectedNodeInputSlot {
201 input_slot: index,
202 node: self.label,
203 })
204 }
205
206 pub fn get_output_slot_edge(&self, index: usize) -> Result<&Edge, RenderGraphError> {
209 self.output_edges
210 .iter()
211 .find(|e| {
212 if let Edge::SlotEdge { output_index, .. } = e {
213 *output_index == index
214 } else {
215 false
216 }
217 })
218 .ok_or(RenderGraphError::UnconnectedNodeOutputSlot {
219 output_slot: index,
220 node: self.label,
221 })
222 }
223}
224
225pub struct NodeState {
230 pub label: InternedRenderLabel,
231 pub type_name: &'static str,
233 pub node: Box<dyn Node>,
234 pub input_slots: SlotInfos,
235 pub output_slots: SlotInfos,
236 pub edges: Edges,
237}
238
239impl Debug for NodeState {
240 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
241 writeln!(f, "{:?} ({:?})", self.label, self.type_name)
242 }
243}
244
245impl NodeState {
246 pub fn new<T>(label: InternedRenderLabel, node: T) -> Self
249 where
250 T: Node,
251 {
252 NodeState {
253 label,
254 input_slots: node.input().into(),
255 output_slots: node.output().into(),
256 node: Box::new(node),
257 type_name: core::any::type_name::<T>(),
258 edges: Edges {
259 label,
260 input_edges: Vec::new(),
261 output_edges: Vec::new(),
262 },
263 }
264 }
265
266 pub fn node<T>(&self) -> Result<&T, RenderGraphError>
268 where
269 T: Node,
270 {
271 self.node
272 .downcast_ref::<T>()
273 .ok_or(RenderGraphError::WrongNodeType)
274 }
275
276 pub fn node_mut<T>(&mut self) -> Result<&mut T, RenderGraphError>
278 where
279 T: Node,
280 {
281 self.node
282 .downcast_mut::<T>()
283 .ok_or(RenderGraphError::WrongNodeType)
284 }
285
286 pub fn validate_input_slots(&self) -> Result<(), RenderGraphError> {
288 for i in 0..self.input_slots.len() {
289 self.edges.get_input_slot_edge(i)?;
290 }
291
292 Ok(())
293 }
294
295 pub fn validate_output_slots(&self) -> Result<(), RenderGraphError> {
297 for i in 0..self.output_slots.len() {
298 self.edges.get_output_slot_edge(i)?;
299 }
300
301 Ok(())
302 }
303}
304
305#[derive(Default)]
309pub struct EmptyNode;
310
311impl Node for EmptyNode {
312 fn run(
313 &self,
314 _graph: &mut RenderGraphContext,
315 _render_context: &mut RenderContext,
316 _world: &World,
317 ) -> Result<(), NodeRunError> {
318 Ok(())
319 }
320}
321
322pub struct RunGraphOnViewNode {
325 sub_graph: InternedRenderSubGraph,
326}
327
328impl RunGraphOnViewNode {
329 pub fn new<T: RenderSubGraph>(sub_graph: T) -> Self {
330 Self {
331 sub_graph: sub_graph.intern(),
332 }
333 }
334}
335
336impl Node for RunGraphOnViewNode {
337 fn run(
338 &self,
339 graph: &mut RenderGraphContext,
340 _render_context: &mut RenderContext,
341 _world: &World,
342 ) -> Result<(), NodeRunError> {
343 graph.run_sub_graph(self.sub_graph, vec![], Some(graph.view_entity()))?;
344 Ok(())
345 }
346}
347
348pub trait ViewNode {
352 type ViewQuery: ReadOnlyQueryData;
355
356 fn update(&mut self, _world: &mut World) {}
358
359 fn run<'w>(
363 &self,
364 graph: &mut RenderGraphContext,
365 render_context: &mut RenderContext<'w>,
366 view_query: QueryItem<'w, Self::ViewQuery>,
367 world: &'w World,
368 ) -> Result<(), NodeRunError>;
369}
370
371pub struct ViewNodeRunner<N: ViewNode> {
376 view_query: QueryState<N::ViewQuery>,
377 node: N,
378}
379
380impl<N: ViewNode> ViewNodeRunner<N> {
381 pub fn new(node: N, world: &mut World) -> Self {
382 Self {
383 view_query: world.query_filtered(),
384 node,
385 }
386 }
387}
388
389impl<N: ViewNode + FromWorld> FromWorld for ViewNodeRunner<N> {
390 fn from_world(world: &mut World) -> Self {
391 Self::new(N::from_world(world), world)
392 }
393}
394
395impl<T> Node for ViewNodeRunner<T>
396where
397 T: ViewNode + Send + Sync + 'static,
398{
399 fn update(&mut self, world: &mut World) {
400 self.view_query.update_archetypes(world);
401 self.node.update(world);
402 }
403
404 fn run<'w>(
405 &self,
406 graph: &mut RenderGraphContext,
407 render_context: &mut RenderContext<'w>,
408 world: &'w World,
409 ) -> Result<(), NodeRunError> {
410 let Ok(view) = self.view_query.get_manual(world, graph.view_entity()) else {
411 return Ok(());
412 };
413
414 ViewNode::run(&self.node, graph, render_context, view, world)?;
415 Ok(())
416 }
417}