bevy_render/render_graph/
node_slot.rs

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