bevy_render/render_graph/
node.rs

1use 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    /// A strongly-typed class of labels used to identify a [`Node`] in a render graph.
27    RenderLabel,
28    RENDER_LABEL_INTERNER
29);
30
31/// A shorthand for `Interned<dyn RenderLabel>`.
32pub 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
60/// A render node that can be added to a [`RenderGraph`](super::RenderGraph).
61///
62/// Nodes are the fundamental part of the graph and used to extend its functionality, by
63/// generating draw calls and/or running subgraphs.
64/// They are added via the `render_graph::add_node(my_node)` method.
65///
66/// To determine their position in the graph and ensure that all required dependencies (inputs)
67/// are already executed, [`Edges`](Edge) are used.
68///
69/// A node can produce outputs used as dependencies by other nodes.
70/// Those inputs and outputs are called slots and are the default way of passing render data
71/// inside the graph. For more information see [`SlotType`](super::SlotType).
72pub trait Node: Downcast + Send + Sync + 'static {
73    /// Specifies the required input slots for this node.
74    /// They will then be available during the run method inside the [`RenderGraphContext`].
75    fn input(&self) -> Vec<SlotInfo> {
76        Vec::new()
77    }
78
79    /// Specifies the produced output slots for this node.
80    /// They can then be passed one inside [`RenderGraphContext`] during the run method.
81    fn output(&self) -> Vec<SlotInfo> {
82        Vec::new()
83    }
84
85    /// Updates internal node state using the current render [`World`] prior to the run method.
86    fn update(&mut self, _world: &mut World) {}
87
88    /// Runs the graph node logic, issues draw calls, updates the output slots and
89    /// optionally queues up subgraphs for execution. The graph data, input and output values are
90    /// passed via the [`RenderGraphContext`].
91    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/// A collection of input and output [`Edges`](Edge) for a [`Node`].
114#[derive(Debug)]
115pub struct Edges {
116    label: InternedRenderLabel,
117    input_edges: Vec<Edge>,
118    output_edges: Vec<Edge>,
119}
120
121impl Edges {
122    /// Returns all "input edges" (edges going "in") for this node .
123    #[inline]
124    pub fn input_edges(&self) -> &[Edge] {
125        &self.input_edges
126    }
127
128    /// Returns all "output edges" (edges going "out") for this node .
129    #[inline]
130    pub fn output_edges(&self) -> &[Edge] {
131        &self.output_edges
132    }
133
134    /// Returns this node's label.
135    #[inline]
136    pub fn label(&self) -> InternedRenderLabel {
137        self.label
138    }
139
140    /// Adds an edge to the `input_edges` if it does not already exist.
141    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    /// Removes an edge from the `input_edges` if it exists.
150    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    /// Adds an edge to the `output_edges` if it does not already exist.
160    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    /// Removes an edge from the `output_edges` if it exists.
169    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    /// Checks whether the input edge already exists.
179    pub fn has_input_edge(&self, edge: &Edge) -> bool {
180        self.input_edges.contains(edge)
181    }
182
183    /// Checks whether the output edge already exists.
184    pub fn has_output_edge(&self, edge: &Edge) -> bool {
185        self.output_edges.contains(edge)
186    }
187
188    /// Searches the `input_edges` for a [`Edge::SlotEdge`],
189    /// which `input_index` matches the `index`;
190    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    /// Searches the `output_edges` for a [`Edge::SlotEdge`],
207    /// which `output_index` matches the `index`;
208    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
225/// The internal representation of a [`Node`], with all data required
226/// by the [`RenderGraph`](super::RenderGraph).
227///
228/// The `input_slots` and `output_slots` are provided by the `node`.
229pub struct NodeState {
230    pub label: InternedRenderLabel,
231    /// The name of the type that implements [`Node`].
232    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    /// Creates an [`NodeState`] without edges, but the `input_slots` and `output_slots`
247    /// are provided by the `node`.
248    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    /// Retrieves the [`Node`].
267    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    /// Retrieves the [`Node`] mutably.
277    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    /// Validates that each input slot corresponds to an input edge.
287    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    /// Validates that each output slot corresponds to an output edge.
296    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/// A [`Node`] without any inputs, outputs and subgraphs, which does nothing when run.
306/// Used (as a label) to bundle multiple dependencies into one inside
307/// the [`RenderGraph`](super::RenderGraph).
308#[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
322/// A [`RenderGraph`](super::RenderGraph) [`Node`] that runs the configured subgraph once.
323/// This makes it easier to insert sub-graph runs into a graph.
324pub 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
348/// This trait should be used instead of the [`Node`] trait when making a render node that runs on a view.
349///
350/// It is intended to be used with [`ViewNodeRunner`]
351pub trait ViewNode {
352    /// The query that will be used on the view entity.
353    /// It is guaranteed to run on the view entity, so there's no need for a filter
354    type ViewQuery: ReadOnlyQueryData;
355
356    /// Updates internal node state using the current render [`World`] prior to the run method.
357    fn update(&mut self, _world: &mut World) {}
358
359    /// Runs the graph node logic, issues draw calls, updates the output slots and
360    /// optionally queues up subgraphs for execution. The graph data, input and output values are
361    /// passed via the [`RenderGraphContext`].
362    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
371/// This [`Node`] can be used to run any [`ViewNode`].
372/// It will take care of updating the view query in `update()` and running the query in `run()`.
373///
374/// This [`Node`] exists to help reduce boilerplate when making a render node that runs on a view.
375pub 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}