1mod cmd_ref;
21mod compute;
22mod graphics;
23mod pipeline;
24mod ray_tracing;
25
26pub use {
27 self::{
28 cmd_ref::{
29 BuildAccelerationStructureIndirectInfo, BuildAccelerationStructureInfo, CommandRef,
30 UpdateAccelerationStructureIndirectInfo, UpdateAccelerationStructureInfo,
31 },
32 compute::ComputeCommandRef,
33 graphics::{ClearColorValue, GraphicsCommandRef},
34 pipeline::{Pipeline, PipelineCommand},
35 ray_tracing::RayTracingCommandRef,
36 },
37 super::{LoadOp, StoreOp},
38};
39
40use {
41 super::{
42 AccelerationStructureLeaseNode, AccelerationStructureNode, AnyAccelerationStructureNode,
43 AnyBufferNode, AnyImageNode, AnyResource, BufferLeaseNode, BufferNode, CommandData,
44 CommandFunction, Execution, Graph, ImageLeaseNode, ImageNode, Node, Resource,
45 SwapchainImageNode,
46 },
47 crate::{
48 NodeIndex,
49 driver::{buffer::BufferSubresourceRange, image::ImageViewInfo},
50 stream::{AccelerationStructureArg, BufferArg, ImageArg},
51 },
52 ash::vk,
53 std::{ops::Range, sync::Arc},
54 vk_sync::AccessType,
55};
56
57pub(crate) type AttachmentIndex = u32;
59
60pub(crate) type BindingIndex = u32;
62
63pub(crate) type BindingOffset = u32;
65
66pub(crate) type DescriptorSetIndex = u32;
68
69pub struct Command<'a> {
83 pub(super) cmd_idx: usize,
84 pub(super) exec_idx: usize,
85 pub(super) graph: &'a mut Graph,
86}
87
88#[allow(private_bounds)]
89impl<'a> Command<'a> {
90 pub(super) fn new(graph: &'a mut Graph) -> Self {
91 let cmd_idx = graph.cmds.len();
92 graph.cmds.push(CommandData {
93 execs: vec![Default::default()], #[cfg(debug_assertions)]
95 name: None,
96 stream_scope_id: None,
97 });
98
99 Self {
100 cmd_idx,
101 exec_idx: 0,
102 graph,
103 }
104 }
105
106 fn cmd(&self) -> &CommandData {
107 &self.graph.cmds[self.cmd_idx]
108 }
109
110 fn cmd_mut(&mut self) -> &mut CommandData {
111 &mut self.graph.cmds[self.cmd_idx]
112 }
113
114 pub fn bind_resource<R>(&mut self, resource: R) -> R::Node
119 where
120 R: Resource,
121 {
122 self.graph.bind_resource(resource)
123 }
124
125 pub fn bind_pipeline<P>(self, pipeline: P) -> P::Command
134 where
135 P: Pipeline<'a>,
136 {
137 pipeline.bind_cmd(self)
138 }
139
140 pub fn debug_name(mut self, name: impl Into<String>) -> Self {
142 self.set_debug_name(name);
143 self
144 }
145
146 pub fn end_cmd(self) -> &'a mut Graph {
149 if self.exec_idx == 0 {
151 self.graph.cmds.pop();
152 }
153
154 self.graph
155 }
156
157 fn push_exec(&mut self, func: impl FnOnce(CommandRef) + Send + 'static) {
158 let cmd = self.cmd_mut();
159 let exec = {
160 let last_exec = cmd.expect_last_exec_mut();
161 last_exec.func = Some(CommandFunction::Once(Box::new(func)));
162
163 Execution {
164 pipeline: last_exec.pipeline.clone(),
165 ..Default::default()
166 }
167 };
168
169 cmd.execs.push(exec);
170 self.exec_idx += 1;
171 }
172
173 pub(crate) fn push_reusable_exec(
174 &mut self,
175 func: impl for<'r> Fn(CommandRef<'r>) + Send + Sync + 'static,
176 ) {
177 let cmd = self.cmd_mut();
178 let exec = {
179 let last_exec = cmd.expect_last_exec_mut();
180 last_exec.func = Some(CommandFunction::Reusable(Arc::new(func)));
181
182 Execution {
183 pipeline: last_exec.pipeline.clone(),
184 ..Default::default()
185 }
186 };
187
188 cmd.execs.push(exec);
189 self.exec_idx += 1;
190 }
191
192 fn push_subresource_access(
193 &mut self,
194 resource_node: impl Node,
195 subresource: SubresourceRange,
196 access: AccessType,
197 ) {
198 self.graph.assert_node_owner(&resource_node);
199
200 let node_idx = resource_node.index();
201
202 self.push_subresource_access_index(node_idx, subresource, access);
203 }
204
205 pub(crate) fn push_subresource_access_index(
206 &mut self,
207 node_idx: NodeIndex,
208 subresource: SubresourceRange,
209 access: AccessType,
210 ) {
211 debug_assert!(self.graph.resources.get(node_idx).is_some());
212
213 self.cmd_mut().expect_last_exec_mut().accesses.push(
214 node_idx,
215 SubresourceAccess {
216 access,
217 subresource,
218 },
219 );
220 }
221
222 pub fn record_cmd(mut self, func: impl FnOnce(CommandRef<'_>) + Send + 'static) -> Self {
230 self.record_cmd_mut(func);
231 self
232 }
233
234 pub fn record_cmd_mut(&mut self, func: impl FnOnce(CommandRef<'_>) + Send + 'static) {
236 self.push_exec(move |cmd| {
237 func(cmd);
238 });
239 }
240
241 pub(crate) fn record_stream(
242 mut self,
243 func: impl for<'r> Fn(CommandRef<'r>) + Send + Sync + 'static,
244 ) -> Self {
245 self.record_stream_mut(func);
246 self
247 }
248
249 pub(crate) fn record_stream_mut(
250 &mut self,
251 func: impl for<'r> Fn(CommandRef<'r>) + Send + Sync + 'static,
252 ) {
253 self.push_reusable_exec(func);
254 }
255
256 pub fn resource<N>(&self, resource_node: N) -> &N::Resource
259 where
260 N: Node,
261 {
262 self.graph.resource(resource_node)
263 }
264
265 pub fn resource_access<N>(mut self, resource_node: N, access: AccessType) -> Self
271 where
272 N: Node + Subresource,
273 SubresourceRange: From<N::Range>,
274 {
275 self.set_resource_access(resource_node, access);
276 self
277 }
278
279 pub fn set_debug_name(&mut self, name: impl Into<String>) -> &mut Self {
281 #[cfg(debug_assertions)]
282 {
283 self.cmd_mut().name = Some(name.into());
284 }
285
286 #[cfg(not(debug_assertions))]
287 {
288 let _ = name;
289 }
290
291 self
292 }
293
294 pub fn set_resource_access<N>(&mut self, resource_node: N, access: AccessType)
296 where
297 N: Node + Subresource,
298 SubresourceRange: From<N::Range>,
299 {
300 let whole_resource = resource_node.range(&self.graph.resources);
301 let subresource = SubresourceRange::from(whole_resource);
302
303 self.push_subresource_access(resource_node, subresource, access);
304 }
305
306 pub(crate) fn set_stream_scope_id(&mut self, stream_scope_id: u64) {
307 self.cmd_mut().stream_scope_id = Some(stream_scope_id);
308 }
309
310 pub fn set_subresource_access<N>(
312 &mut self,
313 resource_node: N,
314 subresource: impl Into<N::Range>,
315 access: AccessType,
316 ) where
317 N: Node + Subresource,
318 SubresourceRange: From<N::Range>,
319 {
320 let subresource = subresource.into();
321 let subresource = SubresourceRange::from(subresource);
322
323 self.push_subresource_access(resource_node, subresource, access);
324 }
325
326 pub fn subresource_access<N>(
332 mut self,
333 resource_node: N,
334 subresource: impl Into<N::Range>,
335 access: AccessType,
336 ) -> Self
337 where
338 N: Node + Subresource,
339 SubresourceRange: From<N::Range>,
340 {
341 self.set_subresource_access(resource_node, subresource, access);
342 self
343 }
344}
345
346#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
364pub struct Binding {
365 pub binding: u32,
367
368 pub offset: u32,
370
371 pub set: u32,
373}
374
375impl Binding {
376 pub(super) fn into_tuple(self) -> (DescriptorSetIndex, BindingIndex, BindingOffset) {
377 (self.set, self.binding, self.offset)
378 }
379
380 pub(super) fn set(self) -> DescriptorSetIndex {
381 let (res, _, _) = self.into_tuple();
382 res
383 }
384}
385
386impl From<BindingIndex> for Binding {
387 fn from(binding: BindingIndex) -> Self {
388 Self {
389 binding,
390 offset: 0,
391 set: 0,
392 }
393 }
394}
395
396impl From<(DescriptorSetIndex, BindingIndex)> for Binding {
397 fn from((set, binding): (DescriptorSetIndex, BindingIndex)) -> Self {
398 Self {
399 binding,
400 offset: 0,
401 set,
402 }
403 }
404}
405
406impl From<(BindingIndex, [BindingOffset; 1])> for Binding {
407 fn from((binding, [offset]): (BindingIndex, [BindingOffset; 1])) -> Self {
408 Self {
409 binding,
410 offset,
411 set: 0,
412 }
413 }
414}
415
416impl From<(DescriptorSetIndex, BindingIndex, [BindingOffset; 1])> for Binding {
417 fn from(
418 (set, binding, [offset]): (DescriptorSetIndex, BindingIndex, [BindingOffset; 1]),
419 ) -> Self {
420 Self {
421 binding,
422 offset,
423 set,
424 }
425 }
426}
427
428#[allow(private_bounds)]
430pub trait Subresource: private::SubresourceSealed {
431 type Info;
433
434 type Range;
436}
437
438macro_rules! view_accel_struct {
439 ($name:ty) => {
440 impl Subresource for $name {
441 type Info = Self::Range;
442 type Range = ();
443 }
444
445 impl private::SubresourceSealed for $name {
446 fn info(&self, _: &[AnyResource]) -> <Self as Subresource>::Info
447 where
448 Self: Node + Subresource,
449 {
450 }
451
452 fn range(&self, resources: &[AnyResource]) -> <Self as Subresource>::Range
453 where
454 Self: Node + Subresource,
455 {
456 resources[self.index()].expect_accel_struct_info();
457 }
458 }
459 };
460}
461
462view_accel_struct!(AnyAccelerationStructureNode);
463view_accel_struct!(AccelerationStructureArg);
464view_accel_struct!(AccelerationStructureLeaseNode);
465view_accel_struct!(AccelerationStructureNode);
466
467macro_rules! view_buffer {
468 ($name:ty) => {
469 impl Subresource for $name {
470 type Info = Self::Range;
471 type Range = BufferSubresourceRange;
472 }
473
474 impl private::SubresourceSealed for $name {
475 fn info(&self, resources: &[AnyResource]) -> <Self as Subresource>::Info
476 where
477 Self: Node + Subresource,
478 {
479 self.range(resources)
480 }
481
482 fn range(&self, resources: &[AnyResource]) -> <Self as Subresource>::Range
483 where
484 Self: Node + Subresource,
485 {
486 let idx = self.index();
487
488 resources[idx].expect_buffer_info().into()
489 }
490 }
491 };
492}
493
494view_buffer!(AnyBufferNode);
495view_buffer!(BufferArg);
496view_buffer!(BufferLeaseNode);
497view_buffer!(BufferNode);
498
499macro_rules! view_image {
500 ($name:ty) => {
501 impl Subresource for $name {
502 type Info = ImageViewInfo;
503 type Range = vk::ImageSubresourceRange;
504 }
505
506 impl private::SubresourceSealed for $name {
507 fn info(&self, resources: &[AnyResource]) -> <Self as Subresource>::Info
508 where
509 Self: Node + Subresource,
510 {
511 let idx = self.index();
512
513 resources[idx].expect_image_info().into()
514 }
515
516 fn range(&self, resources: &[AnyResource]) -> <Self as Subresource>::Range
517 where
518 Self: Node + Subresource,
519 {
520 self.info(resources).into()
521 }
522 }
523 };
524}
525
526view_image!(AnyImageNode);
527view_image!(ImageArg);
528view_image!(ImageLeaseNode);
529view_image!(ImageNode);
530view_image!(SwapchainImageNode);
531
532#[derive(Clone, Copy, Debug)]
533pub(crate) enum SubresourceRange {
534 AccelerationStructure,
536
537 Image(vk::ImageSubresourceRange),
539
540 Buffer(BufferSubresourceRange),
542}
543
544impl SubresourceRange {
545 pub(super) fn as_image(&self) -> Option<&vk::ImageSubresourceRange> {
546 if let Self::Image(subresource) = self {
547 Some(subresource)
548 } else {
549 None
550 }
551 }
552
553 pub(super) fn expect_image(&self) -> &vk::ImageSubresourceRange {
554 self.as_image().expect("missing image subresource")
555 }
556}
557
558impl From<BufferSubresourceRange> for SubresourceRange {
559 fn from(subresource: BufferSubresourceRange) -> Self {
560 Self::Buffer(subresource)
561 }
562}
563
564impl From<()> for SubresourceRange {
565 fn from(_: ()) -> Self {
566 Self::AccelerationStructure
567 }
568}
569
570impl From<ImageViewInfo> for SubresourceRange {
571 fn from(subresource: ImageViewInfo) -> Self {
572 Self::Image(subresource.into())
573 }
574}
575
576impl From<vk::ImageSubresourceRange> for SubresourceRange {
577 fn from(subresource: vk::ImageSubresourceRange) -> Self {
578 Self::Image(subresource)
579 }
580}
581
582#[derive(Clone, Copy, Debug)]
583pub(super) struct SubresourceAccess {
584 pub access: AccessType,
585 pub subresource: SubresourceRange,
586}
587
588#[derive(Clone, Copy, Debug, Eq, PartialEq)]
590pub(crate) enum ViewInfo {
591 AccelerationStructure,
593
594 Image(ImageViewInfo),
596
597 Buffer(BufferSubresourceRange),
599}
600
601impl ViewInfo {
602 pub(crate) fn as_buffer(&self) -> Option<&BufferSubresourceRange> {
603 match self {
604 Self::Buffer(info) => Some(info),
605 _ => None,
606 }
607 }
608
609 pub(crate) fn as_image(&self) -> Option<&ImageViewInfo> {
610 match self {
611 Self::Image(info) => Some(info),
612 _ => None,
613 }
614 }
615
616 pub(crate) fn expect_buffer(&self) -> &BufferSubresourceRange {
617 self.as_buffer().expect("missing buffer view info")
618 }
619
620 pub(crate) fn expect_image(&self) -> &ImageViewInfo {
621 self.as_image().expect("missing image view info")
622 }
623}
624
625impl From<()> for ViewInfo {
626 fn from(_: ()) -> Self {
627 Self::AccelerationStructure
628 }
629}
630
631impl From<BufferSubresourceRange> for ViewInfo {
632 fn from(info: BufferSubresourceRange) -> Self {
633 Self::Buffer(info)
634 }
635}
636
637impl From<ImageViewInfo> for ViewInfo {
638 fn from(info: ImageViewInfo) -> Self {
639 Self::Image(info)
640 }
641}
642
643impl From<Range<vk::DeviceSize>> for ViewInfo {
644 fn from(range: Range<vk::DeviceSize>) -> Self {
645 Self::Buffer(BufferSubresourceRange {
646 start: range.start,
647 end: range.end,
648 })
649 }
650}
651
652mod private {
653 use crate::{AnyResource, Node};
654
655 pub(crate) trait SubresourceSealed: Sized {
656 fn info(&self, resources: &[AnyResource]) -> <Self as super::Subresource>::Info
657 where
658 Self: Node + super::Subresource;
659
660 fn range(&self, resources: &[AnyResource]) -> <Self as super::Subresource>::Range
661 where
662 Self: Node + super::Subresource;
663 }
664}