1use {
2 super::{
3 AccessType, Binding, Command, Graph, Node, Resource, Subresource, SubresourceRange,
4 ViewInfo,
5 },
6 crate::{
7 ExecutionPipeline, TimestampQuery,
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 write_timestamp(&mut self) -> TimestampQuery {
129 self.cmd.write_timestamp()
130 }
131
132 pub fn end_cmd(self) -> &'c mut Graph {
134 self.cmd.end_cmd()
135 }
136
137 pub fn resource<N>(&self, resource_node: N) -> &N::Resource
139 where
140 N: Node,
141 {
142 self.cmd.resource(resource_node)
143 }
144
145 pub fn resource_access<N>(mut self, resource_node: N, access: AccessType) -> Self
150 where
151 N: Node + Subresource,
152 SubresourceRange: From<N::Range>,
153 {
154 self.cmd.set_resource_access(resource_node, access);
155 self
156 }
157
158 pub fn set_resource_access<N>(&mut self, resource_node: N, access: AccessType) -> &mut Self
160 where
161 N: Node + Subresource,
162 SubresourceRange: From<N::Range>,
163 {
164 self.cmd.set_resource_access(resource_node, access);
165 self
166 }
167
168 pub fn set_shader_resource_access<N>(
170 &mut self,
171 binding: impl Into<Binding>,
172 resource_node: N,
173 access: AccessType,
174 ) -> &mut Self
175 where
176 N: Node + Subresource,
177 N::Info: Copy,
178 SubresourceRange: From<N::Info>,
179 ViewInfo: From<N::Info>,
180 {
181 let subresource = resource_node.info(&self.cmd.graph.resources);
182
183 self.set_shader_subresource_access(binding, resource_node, subresource, access)
184 }
185
186 pub fn set_shader_subresource_access<N>(
188 &mut self,
189 binding: impl Into<Binding>,
190 resource_node: N,
191 subresource: impl Into<N::Info>,
192 access: AccessType,
193 ) -> &mut Self
194 where
195 N: Node + Subresource,
196 N::Info: Copy,
197 SubresourceRange: From<N::Info>,
198 ViewInfo: From<N::Info>,
199 {
200 let binding = binding.into();
201 let subresource = subresource.into();
202 let node_idx = resource_node.index();
203 let view_info = subresource.into();
204
205 self.cmd.push_subresource_access(
206 resource_node,
207 SubresourceRange::from(subresource),
208 access,
209 );
210
211 #[cfg(feature = "checked")]
212 {
213 if let Some(prev) = self.cmd.cmd().expect_last_exec().bindings.get(&binding) {
214 assert!(
215 *prev == (node_idx, view_info),
216 "shader binding {binding:?} already bound to a different resource or view"
217 );
218 }
219 }
220
221 self.cmd
222 .cmd_mut()
223 .expect_last_exec_mut()
224 .bindings
225 .insert(binding, (node_idx, view_info));
226
227 self
228 }
229
230 pub fn set_subresource_access<N>(
232 &mut self,
233 resource_node: N,
234 subresource: impl Into<N::Range>,
235 access: AccessType,
236 ) -> &mut Self
237 where
238 N: Node + Subresource,
239 SubresourceRange: From<N::Range>,
240 {
241 self.cmd
242 .set_subresource_access(resource_node, subresource, access);
243 self
244 }
245
246 pub fn shader_resource_access<N>(
255 mut self,
256 binding: impl Into<Binding>,
257 resource_node: N,
258 access: AccessType,
259 ) -> Self
260 where
261 N: Node + Subresource,
262 N::Info: Copy,
263 SubresourceRange: From<N::Info>,
264 ViewInfo: From<N::Info>,
265 {
266 self.set_shader_resource_access(binding, resource_node, access);
267 self
268 }
269
270 pub fn shader_subresource_access<N>(
280 mut self,
281 binding: impl Into<Binding>,
282 resource_node: N,
283 subresource: impl Into<N::Info>,
284 access: AccessType,
285 ) -> Self
286 where
287 N: Node + Subresource,
288 N::Info: Copy,
289 SubresourceRange: From<N::Info>,
290 ViewInfo: From<N::Info>,
291 {
292 self.set_shader_subresource_access(binding, resource_node, subresource, access);
293 self
294 }
295
296 pub fn subresource_access<N>(
302 mut self,
303 resource_node: N,
304 subresource: impl Into<N::Range>,
305 access: AccessType,
306 ) -> Self
307 where
308 N: Node + Subresource,
309 SubresourceRange: From<N::Range>,
310 {
311 self.cmd
312 .set_subresource_access(resource_node, subresource, access);
313 self
314 }
315}