bevy_render/render_graph/
node_slot.rs

1use alloc::borrow::Cow;
2use bevy_ecs::entity::Entity;
3use core::fmt;
4use derive_more::derive::From;
5
6use crate::render_resource::{Buffer, Sampler, TextureView};
7
8/// A value passed between render [`Nodes`](super::Node).
9/// Corresponds to the [`SlotType`] specified in the [`RenderGraph`](super::RenderGraph).
10///
11/// Slots can have four different types of values:
12/// [`Buffer`], [`TextureView`], [`Sampler`] and [`Entity`].
13///
14/// These values do not contain the actual render data, but only the ids to retrieve them.
15#[derive(Debug, Clone, From)]
16pub enum SlotValue {
17    /// A GPU-accessible [`Buffer`].
18    Buffer(Buffer),
19    /// A [`TextureView`] describes a texture used in a pipeline.
20    TextureView(TextureView),
21    /// A texture [`Sampler`] defines how a pipeline will sample from a [`TextureView`].
22    Sampler(Sampler),
23    /// An entity from the ECS.
24    Entity(Entity),
25}
26
27impl SlotValue {
28    /// Returns the [`SlotType`] of this value.
29    pub fn slot_type(&self) -> SlotType {
30        match self {
31            SlotValue::Buffer(_) => SlotType::Buffer,
32            SlotValue::TextureView(_) => SlotType::TextureView,
33            SlotValue::Sampler(_) => SlotType::Sampler,
34            SlotValue::Entity(_) => SlotType::Entity,
35        }
36    }
37}
38
39/// Describes the render resources created (output) or used (input) by
40/// the render [`Nodes`](super::Node).
41///
42/// This should not be confused with [`SlotValue`], which actually contains the passed data.
43#[derive(Debug, Copy, Clone, Eq, PartialEq)]
44pub enum SlotType {
45    /// A GPU-accessible [`Buffer`].
46    Buffer,
47    /// A [`TextureView`] describes a texture used in a pipeline.
48    TextureView,
49    /// A texture [`Sampler`] defines how a pipeline will sample from a [`TextureView`].
50    Sampler,
51    /// An entity from the ECS.
52    Entity,
53}
54
55impl fmt::Display for SlotType {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        let s = match self {
58            SlotType::Buffer => "Buffer",
59            SlotType::TextureView => "TextureView",
60            SlotType::Sampler => "Sampler",
61            SlotType::Entity => "Entity",
62        };
63
64        f.write_str(s)
65    }
66}
67
68/// A [`SlotLabel`] is used to reference a slot by either its name or index
69/// inside the [`RenderGraph`](super::RenderGraph).
70#[derive(Debug, Clone, Eq, PartialEq, From)]
71pub enum SlotLabel {
72    Index(usize),
73    Name(Cow<'static, str>),
74}
75
76impl From<&SlotLabel> for SlotLabel {
77    fn from(value: &SlotLabel) -> Self {
78        value.clone()
79    }
80}
81
82impl From<String> for SlotLabel {
83    fn from(value: String) -> Self {
84        SlotLabel::Name(value.into())
85    }
86}
87
88impl From<&'static str> for SlotLabel {
89    fn from(value: &'static str) -> Self {
90        SlotLabel::Name(value.into())
91    }
92}
93
94/// The internal representation of a slot, which specifies its [`SlotType`] and name.
95#[derive(Clone, Debug)]
96pub struct SlotInfo {
97    pub name: Cow<'static, str>,
98    pub slot_type: SlotType,
99}
100
101impl SlotInfo {
102    pub fn new(name: impl Into<Cow<'static, str>>, slot_type: SlotType) -> Self {
103        SlotInfo {
104            name: name.into(),
105            slot_type,
106        }
107    }
108}
109
110/// A collection of input or output [`SlotInfos`](SlotInfo) for
111/// a [`NodeState`](super::NodeState).
112#[derive(Default, Debug)]
113pub struct SlotInfos {
114    slots: Vec<SlotInfo>,
115}
116
117impl<T: IntoIterator<Item = SlotInfo>> From<T> for SlotInfos {
118    fn from(slots: T) -> Self {
119        SlotInfos {
120            slots: slots.into_iter().collect(),
121        }
122    }
123}
124
125impl SlotInfos {
126    /// Returns the count of slots.
127    #[inline]
128    pub fn len(&self) -> usize {
129        self.slots.len()
130    }
131
132    /// Returns true if there are no slots.
133    #[inline]
134    pub fn is_empty(&self) -> bool {
135        self.slots.is_empty()
136    }
137
138    /// Retrieves the [`SlotInfo`] for the provided label.
139    pub fn get_slot(&self, label: impl Into<SlotLabel>) -> Option<&SlotInfo> {
140        let label = label.into();
141        let index = self.get_slot_index(label)?;
142        self.slots.get(index)
143    }
144
145    /// Retrieves the [`SlotInfo`] for the provided label mutably.
146    pub fn get_slot_mut(&mut self, label: impl Into<SlotLabel>) -> Option<&mut SlotInfo> {
147        let label = label.into();
148        let index = self.get_slot_index(label)?;
149        self.slots.get_mut(index)
150    }
151
152    /// Retrieves the index (inside input or output slots) of the slot for the provided label.
153    pub fn get_slot_index(&self, label: impl Into<SlotLabel>) -> Option<usize> {
154        let label = label.into();
155        match label {
156            SlotLabel::Index(index) => Some(index),
157            SlotLabel::Name(ref name) => self.slots.iter().position(|s| s.name == *name),
158        }
159    }
160
161    /// Returns an iterator over the slot infos.
162    pub fn iter(&self) -> impl Iterator<Item = &SlotInfo> {
163        self.slots.iter()
164    }
165}