maplibre/render/graph/
node_slot.rs

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