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 core::fmt::Debug;
17use downcast_rs::{impl_downcast, Downcast};
18use thiserror::Error;
19use variadics_please::all_tuples_with_size;
20
21pub use bevy_render_macros::RenderLabel;
22
23use super::{InternedRenderSubGraph, RenderSubGraph};
24
25define_label!(
26 #[diagnostic::on_unimplemented(
27 note = "consider annotating `{Self}` with `#[derive(RenderLabel)]`"
28 )]
29 RenderLabel,
31 RENDER_LABEL_INTERNER
32);
33
34pub type InternedRenderLabel = Interned<dyn RenderLabel>;
36
37pub trait IntoRenderNodeArray<const N: usize> {
38 fn into_array(self) -> [InternedRenderLabel; N];
39}
40
41impl<const N: usize> IntoRenderNodeArray<N> for Vec<InternedRenderLabel> {
42 fn into_array(self) -> [InternedRenderLabel; N] {
43 self.try_into().unwrap()
44 }
45}
46
47macro_rules! impl_render_label_tuples {
48 ($N: expr, $(#[$meta:meta])* $(($T: ident, $I: ident)),*) => {
49 $(#[$meta])*
50 impl<$($T: RenderLabel),*> IntoRenderNodeArray<$N> for ($($T,)*) {
51 #[inline]
52 fn into_array(self) -> [InternedRenderLabel; $N] {
53 let ($($I,)*) = self;
54 [$($I.intern(), )*]
55 }
56 }
57 }
58}
59
60all_tuples_with_size!(
61 #[doc(fake_variadic)]
62 impl_render_label_tuples,
63 1,
64 32,
65 T,
66 l
67);
68
69pub trait Node: Downcast + Send + Sync + 'static {
82 fn input(&self) -> Vec<SlotInfo> {
85 Vec::new()
86 }
87
88 fn output(&self) -> Vec<SlotInfo> {
91 Vec::new()
92 }
93
94 fn update(&mut self, _world: &mut World) {}
96
97 fn run<'w>(
101 &self,
102 graph: &mut RenderGraphContext,
103 render_context: &mut RenderContext<'w>,
104 world: &'w World,
105 ) -> Result<(), NodeRunError>;
106}
107
108impl_downcast!(Node);
109
110#[derive(Error, Debug, Eq, PartialEq)]
111pub enum NodeRunError {
112 #[error("encountered an input slot error")]
113 InputSlotError(#[from] InputSlotError),
114 #[error("encountered an output slot error")]
115 OutputSlotError(#[from] OutputSlotError),
116 #[error("encountered an error when running a sub-graph")]
117 RunSubGraphError(#[from] RunSubGraphError),
118 #[error("encountered an error when executing draw command")]
119 DrawError(#[from] DrawError),
120}
121
122#[derive(Debug)]
124pub struct Edges {
125 label: InternedRenderLabel,
126 input_edges: Vec<Edge>,
127 output_edges: Vec<Edge>,
128}
129
130impl Edges {
131 #[inline]
133 pub fn input_edges(&self) -> &[Edge] {
134 &self.input_edges
135 }
136
137 #[inline]
139 pub fn output_edges(&self) -> &[Edge] {
140 &self.output_edges
141 }
142
143 #[inline]
145 pub fn label(&self) -> InternedRenderLabel {
146 self.label
147 }
148
149 pub(crate) fn add_input_edge(&mut self, edge: Edge) -> Result<(), RenderGraphError> {
151 if self.has_input_edge(&edge) {
152 return Err(RenderGraphError::EdgeAlreadyExists(edge));
153 }
154 self.input_edges.push(edge);
155 Ok(())
156 }
157
158 pub(crate) fn remove_input_edge(&mut self, edge: Edge) -> Result<(), RenderGraphError> {
160 if let Some(index) = self.input_edges.iter().position(|e| *e == edge) {
161 self.input_edges.swap_remove(index);
162 Ok(())
163 } else {
164 Err(RenderGraphError::EdgeDoesNotExist(edge))
165 }
166 }
167
168 pub(crate) fn add_output_edge(&mut self, edge: Edge) -> Result<(), RenderGraphError> {
170 if self.has_output_edge(&edge) {
171 return Err(RenderGraphError::EdgeAlreadyExists(edge));
172 }
173 self.output_edges.push(edge);
174 Ok(())
175 }
176
177 pub(crate) fn remove_output_edge(&mut self, edge: Edge) -> Result<(), RenderGraphError> {
179 if let Some(index) = self.output_edges.iter().position(|e| *e == edge) {
180 self.output_edges.swap_remove(index);
181 Ok(())
182 } else {
183 Err(RenderGraphError::EdgeDoesNotExist(edge))
184 }
185 }
186
187 pub fn has_input_edge(&self, edge: &Edge) -> bool {
189 self.input_edges.contains(edge)
190 }
191
192 pub fn has_output_edge(&self, edge: &Edge) -> bool {
194 self.output_edges.contains(edge)
195 }
196
197 pub fn get_input_slot_edge(&self, index: usize) -> Result<&Edge, RenderGraphError> {
200 self.input_edges
201 .iter()
202 .find(|e| {
203 if let Edge::SlotEdge { input_index, .. } = e {
204 *input_index == index
205 } else {
206 false
207 }
208 })
209 .ok_or(RenderGraphError::UnconnectedNodeInputSlot {
210 input_slot: index,
211 node: self.label,
212 })
213 }
214
215 pub fn get_output_slot_edge(&self, index: usize) -> Result<&Edge, RenderGraphError> {
218 self.output_edges
219 .iter()
220 .find(|e| {
221 if let Edge::SlotEdge { output_index, .. } = e {
222 *output_index == index
223 } else {
224 false
225 }
226 })
227 .ok_or(RenderGraphError::UnconnectedNodeOutputSlot {
228 output_slot: index,
229 node: self.label,
230 })
231 }
232}
233
234pub struct NodeState {
239 pub label: InternedRenderLabel,
240 pub type_name: &'static str,
242 pub node: Box<dyn Node>,
243 pub input_slots: SlotInfos,
244 pub output_slots: SlotInfos,
245 pub edges: Edges,
246}
247
248impl Debug for NodeState {
249 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
250 writeln!(f, "{:?} ({})", self.label, self.type_name)
251 }
252}
253
254impl NodeState {
255 pub fn new<T>(label: InternedRenderLabel, node: T) -> Self
258 where
259 T: Node,
260 {
261 NodeState {
262 label,
263 input_slots: node.input().into(),
264 output_slots: node.output().into(),
265 node: Box::new(node),
266 type_name: core::any::type_name::<T>(),
267 edges: Edges {
268 label,
269 input_edges: Vec::new(),
270 output_edges: Vec::new(),
271 },
272 }
273 }
274
275 pub fn node<T>(&self) -> Result<&T, RenderGraphError>
277 where
278 T: Node,
279 {
280 self.node
281 .downcast_ref::<T>()
282 .ok_or(RenderGraphError::WrongNodeType)
283 }
284
285 pub fn node_mut<T>(&mut self) -> Result<&mut T, RenderGraphError>
287 where
288 T: Node,
289 {
290 self.node
291 .downcast_mut::<T>()
292 .ok_or(RenderGraphError::WrongNodeType)
293 }
294
295 pub fn validate_input_slots(&self) -> Result<(), RenderGraphError> {
297 for i in 0..self.input_slots.len() {
298 self.edges.get_input_slot_edge(i)?;
299 }
300
301 Ok(())
302 }
303
304 pub fn validate_output_slots(&self) -> Result<(), RenderGraphError> {
306 for i in 0..self.output_slots.len() {
307 self.edges.get_output_slot_edge(i)?;
308 }
309
310 Ok(())
311 }
312}
313
314#[derive(Default)]
318pub struct EmptyNode;
319
320impl Node for EmptyNode {
321 fn run(
322 &self,
323 _graph: &mut RenderGraphContext,
324 _render_context: &mut RenderContext,
325 _world: &World,
326 ) -> Result<(), NodeRunError> {
327 Ok(())
328 }
329}
330
331pub struct RunGraphOnViewNode {
334 sub_graph: InternedRenderSubGraph,
335}
336
337impl RunGraphOnViewNode {
338 pub fn new<T: RenderSubGraph>(sub_graph: T) -> Self {
339 Self {
340 sub_graph: sub_graph.intern(),
341 }
342 }
343}
344
345impl Node for RunGraphOnViewNode {
346 fn run(
347 &self,
348 graph: &mut RenderGraphContext,
349 _render_context: &mut RenderContext,
350 _world: &World,
351 ) -> Result<(), NodeRunError> {
352 graph.run_sub_graph(self.sub_graph, vec![], Some(graph.view_entity()), None)?;
353 Ok(())
354 }
355}
356
357pub trait ViewNode {
361 type ViewQuery: ReadOnlyQueryData;
364
365 fn update(&mut self, _world: &mut World) {}
367
368 fn run<'w>(
372 &self,
373 graph: &mut RenderGraphContext,
374 render_context: &mut RenderContext<'w>,
375 view_query: QueryItem<'w, '_, Self::ViewQuery>,
376 world: &'w World,
377 ) -> Result<(), NodeRunError>;
378}
379
380pub struct ViewNodeRunner<N: ViewNode> {
385 view_query: QueryState<N::ViewQuery>,
386 node: N,
387}
388
389impl<N: ViewNode> ViewNodeRunner<N> {
390 pub fn new(node: N, world: &mut World) -> Self {
391 Self {
392 view_query: world.query_filtered(),
393 node,
394 }
395 }
396}
397
398impl<N: ViewNode + FromWorld> FromWorld for ViewNodeRunner<N> {
399 fn from_world(world: &mut World) -> Self {
400 Self::new(N::from_world(world), world)
401 }
402}
403
404impl<T> Node for ViewNodeRunner<T>
405where
406 T: ViewNode + Send + Sync + 'static,
407{
408 fn update(&mut self, world: &mut World) {
409 self.view_query.update_archetypes(world);
410 self.node.update(world);
411 }
412
413 fn run<'w>(
414 &self,
415 graph: &mut RenderGraphContext,
416 render_context: &mut RenderContext<'w>,
417 world: &'w World,
418 ) -> Result<(), NodeRunError> {
419 let Ok(view) = self.view_query.get_manual(world, graph.view_entity()) else {
420 return Ok(());
421 };
422
423 ViewNode::run(&self.node, graph, render_context, view, world)?;
424 Ok(())
425 }
426}