1use {
2 super::{
3 AccessType, Binding, Command, Graph, Node, Resource, Subresource, SubresourceRange,
4 ViewInfo,
5 },
6 crate::{
7 ExecutionPipeline,
8 driver::{
9 compute::ComputePipeline, graphics::GraphicsPipeline, ray_tracing::RayTracingPipeline,
10 },
11 },
12 std::marker::PhantomData,
13};
14
15pub trait Pipeline<'a> {
19 type Command;
21
22 fn bind_cmd(self, _: Command<'a>) -> Self::Command;
26}
27
28macro_rules! pipeline {
29 ($variant:ident, $pipeline:ident, $is_fn:ident, $unwrap_fn:ident) => {
30 paste::paste! {
31 impl<'a> Pipeline<'a> for $pipeline {
32 type Command = PipelineCommand<'a, $pipeline>;
33
34 fn bind_cmd(self, mut cmd: Command<'a>) -> Self::Command {
35 {
36 let cmd = cmd.cmd_mut();
37 if cmd.expect_last_exec().pipeline.is_some() {
38 cmd.execs.push(Default::default());
39 }
40
41 cmd.expect_last_exec_mut().pipeline = Some(ExecutionPipeline::$variant(self));
42 }
43
44 Self::Command {
45 __: PhantomData,
46 cmd,
47 }
48 }
49 }
50
51 impl<'a> Pipeline<'a> for &'a $pipeline {
52 type Command = PipelineCommand<'a, $pipeline>;
53
54 fn bind_cmd(self, mut cmd: Command<'a>) -> Self::Command {
55 {
56 let cmd = cmd.cmd_mut();
57 if cmd.expect_last_exec().pipeline.is_some() {
58 cmd.execs.push(Default::default());
59 }
60
61 cmd.expect_last_exec_mut().pipeline
62 = Some(ExecutionPipeline::$variant(self.clone()));
63 }
64
65 Self::Command {
66 __: PhantomData,
67 cmd,
68 }
69 }
70
71 }
72
73 impl ExecutionPipeline {
74 #[allow(unused)]
75 pub(crate) fn $is_fn(&self) -> bool {
76 matches!(self, Self::$variant(_))
77 }
78
79 #[allow(unused)]
80 pub(crate) fn $unwrap_fn(&self) -> &$pipeline {
81 if let Self::$variant(binding) = self {
82 &binding
83 } else {
84 panic!();
85 }
86 }
87 }
88 }
89 };
90}
91
92pipeline!(Compute, ComputePipeline, is_compute, unwrap_compute);
94pipeline!(Graphics, GraphicsPipeline, is_graphics, unwrap_graphics);
95pipeline!(
96 RayTracing,
97 RayTracingPipeline,
98 is_ray_tracing,
99 unwrap_ray_tracing
100);
101
102pub struct PipelineCommand<'c, T> {
104 pub(super) __: PhantomData<T>,
105 pub(super) cmd: Command<'c>,
106}
107
108#[allow(private_bounds)]
110impl<'c, T> PipelineCommand<'c, T> {
111 pub fn bind_pipeline<P>(self, pipeline: P) -> P::Command
113 where
114 P: Pipeline<'c>,
115 {
116 pipeline.bind_cmd(self.cmd)
117 }
118
119 pub fn bind_resource<R>(&mut self, resource: R) -> R::Node
121 where
122 R: Resource,
123 {
124 self.cmd.bind_resource(resource)
125 }
126
127 pub fn end_cmd(self) -> &'c mut Graph {
129 self.cmd.end_cmd()
130 }
131
132 pub fn resource<N>(&self, resource_node: N) -> &N::Resource
134 where
135 N: Node,
136 {
137 self.cmd.resource(resource_node)
138 }
139
140 pub fn resource_access<N>(mut self, resource_node: N, access: AccessType) -> Self
145 where
146 N: Node + Subresource,
147 SubresourceRange: From<N::Range>,
148 {
149 self.cmd.set_resource_access(resource_node, access);
150 self
151 }
152
153 pub fn set_resource_access<N>(&mut self, resource_node: N, access: AccessType) -> &mut Self
155 where
156 N: Node + Subresource,
157 SubresourceRange: From<N::Range>,
158 {
159 self.cmd.set_resource_access(resource_node, access);
160 self
161 }
162
163 pub fn set_shader_resource_access<N>(
165 &mut self,
166 binding: impl Into<Binding>,
167 resource_node: N,
168 access: AccessType,
169 ) -> &mut Self
170 where
171 N: Node + Subresource,
172 N::Info: Copy,
173 SubresourceRange: From<N::Info>,
174 ViewInfo: From<N::Info>,
175 {
176 let subresource = resource_node.info(&self.cmd.graph.resources);
177
178 self.set_shader_subresource_access(binding, resource_node, subresource, access)
179 }
180
181 pub fn set_shader_subresource_access<N>(
183 &mut self,
184 binding: impl Into<Binding>,
185 resource_node: N,
186 subresource: impl Into<N::Info>,
187 access: AccessType,
188 ) -> &mut Self
189 where
190 N: Node + Subresource,
191 N::Info: Copy,
192 SubresourceRange: From<N::Info>,
193 ViewInfo: From<N::Info>,
194 {
195 let binding = binding.into();
196 let subresource = subresource.into();
197 let node_idx = resource_node.index();
198 let view_info = subresource.into();
199
200 self.cmd.push_subresource_access(
201 resource_node,
202 SubresourceRange::from(subresource),
203 access,
204 );
205
206 #[cfg(feature = "checked")]
207 {
208 if let Some(prev) = self.cmd.cmd().expect_last_exec().bindings.get(&binding) {
209 assert!(
210 *prev == (node_idx, view_info),
211 "shader binding {binding:?} already bound to a different resource or view"
212 );
213 }
214 }
215
216 self.cmd
217 .cmd_mut()
218 .expect_last_exec_mut()
219 .bindings
220 .insert(binding, (node_idx, view_info));
221
222 self
223 }
224
225 pub fn set_subresource_access<N>(
227 &mut self,
228 resource_node: N,
229 subresource: impl Into<N::Range>,
230 access: AccessType,
231 ) -> &mut Self
232 where
233 N: Node + Subresource,
234 SubresourceRange: From<N::Range>,
235 {
236 self.cmd
237 .set_subresource_access(resource_node, subresource, access);
238 self
239 }
240
241 pub fn shader_resource_access<N>(
250 mut self,
251 binding: impl Into<Binding>,
252 resource_node: N,
253 access: AccessType,
254 ) -> Self
255 where
256 N: Node + Subresource,
257 N::Info: Copy,
258 SubresourceRange: From<N::Info>,
259 ViewInfo: From<N::Info>,
260 {
261 self.set_shader_resource_access(binding, resource_node, access);
262 self
263 }
264
265 pub fn shader_subresource_access<N>(
275 mut self,
276 binding: impl Into<Binding>,
277 resource_node: N,
278 subresource: impl Into<N::Info>,
279 access: AccessType,
280 ) -> Self
281 where
282 N: Node + Subresource,
283 N::Info: Copy,
284 SubresourceRange: From<N::Info>,
285 ViewInfo: From<N::Info>,
286 {
287 self.set_shader_subresource_access(binding, resource_node, subresource, access);
288 self
289 }
290
291 pub fn subresource_access<N>(
297 mut self,
298 resource_node: N,
299 subresource: impl Into<N::Range>,
300 access: AccessType,
301 ) -> Self
302 where
303 N: Node + Subresource,
304 SubresourceRange: From<N::Range>,
305 {
306 self.cmd
307 .set_subresource_access(resource_node, subresource, access);
308 self
309 }
310}