screen_13/graph/
binding.rs

1use {
2    super::{
3        AccelerationStructureLeaseNode, AccelerationStructureNode, BufferLeaseNode, BufferNode,
4        ImageLeaseNode, ImageNode, RenderGraph,
5    },
6    crate::{
7        driver::{
8            accel_struct::AccelerationStructure, buffer::Buffer, image::Image,
9            swapchain::SwapchainImage,
10        },
11        pool::Lease,
12    },
13    std::{fmt::Debug, sync::Arc},
14};
15
16// #[derive(Debug)]
17// pub enum AnyBufferBinding<'a> {
18//     Buffer(&'a Arc<Buffer>),
19//     BufferLease(&'a Lease<Buffer>),
20// }
21
22// impl<'a> From<&'a Arc<Buffer>> for AnyBufferBinding<'a> {
23//     fn from(buffer: &'a Arc<Buffer>) -> Self {
24//         Self::Buffer(buffer)
25//     }
26// }
27
28// impl<'a> From<&'a Lease<Buffer>> for AnyBufferBinding<'a> {
29//     fn from(buffer: &'a Lease<Buffer>) -> Self {
30//         Self::BufferLease(buffer)
31//     }
32// }
33
34// #[derive(Debug)]
35// pub enum AnyImageBinding<'a> {
36//     Image(&'a Arc<Image>),
37//     ImageLease(&'a Lease<Image>),
38//     SwapchainImage(&'a SwapchainImage),
39// }
40
41// impl<'a> From<&'a Arc<Image>> for AnyImageBinding<'a> {
42//     fn from(image: &'a Arc<Image>) -> Self {
43//         Self::Image(image)
44//     }
45// }
46
47// impl<'a> From<&'a Lease<Image>> for AnyImageBinding<'a> {
48//     fn from(image: &'a Lease<Image>) -> Self {
49//         Self::ImageLease(image)
50//     }
51// }
52
53// impl<'a> From<&'a SwapchainImage> for AnyImageBinding<'a> {
54//     fn from(image: &'a SwapchainImage) -> Self {
55//         Self::SwapchainImage(image)
56//     }
57// }
58
59/// A trait for resources which may be bound to a `RenderGraph`.
60///
61/// See [`RenderGraph::bind_node`] and
62/// [`PassRef::bind_pipeline`](super::pass_ref::PassRef::bind_pipeline) for details.
63pub trait Bind<Graph, Node> {
64    /// Binds the resource to a graph-like object.
65    ///
66    /// Returns a reference Node object.
67    fn bind(self, graph: Graph) -> Node;
68}
69
70#[derive(Debug)]
71pub enum Binding {
72    AccelerationStructure(Arc<AccelerationStructure>, bool),
73    AccelerationStructureLease(Arc<Lease<AccelerationStructure>>, bool),
74    Buffer(Arc<Buffer>, bool),
75    BufferLease(Arc<Lease<Buffer>>, bool),
76    Image(Arc<Image>, bool),
77    ImageLease(Arc<Lease<Image>>, bool),
78    SwapchainImage(Box<SwapchainImage>, bool),
79}
80
81impl Binding {
82    pub(super) fn as_driver_acceleration_structure(&self) -> Option<&AccelerationStructure> {
83        Some(match self {
84            Self::AccelerationStructure(binding, _) => binding,
85            Self::AccelerationStructureLease(binding, _) => binding,
86            _ => return None,
87        })
88    }
89
90    pub(super) fn as_driver_buffer(&self) -> Option<&Buffer> {
91        Some(match self {
92            Self::Buffer(binding, _) => binding,
93            Self::BufferLease(binding, _) => binding,
94            _ => return None,
95        })
96    }
97
98    pub(super) fn as_driver_image(&self) -> Option<&Image> {
99        Some(match self {
100            Self::Image(binding, _) => binding,
101            Self::ImageLease(binding, _) => binding,
102            Self::SwapchainImage(binding, _) => binding,
103            _ => return None,
104        })
105    }
106
107    pub(super) fn is_bound(&self) -> bool {
108        match self {
109            Self::AccelerationStructure(_, is_bound) => *is_bound,
110            Self::AccelerationStructureLease(_, is_bound) => *is_bound,
111            Self::Buffer(_, is_bound) => *is_bound,
112            Self::BufferLease(_, is_bound) => *is_bound,
113            Self::Image(_, is_bound) => *is_bound,
114            Self::ImageLease(_, is_bound) => *is_bound,
115            Self::SwapchainImage(_, is_bound) => *is_bound,
116        }
117    }
118
119    pub(super) fn unbind(&mut self) {
120        *match self {
121            Self::AccelerationStructure(_, is_bound) => is_bound,
122            Self::AccelerationStructureLease(_, is_bound) => is_bound,
123            Self::Buffer(_, is_bound) => is_bound,
124            Self::BufferLease(_, is_bound) => is_bound,
125            Self::Image(_, is_bound) => is_bound,
126            Self::ImageLease(_, is_bound) => is_bound,
127            Self::SwapchainImage(_, is_bound) => is_bound,
128        } = false;
129    }
130}
131
132macro_rules! bind {
133    ($name:ident) => {
134        paste::paste! {
135            impl Bind<&mut RenderGraph, [<$name Node>]> for $name {
136                #[profiling::function]
137                fn bind(self, graph: &mut RenderGraph) -> [<$name Node>] {
138                    // In this function we are binding a new item (Image or Buffer or etc)
139
140                    // We will return a new node
141                    let res = [<$name Node>]::new(graph.bindings.len());
142                    let binding = Binding::$name(Arc::new(self), true);
143                    graph.bindings.push(binding);
144
145                    res
146                }
147            }
148
149            impl<'a> Bind<&mut RenderGraph, [<$name Node>]> for &'a Arc<$name> {
150                fn bind(self, graph: &mut RenderGraph) -> [<$name Node>] {
151                    // In this function we are binding a borrowed binding (&Arc<Image> or
152                    // &Arc<Buffer> or etc)
153
154                    Arc::clone(self).bind(graph)
155                }
156            }
157
158            impl Bind<&mut RenderGraph, [<$name Node>]> for Arc<$name> {
159                #[profiling::function]
160                fn bind(self, graph: &mut RenderGraph) -> [<$name Node>] {
161                    // In this function we are binding an existing binding (Arc<Image> or
162                    // Arc<Buffer> or etc)
163
164                    // We will return an existing node, if possible
165                    // TODO: Could store a sorted list of these shared pointers to avoid the O(N)
166                    for (idx, existing_binding) in graph.bindings.iter_mut().enumerate() {
167                        if let Some((existing_binding, is_bound)) = existing_binding.[<as_ $name:snake _mut>]() {
168                            if Arc::ptr_eq(existing_binding, &self) {
169                                *is_bound = true;
170
171                                return [<$name Node>]::new(idx);
172                            }
173                        }
174                    }
175
176                    // Return a new node
177                    let res = [<$name Node>]::new(graph.bindings.len());
178                    let binding = Binding::$name(self, true);
179                    graph.bindings.push(binding);
180
181                    res
182                }
183            }
184
185            impl Binding {
186                pub(super) fn [<as_ $name:snake>](&self) -> Option<&Arc<$name>> {
187                    if let Self::$name(binding, _) = self {
188                        Some(&binding)
189                    } else {
190                        None
191                    }
192                }
193
194                pub(super) fn [<as_ $name:snake _mut>](&mut self) -> Option<(&mut Arc<$name>, &mut bool)> {
195                    if let Self::$name(binding, is_bound) = self {
196                        Some((binding, is_bound))
197                    } else {
198                        None
199                    }
200                }
201            }
202        }
203    };
204}
205
206bind!(AccelerationStructure);
207bind!(Image);
208bind!(Buffer);
209
210macro_rules! bind_lease {
211    ($name:ident) => {
212        paste::paste! {
213            impl Bind<&mut RenderGraph, [<$name LeaseNode>]> for Lease<$name> {
214                #[profiling::function]
215                fn bind(self, graph: &mut RenderGraph) -> [<$name LeaseNode>] {
216                    // In this function we are binding a new lease (Lease<Image> or Lease<Buffer> or
217                    // etc)
218
219                    // We will return a new node
220                    let res = [<$name LeaseNode>]::new(graph.bindings.len());
221                    let binding = Binding::[<$name Lease>](Arc::new(self), true);
222                    graph.bindings.push(binding);
223
224                    res
225                }
226            }
227
228            impl<'a> Bind<&mut RenderGraph, [<$name LeaseNode>]> for &'a Arc<Lease<$name>> {
229                fn bind(self, graph: &mut RenderGraph) -> [<$name LeaseNode>] {
230                    // In this function we are binding a borrowed binding (&Arc<Lease<Image>> or
231                    // &Arc<Lease<Buffer>> or etc)
232
233                    Arc::clone(self).bind(graph)
234                }
235            }
236
237            impl Bind<&mut RenderGraph, [<$name LeaseNode>]> for Arc<Lease<$name>> {
238                #[profiling::function]
239                fn bind(self, graph: &mut RenderGraph) -> [<$name LeaseNode>] {
240                    // In this function we are binding an existing lease binding
241                    // (Arc<Lease<Image>> or Arc<Lease<Buffer>> or etc)
242
243                    // We will return an existing node, if possible
244                    // TODO: Could store a sorted list of these shared pointers to avoid the O(N)
245                    for (idx, existing_binding) in graph.bindings.iter_mut().enumerate() {
246                        if let Some((existing_binding, is_bound)) = existing_binding.[<as_ $name:snake _lease_mut>]() {
247                            if Arc::ptr_eq(existing_binding, &self) {
248                                *is_bound = true;
249
250                                return [<$name LeaseNode>]::new(idx);
251                            }
252                        }
253                    }
254
255                    // We will return a new node
256                    let res = [<$name LeaseNode>]::new(graph.bindings.len());
257                    let binding = Binding::[<$name Lease>](self, true);
258                    graph.bindings.push(binding);
259
260                    res
261                }
262            }
263
264            impl Binding {
265                pub(super) fn [<as_ $name:snake _lease>](&self) -> Option<&Arc<Lease<$name>>> {
266                    if let Self::[<$name Lease>](binding, _) = self {
267                        Some(binding)
268                    } else {
269                        None
270                    }
271                }
272
273                pub(super) fn [<as_ $name:snake _lease_mut>](&mut self) -> Option<(&Arc<Lease<$name>>, &mut bool)> {
274                    if let Self::[<$name Lease>](binding, is_bound) = self {
275                        Some((binding, is_bound))
276                    } else {
277                        None
278                    }
279                }
280            }
281        }
282    }
283}
284
285bind_lease!(AccelerationStructure);
286bind_lease!(Image);
287bind_lease!(Buffer);
288
289/// A trait for resources which may be unbound from a `RenderGraph`.
290///
291/// See [`RenderGraph::unbind_node`] for details.
292pub trait Unbind<Graph, Binding> {
293    /// Unbinds the resource from a graph-like object.
294    ///
295    /// Returns the original Binding object.
296    fn unbind(self, graph: &mut Graph) -> Binding;
297}