1#![deny(missing_docs)]
15#![deny(rustdoc::broken_intra_doc_links)]
16
17pub mod cmd;
18pub mod driver;
19pub mod node;
20pub mod pool;
21
22mod submission;
23
24use std::sync::Arc;
25
26use crate::{
27 cmd::{ClearColorValue, CommandRef},
28 driver::{
29 accel_struct::AccelerationStructure, buffer::Buffer, image::Image,
30 swapchain::SwapchainImage,
31 },
32 pool::Lease,
33};
34
35pub use self::submission::Submission;
36
37#[allow(deprecated)]
38pub use self::deprecated::{Display, DisplayInfo, DisplayInfoBuilder};
39
40use {
41 self::{
42 cmd::{AttachmentIndex, Binding, Command, SubresourceAccess, ViewInfo},
43 node::{
44 AccelerationStructureLeaseNode, AccelerationStructureNode,
45 AnyAccelerationStructureNode, AnyBufferNode, AnyImageNode, BufferLeaseNode, BufferNode,
46 ImageLeaseNode, ImageNode, SwapchainImageNode,
47 },
48 },
49 crate::driver::{
50 DescriptorBindingMap,
51 compute::ComputePipeline,
52 format_aspect_mask, format_texel_block_extent, format_texel_block_size,
53 graphic::{DepthStencilInfo, GraphicPipeline},
54 image::{ImageInfo, ImageViewInfo, SampleCount},
55 image_subresource_range_from_layers,
56 ray_trace::RayTracePipeline,
57 render_pass::ResolveMode,
58 shader::PipelineDescriptorInfo,
59 },
60 ash::vk,
61 std::{
62 cmp::Ord,
63 collections::{BTreeMap, HashMap},
64 fmt::{Debug, Formatter},
65 ops::Range,
66 },
67 vk_sync::AccessType,
68};
69
70type ExecFn = Box<dyn FnOnce(CommandRef) + Send>;
71type NodeIndex = usize;
72
73#[derive(Debug)]
74#[doc(hidden)]
75pub enum AnyResource {
76 AccelerationStructure(Arc<AccelerationStructure>),
77 AccelerationStructureLease(Arc<Lease<AccelerationStructure>>),
78 Buffer(Arc<Buffer>),
79 BufferLease(Arc<Lease<Buffer>>),
80 Image(Arc<Image>),
81 ImageLease(Arc<Lease<Image>>),
82 SwapchainImage(Box<SwapchainImage>),
83}
84
85impl AnyResource {
86 fn as_accel_struct(&self) -> Option<&AccelerationStructure> {
87 Some(match self {
88 Self::AccelerationStructure(resource) => resource,
89 Self::AccelerationStructureLease(resource) => resource,
90 _ => return None,
91 })
92 }
93
94 fn as_buffer(&self) -> Option<&Buffer> {
95 Some(match self {
96 Self::Buffer(resource) => resource,
97 Self::BufferLease(resource) => resource,
98 _ => return None,
99 })
100 }
101
102 fn as_image(&self) -> Option<&Image> {
103 Some(match self {
104 Self::Image(resource) => resource,
105 Self::ImageLease(resource) => resource,
106 Self::SwapchainImage(resource) => resource,
107 _ => return None,
108 })
109 }
110
111 fn as_swapchain_image(&self) -> Option<&SwapchainImage> {
112 Some(match self {
113 Self::SwapchainImage(resource) => resource,
114 _ => return None,
115 })
116 }
117
118 fn expect_accel_struct(&self) -> &AccelerationStructure {
119 self.as_accel_struct()
120 .expect("missing acceleration structure resource")
121 }
122
123 fn expect_buffer(&self) -> &Buffer {
124 self.as_buffer().expect("missing buffer resource")
125 }
126
127 fn expect_image(&self) -> &Image {
128 self.as_image().expect("missing image resource")
129 }
130}
131
132#[derive(Clone, Copy, Debug)]
133struct Attachment {
134 array_layer_count: u32,
135 aspect_mask: vk::ImageAspectFlags,
136 base_array_layer: u32,
137 base_mip_level: u32,
138 format: vk::Format,
139 mip_level_count: u32,
140 sample_count: SampleCount,
141 target: NodeIndex,
142}
143
144impl Attachment {
145 fn new(image_view_info: ImageViewInfo, sample_count: SampleCount, target: NodeIndex) -> Self {
146 Self {
147 array_layer_count: image_view_info.array_layer_count,
148 aspect_mask: image_view_info.aspect_mask,
149 base_array_layer: image_view_info.base_array_layer,
150 base_mip_level: image_view_info.base_mip_level,
151 format: image_view_info.fmt,
152 mip_level_count: image_view_info.mip_level_count,
153 sample_count,
154 target,
155 }
156 }
157
158 fn are_compatible(lhs: Option<Self>, rhs: Option<Self>) -> bool {
159 let (Some(lhs), Some(rhs)) = (lhs, rhs) else {
163 return true;
164 };
165
166 Self::are_identical(lhs, rhs)
167 }
168
169 fn are_identical(lhs: Self, rhs: Self) -> bool {
170 lhs.array_layer_count == rhs.array_layer_count
171 && lhs.base_array_layer == rhs.base_array_layer
172 && lhs.base_mip_level == rhs.base_mip_level
173 && lhs.format == rhs.format
174 && lhs.mip_level_count == rhs.mip_level_count
175 && lhs.sample_count == rhs.sample_count
176 && lhs.target == rhs.target
177 }
178
179 fn image_view_info(self, image_info: ImageInfo) -> ImageViewInfo {
180 image_info
181 .into_builder()
182 .array_layer_count(self.array_layer_count)
183 .mip_level_count(self.mip_level_count)
184 .fmt(self.format)
185 .into_image_view()
186 .aspect_mask(self.aspect_mask)
187 .base_array_layer(self.base_array_layer)
188 .base_mip_level(self.base_mip_level)
189 .build()
190 }
191}
192
193#[derive(Default)]
194struct Execution {
195 accesses: HashMap<NodeIndex, Vec<SubresourceAccess>>,
196 bindings: BTreeMap<Binding, (NodeIndex, ViewInfo)>,
197
198 correlated_view_mask: u32,
199 depth_stencil: Option<DepthStencilInfo>,
200 render_area: Option<vk::Rect2D>,
201 view_mask: u32,
202
203 color_attachments: HashMap<AttachmentIndex, Attachment>,
204 color_clears: HashMap<AttachmentIndex, (Attachment, [f32; 4])>,
205 color_loads: HashMap<AttachmentIndex, Attachment>,
206 color_resolves: HashMap<AttachmentIndex, (Attachment, AttachmentIndex)>,
207 color_stores: HashMap<AttachmentIndex, Attachment>,
208 depth_stencil_attachment: Option<Attachment>,
209 depth_stencil_clear: Option<(Attachment, vk::ClearDepthStencilValue)>,
210 depth_stencil_load: Option<Attachment>,
211 depth_stencil_resolve: Option<(
212 Attachment,
213 AttachmentIndex,
214 Option<ResolveMode>,
215 Option<ResolveMode>,
216 )>,
217 depth_stencil_store: Option<Attachment>,
218
219 func: Option<ExecutionFunction>,
220 pipeline: Option<ExecutionPipeline>,
221}
222
223impl Debug for Execution {
224 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
225 f.debug_struct("Execution")
228 .field("accesses", &self.accesses)
229 .field("bindings", &self.bindings)
230 .field("depth_stencil", &self.depth_stencil)
231 .field("color_attachments", &self.color_attachments)
232 .field("color_clears", &self.color_clears)
233 .field("color_loads", &self.color_loads)
234 .field("color_resolves", &self.color_resolves)
235 .field("color_stores", &self.color_stores)
236 .field("depth_stencil_attachment", &self.depth_stencil_attachment)
237 .field("depth_stencil_clear", &self.depth_stencil_clear)
238 .field("depth_stencil_load", &self.depth_stencil_load)
239 .field("depth_stencil_resolve", &self.depth_stencil_resolve)
240 .field("depth_stencil_store", &self.depth_stencil_store)
241 .field("pipeline", &self.pipeline)
242 .finish()
243 }
244}
245
246struct ExecutionFunction(ExecFn);
247
248#[derive(Clone, Debug)]
249enum ExecutionPipeline {
250 Compute(ComputePipeline),
251 Graphic(GraphicPipeline),
252 RayTrace(RayTracePipeline),
253}
254
255impl ExecutionPipeline {
256 fn as_graphic(&self) -> Option<&GraphicPipeline> {
257 if let Self::Graphic(pipeline) = self {
258 Some(pipeline)
259 } else {
260 None
261 }
262 }
263
264 fn bind_point(&self) -> vk::PipelineBindPoint {
265 match self {
266 ExecutionPipeline::Compute(_) => vk::PipelineBindPoint::COMPUTE,
267 ExecutionPipeline::Graphic(_) => vk::PipelineBindPoint::GRAPHICS,
268 ExecutionPipeline::RayTrace(_) => vk::PipelineBindPoint::RAY_TRACING_KHR,
269 }
270 }
271
272 fn descriptor_bindings(&self) -> &DescriptorBindingMap {
273 match self {
274 ExecutionPipeline::Compute(pipeline) => &pipeline.inner.descriptor_bindings,
275 ExecutionPipeline::Graphic(pipeline) => &pipeline.inner.descriptor_bindings,
276 ExecutionPipeline::RayTrace(pipeline) => &pipeline.inner.descriptor_bindings,
277 }
278 }
279
280 fn descriptor_info(&self) -> &PipelineDescriptorInfo {
281 match self {
282 ExecutionPipeline::Compute(pipeline) => &pipeline.inner.descriptor_info,
283 ExecutionPipeline::Graphic(pipeline) => &pipeline.inner.descriptor_info,
284 ExecutionPipeline::RayTrace(pipeline) => &pipeline.inner.descriptor_info,
285 }
286 }
287
288 fn expect_compute(&self) -> &ComputePipeline {
289 if let Self::Compute(pipeline) = self {
290 pipeline
291 } else {
292 panic!("missing compute pipeline")
293 }
294 }
295
296 fn expect_graphic(&self) -> &GraphicPipeline {
297 self.as_graphic().expect("missing graphic pipeline")
298 }
299
300 fn expect_ray_trace(&self) -> &RayTracePipeline {
301 if let Self::RayTrace(pipeline) = self {
302 pipeline
303 } else {
304 panic!("missing ray trace pipeline")
305 }
306 }
307
308 fn layout(&self) -> vk::PipelineLayout {
309 match self {
310 ExecutionPipeline::Compute(pipeline) => pipeline.inner.layout,
311 ExecutionPipeline::Graphic(pipeline) => pipeline.inner.layout,
312 ExecutionPipeline::RayTrace(pipeline) => pipeline.inner.layout,
313 }
314 }
315
316 fn stage(&self) -> vk::PipelineStageFlags {
317 match self {
318 ExecutionPipeline::Compute(_) => vk::PipelineStageFlags::COMPUTE_SHADER,
319 ExecutionPipeline::Graphic(_) => vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
320 ExecutionPipeline::RayTrace(_) => vk::PipelineStageFlags::RAY_TRACING_SHADER_KHR,
321 }
322 }
323}
324
325#[derive(Debug)]
326struct CommandData {
327 execs: Vec<Execution>,
328 name: Option<String>,
329}
330
331impl CommandData {
332 fn descriptor_pools_sizes(
333 &self,
334 ) -> impl Iterator<Item = impl Iterator<Item = (&vk::DescriptorType, &u32)>> {
335 self.execs
336 .iter()
337 .flat_map(|exec| &exec.pipeline)
338 .map(|pipeline| {
339 pipeline
340 .descriptor_info()
341 .pool_sizes
342 .values()
343 .flat_map(HashMap::iter)
344 })
345 }
346
347 fn expect_first_exec(&self) -> &Execution {
348 self.execs.first().expect("missing command execution")
349 }
350
351 fn expect_last_exec(&self) -> &Execution {
355 self.execs.last().expect("missing command execution")
356 }
357
358 fn expect_last_exec_mut(&mut self) -> &mut Execution {
362 self.execs.last_mut().expect("missing command execution")
363 }
364
365 fn expect_last_pipeline(&self) -> &ExecutionPipeline {
366 self.expect_last_exec()
367 .pipeline
368 .as_ref()
369 .expect("missing command pipeline")
370 }
371
372 fn name(&self) -> &str {
373 self.name.as_deref().unwrap_or("command")
374 }
375}
376
377#[derive(Debug, Default)]
386pub struct Graph {
387 cmds: Vec<CommandData>,
388 resources: Vec<AnyResource>,
389}
390
391impl Graph {
392 pub fn new() -> Self {
394 Self::default()
395 }
396
397 pub fn begin_cmd(&mut self) -> Command<'_> {
399 Command::new(self)
400 }
401
402 pub fn bind_resource<R>(&mut self, resource: R) -> R::Node
407 where
408 R: Resource,
409 {
410 resource.bind_graph(self)
411 }
412
413 pub fn blit_image(
415 &mut self,
416 src: impl Into<AnyImageNode>,
417 dst: impl Into<AnyImageNode>,
418 filter: vk::Filter,
419 ) -> &mut Self {
420 let src = src.into();
421 let src_info = self.resource(src).info;
422
423 let dst = dst.into();
424 let dst_info = self.resource(dst).info;
425
426 self.blit_image_region(
427 src,
428 dst,
429 filter,
430 [vk::ImageBlit {
431 src_subresource: vk::ImageSubresourceLayers {
432 aspect_mask: format_aspect_mask(src_info.fmt),
433 mip_level: 0,
434 base_array_layer: 0,
435 layer_count: 1,
436 },
437 src_offsets: [
438 vk::Offset3D { x: 0, y: 0, z: 0 },
439 vk::Offset3D {
440 x: src_info.width as _,
441 y: src_info.height as _,
442 z: src_info.depth as _,
443 },
444 ],
445 dst_subresource: vk::ImageSubresourceLayers {
446 aspect_mask: format_aspect_mask(dst_info.fmt),
447 mip_level: 0,
448 base_array_layer: 0,
449 layer_count: 1,
450 },
451 dst_offsets: [
452 vk::Offset3D { x: 0, y: 0, z: 0 },
453 vk::Offset3D {
454 x: dst_info.width as _,
455 y: dst_info.height as _,
456 z: dst_info.depth as _,
457 },
458 ],
459 }],
460 )
461 }
462
463 #[profiling::function]
465 pub fn blit_image_region(
466 &mut self,
467 src: impl Into<AnyImageNode>,
468 dst: impl Into<AnyImageNode>,
469 filter: vk::Filter,
470 regions: impl AsRef<[vk::ImageBlit]> + 'static + Send,
471 ) -> &mut Self {
472 let src = src.into();
473 let dst = dst.into();
474
475 let mut cmd = self.begin_cmd().debug_name("blit image");
476
477 for region in regions.as_ref() {
478 let src_region = image_subresource_range_from_layers(region.src_subresource);
479 cmd.set_subresource_access(src, src_region, AccessType::TransferRead);
480
481 let dst_region = image_subresource_range_from_layers(region.dst_subresource);
482 cmd.set_subresource_access(dst, dst_region, AccessType::TransferWrite);
483 }
484
485 cmd.record_cmd(move |cmd| {
486 let src_image = cmd.resource(src).handle;
487 let dst_image = cmd.resource(dst).handle;
488
489 unsafe {
490 cmd.device.cmd_blit_image(
491 cmd.handle,
492 src_image,
493 vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
494 dst_image,
495 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
496 regions.as_ref(),
497 filter,
498 );
499 }
500 })
501 .end_cmd()
502 }
503
504 #[profiling::function]
506 pub fn clear_color_image(
507 &mut self,
508 image: impl Into<AnyImageNode>,
509 color: impl Into<ClearColorValue>,
510 ) -> &mut Self {
511 let color = color.into().into();
512 let image = image.into();
513 let image_view = self.resource(image).info.into();
514
515 self.begin_cmd()
516 .debug_name("clear color")
517 .subresource_access(image, image_view, AccessType::TransferWrite)
518 .record_cmd(move |cmd| {
519 let image = cmd.resource(image);
520
521 unsafe {
522 cmd.device.cmd_clear_color_image(
523 cmd.handle,
524 image.handle,
525 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
526 &color,
527 &[image_view],
528 );
529 }
530 })
531 .end_cmd()
532 }
533
534 #[profiling::function]
536 pub fn clear_depth_stencil_image(
537 &mut self,
538 image: impl Into<AnyImageNode>,
539 depth: f32,
540 stencil: u32,
541 ) -> &mut Self {
542 let image = image.into();
543 let image_view = self.resource(image).info.into();
544
545 self.begin_cmd()
546 .debug_name("clear depth/stencil")
547 .subresource_access(image, image_view, AccessType::TransferWrite)
548 .record_cmd(move |cmd| {
549 let image = cmd.resource(image);
550
551 unsafe {
552 cmd.device.cmd_clear_depth_stencil_image(
553 cmd.handle,
554 image.handle,
555 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
556 &vk::ClearDepthStencilValue { depth, stencil },
557 &[image_view],
558 );
559 }
560 })
561 .end_cmd()
562 }
563
564 pub fn copy_buffer(
566 &mut self,
567 src: impl Into<AnyBufferNode>,
568 dst: impl Into<AnyBufferNode>,
569 ) -> &mut Self {
570 let src = src.into();
571 let dst = dst.into();
572 let src_info = self.resource(src).info;
573 let dst_info = self.resource(dst).info;
574
575 self.copy_buffer_region(
576 src,
577 dst,
578 [vk::BufferCopy {
579 src_offset: 0,
580 dst_offset: 0,
581 size: src_info.size.min(dst_info.size),
582 }],
583 )
584 }
585
586 #[profiling::function]
588 pub fn copy_buffer_region(
589 &mut self,
590 src: impl Into<AnyBufferNode>,
591 dst: impl Into<AnyBufferNode>,
592 regions: impl AsRef<[vk::BufferCopy]> + 'static + Send,
593 ) -> &mut Self {
594 let src = src.into();
595 let dst = dst.into();
596
597 #[cfg(debug_assertions)]
598 let src_size = self.resource(src).info.size;
599
600 #[cfg(debug_assertions)]
601 let dst_size = self.resource(dst).info.size;
602
603 let mut cmd = self.begin_cmd().debug_name("copy buffer");
604
605 for region in regions.as_ref() {
606 #[cfg(debug_assertions)]
607 {
608 assert!(
609 region.src_offset + region.size <= src_size,
610 "source range end ({}) exceeds source size ({src_size})",
611 region.src_offset + region.size
612 );
613 assert!(
614 region.dst_offset + region.size <= dst_size,
615 "destination range end ({}) exceeds destination size ({dst_size})",
616 region.dst_offset + region.size
617 );
618 };
619
620 cmd.set_subresource_access(
621 src,
622 region.src_offset..region.src_offset + region.size,
623 AccessType::TransferRead,
624 );
625 cmd.set_subresource_access(
626 dst,
627 region.dst_offset..region.dst_offset + region.size,
628 AccessType::TransferWrite,
629 );
630 }
631
632 cmd.record_cmd(move |cmd| {
633 let src = cmd.resource(src);
634 let dst = cmd.resource(dst);
635
636 unsafe {
637 cmd.device
638 .cmd_copy_buffer(cmd.handle, src.handle, dst.handle, regions.as_ref());
639 }
640 })
641 .end_cmd()
642 }
643
644 pub fn copy_buffer_to_image(
646 &mut self,
647 src: impl Into<AnyBufferNode>,
648 dst: impl Into<AnyImageNode>,
649 ) -> &mut Self {
650 let dst = dst.into();
651 let dst_info = self.resource(dst).info;
652
653 self.copy_buffer_to_image_region(
654 src,
655 dst,
656 [vk::BufferImageCopy {
657 buffer_offset: 0,
658 buffer_row_length: dst_info.width,
659 buffer_image_height: dst_info.height,
660 image_subresource: vk::ImageSubresourceLayers {
661 aspect_mask: format_aspect_mask(dst_info.fmt),
662 mip_level: 0,
663 base_array_layer: 0,
664 layer_count: 1,
665 },
666 image_offset: Default::default(),
667 image_extent: vk::Extent3D {
668 depth: dst_info.depth,
669 height: dst_info.height,
670 width: dst_info.width,
671 },
672 }],
673 )
674 }
675
676 #[profiling::function]
678 pub fn copy_buffer_to_image_region(
679 &mut self,
680 src: impl Into<AnyBufferNode>,
681 dst: impl Into<AnyImageNode>,
682 regions: impl AsRef<[vk::BufferImageCopy]> + 'static + Send,
683 ) -> &mut Self {
684 let src = src.into();
685 let dst = dst.into();
686 let dst_info = self.resource(dst).info;
687
688 let mut cmd = self.begin_cmd().debug_name("copy buffer to image");
689
690 for region in regions.as_ref() {
691 let block_bytes_size = format_texel_block_size(dst_info.fmt);
692 let (block_height, block_width) = format_texel_block_extent(dst_info.fmt);
693 let data_size = block_bytes_size
694 * (region.buffer_row_length / block_width)
695 * (region.buffer_image_height / block_height);
696
697 cmd.set_subresource_access(
698 src,
699 region.buffer_offset..region.buffer_offset + data_size as vk::DeviceSize,
700 AccessType::TransferRead,
701 );
702 cmd.set_subresource_access(
703 dst,
704 image_subresource_range_from_layers(region.image_subresource),
705 AccessType::TransferWrite,
706 );
707 }
708
709 cmd.record_cmd(move |cmd| {
710 let src = cmd.resource(src);
711 let dst = cmd.resource(dst);
712
713 unsafe {
714 cmd.device.cmd_copy_buffer_to_image(
715 cmd.handle,
716 src.handle,
717 dst.handle,
718 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
719 regions.as_ref(),
720 );
721 }
722 })
723 .end_cmd()
724 }
725
726 pub fn copy_image(
728 &mut self,
729 src: impl Into<AnyImageNode>,
730 dst: impl Into<AnyImageNode>,
731 ) -> &mut Self {
732 let src = src.into();
733 let src_info = self.resource(src).info;
734
735 let dst = dst.into();
736 let dst_info = self.resource(dst).info;
737
738 self.copy_image_region(
739 src,
740 dst,
741 [vk::ImageCopy {
742 src_subresource: vk::ImageSubresourceLayers {
743 aspect_mask: format_aspect_mask(src_info.fmt),
744 mip_level: 0,
745 base_array_layer: 0,
746 layer_count: src_info.array_layer_count,
747 },
748 src_offset: vk::Offset3D { x: 0, y: 0, z: 0 },
749 dst_subresource: vk::ImageSubresourceLayers {
750 aspect_mask: format_aspect_mask(dst_info.fmt),
751 mip_level: 0,
752 base_array_layer: 0,
753 layer_count: src_info.array_layer_count,
754 },
755 dst_offset: vk::Offset3D { x: 0, y: 0, z: 0 },
756 extent: vk::Extent3D {
757 depth: src_info.depth.clamp(1, dst_info.depth),
758 height: src_info.height.clamp(1, dst_info.height),
759 width: src_info.width.min(dst_info.width),
760 },
761 }],
762 )
763 }
764
765 #[profiling::function]
767 pub fn copy_image_region(
768 &mut self,
769 src: impl Into<AnyImageNode>,
770 dst: impl Into<AnyImageNode>,
771 regions: impl AsRef<[vk::ImageCopy]> + 'static + Send,
772 ) -> &mut Self {
773 let src = src.into();
774 let dst = dst.into();
775
776 let mut cmd = self.begin_cmd().debug_name("copy image");
777
778 for region in regions.as_ref() {
779 cmd.set_subresource_access(
780 src,
781 image_subresource_range_from_layers(region.src_subresource),
782 AccessType::TransferRead,
783 );
784 cmd.set_subresource_access(
785 dst,
786 image_subresource_range_from_layers(region.dst_subresource),
787 AccessType::TransferWrite,
788 );
789 }
790
791 cmd.record_cmd(move |cmd| {
792 let src = cmd.resource(src);
793 let dst = cmd.resource(dst);
794
795 unsafe {
796 cmd.device.cmd_copy_image(
797 cmd.handle,
798 src.handle,
799 vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
800 dst.handle,
801 vk::ImageLayout::TRANSFER_DST_OPTIMAL,
802 regions.as_ref(),
803 );
804 }
805 })
806 .end_cmd()
807 }
808
809 pub fn copy_image_to_buffer(
811 &mut self,
812 src: impl Into<AnyImageNode>,
813 dst: impl Into<AnyBufferNode>,
814 ) -> &mut Self {
815 let src = src.into();
816 let dst = dst.into();
817
818 let src_info = self.resource(src).info;
819
820 self.copy_image_to_buffer_region(
821 src,
822 dst,
823 [vk::BufferImageCopy {
824 buffer_offset: 0,
825 buffer_row_length: src_info.width,
826 buffer_image_height: src_info.height,
827 image_subresource: vk::ImageSubresourceLayers {
828 aspect_mask: format_aspect_mask(src_info.fmt),
829 mip_level: 0,
830 base_array_layer: 0,
831 layer_count: 1,
832 },
833 image_offset: Default::default(),
834 image_extent: vk::Extent3D {
835 depth: src_info.depth,
836 height: src_info.height,
837 width: src_info.width,
838 },
839 }],
840 )
841 }
842
843 #[profiling::function]
845 pub fn copy_image_to_buffer_region(
846 &mut self,
847 src: impl Into<AnyImageNode>,
848 dst: impl Into<AnyBufferNode>,
849 regions: impl AsRef<[vk::BufferImageCopy]> + 'static + Send,
850 ) -> &mut Self {
851 let src = src.into();
852 let src_info = self.resource(src).info;
853 let dst = dst.into();
854
855 let mut cmd = self.begin_cmd().debug_name("copy image to buffer");
856
857 for region in regions.as_ref() {
858 let block_bytes_size = format_texel_block_size(src_info.fmt);
859 let (block_height, block_width) = format_texel_block_extent(src_info.fmt);
860 let data_size = block_bytes_size
861 * (region.buffer_row_length / block_width)
862 * (region.buffer_image_height / block_height);
863
864 cmd.set_subresource_access(
865 src,
866 image_subresource_range_from_layers(region.image_subresource),
867 AccessType::TransferRead,
868 );
869 cmd.set_subresource_access(
870 dst,
871 region.buffer_offset..region.buffer_offset + data_size as vk::DeviceSize,
872 AccessType::TransferWrite,
873 );
874 }
875
876 cmd.record_cmd(move |cmd| {
877 let src = cmd.resource(src);
878 let dst = cmd.resource(dst);
879
880 unsafe {
881 cmd.device.cmd_copy_image_to_buffer(
882 cmd.handle,
883 src.handle,
884 vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
885 dst.handle,
886 regions.as_ref(),
887 );
888 }
889 })
890 .end_cmd()
891 }
892
893 pub fn fill_buffer(
895 &mut self,
896 buffer: impl Into<AnyBufferNode>,
897 region: Range<vk::DeviceSize>,
898 data: u32,
899 ) -> &mut Self {
900 let buffer = buffer.into();
901
902 self.begin_cmd()
903 .debug_name("fill buffer")
904 .subresource_access(buffer, region.clone(), AccessType::TransferWrite)
905 .record_cmd(move |cmd| {
906 let buffer = cmd.resource(buffer);
907
908 unsafe {
909 cmd.device.cmd_fill_buffer(
910 cmd.handle,
911 buffer.handle,
912 region.start,
913 region.end - region.start,
914 data,
915 );
916 }
917 })
918 .end_cmd()
919 }
920
921 #[profiling::function]
923 fn first_node_access_pass_index(&self, resource_node: impl Node) -> Option<usize> {
924 let node_idx = resource_node.index();
925
926 for (pass_idx, pass) in self.cmds.iter().enumerate() {
927 for exec in pass.execs.iter() {
928 if exec.accesses.contains_key(&node_idx) {
929 return Some(pass_idx);
930 }
931 }
932 }
933
934 None
935 }
936
937 #[profiling::function]
940 pub fn into_submission(mut self) -> Submission {
941 for cmd in &mut self.cmds {
943 debug_assert!(cmd.expect_last_exec().func.is_none());
944
945 cmd.execs.pop();
946 }
947
948 Submission::new(self)
949 }
950
951 pub fn resource<N>(&self, resource_node: N) -> &N::Resource
954 where
955 N: Node,
956 {
957 resource_node.borrow(&self.resources)
958 }
959
960 #[profiling::function]
962 pub fn update_buffer(
963 &mut self,
964 buffer: impl Into<AnyBufferNode>,
965 offset: vk::DeviceSize,
966 data: impl AsRef<[u8]> + 'static + Send,
967 ) -> &mut Self {
968 let buffer = buffer.into();
969 let data_end = offset + data.as_ref().len() as vk::DeviceSize;
970
971 #[cfg(debug_assertions)]
972 {
973 let buffer_info = self.resource(buffer).info;
974
975 assert!(
976 data_end <= buffer_info.size,
977 "data range end ({data_end}) exceeds buffer size ({})",
978 buffer_info.size
979 );
980 }
981
982 self.begin_cmd()
983 .debug_name("update buffer")
984 .subresource_access(buffer, offset..data_end, AccessType::TransferWrite)
985 .record_cmd(move |cmd| {
986 let buffer = cmd.resource(buffer);
987
988 unsafe {
989 cmd.device
990 .cmd_update_buffer(cmd.handle, buffer.handle, offset, data.as_ref());
991 }
992 })
993 .end_cmd()
994 }
995}
996
997pub trait Node {
1001 type Resource;
1003
1004 #[doc(hidden)]
1005 fn borrow(self, resources: &[AnyResource]) -> &Self::Resource;
1006
1007 #[doc(hidden)]
1008 fn index(&self) -> NodeIndex;
1009}
1010
1011pub trait Resource {
1016 type Node;
1018
1019 #[doc(hidden)]
1020 fn bind_graph(self, _: &mut Graph) -> Self::Node;
1021
1022 #[deprecated = "use bind_graph function"]
1023 #[doc(hidden)]
1024 fn bind(self, graph: &mut Graph) -> Self::Node
1025 where
1026 Self: Sized,
1027 {
1028 self.bind_graph(graph)
1029 }
1030}
1031
1032impl Resource for SwapchainImage {
1033 type Node = SwapchainImageNode;
1034
1035 fn bind_graph(self, graph: &mut Graph) -> Self::Node {
1036 let node = Self::Node::new(graph.resources.len());
1038
1039 let resource = AnyResource::SwapchainImage(Box::new(self));
1042 graph.resources.push(resource);
1043
1044 node
1045 }
1046}
1047
1048macro_rules! resource {
1049 ($name:ident) => {
1050 paste::paste! {
1051 impl Resource for $name {
1052 type Node = [<$name Node>];
1053
1054 #[profiling::function]
1055 fn bind_graph(self, graph: &mut Graph) -> Self::Node {
1056 let node = Self::Node::new(graph.resources.len());
1059
1060 let resource = AnyResource::$name(Arc::new(self));
1061 graph.resources.push(resource);
1062
1063 node
1064 }
1065 }
1066
1067 impl Resource for Arc<$name> {
1068 type Node = [<$name Node>];
1069
1070 #[profiling::function]
1071 fn bind_graph(self, graph: &mut Graph) -> Self::Node {
1072 for (idx, existing_resource) in graph.resources.iter_mut().enumerate() {
1077 if let AnyResource::$name(existing_resource) = existing_resource
1078 && Arc::ptr_eq(existing_resource, &self) {
1079 return Self::Node::new(idx);
1080 }
1081 }
1082
1083 let node = Self::Node::new(graph.resources.len());
1085 let resource = AnyResource::$name(self);
1086 graph.resources.push(resource);
1087
1088 node
1089 }
1090 }
1091
1092 impl<'a> Resource for &'a Arc<$name> {
1093 type Node = [<$name Node>];
1094
1095 fn bind_graph(self, graph: &mut Graph) -> Self::Node {
1096 Arc::clone(self).bind_graph(graph)
1100 }
1101 }
1102
1103 impl Resource for Lease<$name> {
1104 type Node = [<$name LeaseNode>];
1105
1106 #[profiling::function]
1107 fn bind_graph(self, graph: &mut Graph) -> Self::Node {
1108 let node = Self::Node::new(graph.resources.len());
1113 let resource = AnyResource::[<$name Lease>](Arc::new(self));
1114 graph.resources.push(resource);
1115
1116 node
1117 }
1118 }
1119
1120 impl Resource for Arc<Lease<$name>> {
1121 type Node = [<$name LeaseNode>];
1122
1123 #[profiling::function]
1124 fn bind_graph(self, graph: &mut Graph) -> Self::Node {
1125 for (idx, existing_resource) in graph.resources.iter().enumerate() {
1131 if let AnyResource::[<$name Lease>](existing_resource) = existing_resource
1132 && Arc::ptr_eq(existing_resource, &self) {
1133 return Self::Node::new(idx);
1134 }
1135 }
1136
1137 let node = Self::Node::new(graph.resources.len());
1139 let resource = AnyResource::[<$name Lease>](self);
1140 graph.resources.push(resource);
1141
1142 node
1143 }
1144 }
1145
1146 impl<'a> Resource for &'a Arc<Lease<$name>> {
1147 type Node = [<$name LeaseNode>];
1148
1149 fn bind_graph(self, graph: &mut Graph) -> Self::Node {
1150 Arc::clone(self).bind_graph(graph)
1154 }
1155 }
1156 }
1157 };
1158}
1159
1160resource!(AccelerationStructure);
1161resource!(Image);
1162resource!(Buffer);
1163
1164#[deprecated]
1165#[doc(hidden)]
1166pub mod graph {
1167 #[deprecated = "use vk_graph::node module"]
1168 pub mod node {
1169 #[deprecated = "use vk_graph::node::AccelerationStructureLeaseNode"]
1170 pub type AccelerationStructureLeaseNode = crate::node::AccelerationStructureLeaseNode;
1171
1172 #[deprecated = "use vk_graph::node::AccelerationStructureNode"]
1173 pub type AccelerationStructureNode = crate::node::AccelerationStructureNode;
1174
1175 #[deprecated = "use vk_graph::node::AnyAccelerationStructureNode"]
1176 pub type AnyAccelerationStructureNode = crate::node::AnyAccelerationStructureNode;
1177
1178 #[deprecated = "use vk_graph::node::AnyBufferNode"]
1179 pub type AnyBufferNode = crate::node::AnyBufferNode;
1180
1181 #[deprecated = "use vk_graph::node::AnyImageNode"]
1182 pub type AnyImageNode = crate::node::AnyImageNode;
1183
1184 #[deprecated = "use vk_graph::node::BufferLeaseNode"]
1185 pub type BufferLeaseNode = crate::node::BufferLeaseNode;
1186
1187 #[deprecated = "use vk_graph::node::BufferNode"]
1188 pub type BufferNode = crate::node::BufferNode;
1189
1190 #[deprecated = "use vk_graph::node::ImageLeaseNode"]
1191 pub type ImageLeaseNode = crate::node::ImageLeaseNode;
1192
1193 #[deprecated = "use vk_graph::node::ImageNode"]
1194 pub type ImageNode = crate::node::ImageNode;
1195
1196 #[deprecated = "use vk_graph::node::Node"]
1197 pub type Node = dyn crate::Node<Resource = ()>;
1198
1199 #[deprecated = "use vk_graph::node::SwapchainImageNode"]
1200 pub type SwapchainImageNode = crate::node::SwapchainImageNode;
1201 }
1202
1203 #[deprecated]
1204 #[doc(hidden)]
1205 pub mod pass_ref {
1206 #[deprecated = "use vk_graph::cmd::CommandRef"]
1207 pub type Acceleration<'a> = crate::cmd::CommandRef<'a>;
1208
1209 #[deprecated = "use vk_graph::cmd::CommandRef"]
1210 pub type AccelerationStructureBuildInfo = crate::cmd::BuildAccelerationStructureInfo;
1211
1212 #[deprecated = "use vk_graph::cmd::CommandRef"]
1213 pub type AccelerationStructureIndirectBuildInfo =
1214 crate::cmd::BuildAccelerationStructureIndirectInfo;
1215
1216 #[deprecated = "use vk_graph::cmd::CommandRef"]
1217 pub type AccelerationStructureIndirectUpdateInfo =
1218 crate::cmd::UpdateAccelerationStructureIndirectInfo;
1219
1220 #[deprecated = "use vk_graph::cmd::CommandRef"]
1221 pub type AccelerationStructureUpdateInfo = crate::cmd::UpdateAccelerationStructureInfo;
1222
1223 #[deprecated = "use vk_graph::cmd::Binding"]
1224 pub type Descriptor = crate::cmd::Binding;
1225
1226 #[deprecated = "use vk_graph::cmd::GraphicCommandRef"]
1227 pub type Draw<'a> = crate::cmd::GraphicCommandRef<'a>;
1228
1229 #[deprecated = "use vk_graph::cmd::CommandRef"]
1230 pub type PassRef<'a> = crate::cmd::Command<'a>;
1231
1232 #[deprecated = "use vk_graph::cmd::PipelineCommand"]
1233 pub type PipelinePassRef<'a, T> = crate::cmd::PipelineCommand<'a, T>;
1234
1235 #[deprecated = "use vk_graph::cmd::RayTraceCommandRef"]
1236 pub type RayTrace<'a> = crate::cmd::RayTraceCommandRef<'a>;
1237
1238 #[deprecated = "use vk_graph::ViewInfo"]
1239 pub type ViewType = crate::cmd::ViewInfo;
1240
1241 #[deprecated = "remove"]
1242 pub trait View {
1243 type Information;
1244 }
1245 }
1246
1247 #[deprecated = "use vk_graph::Graph"]
1248 pub type RenderGraph = crate::Graph;
1249
1250 #[deprecated = "use vk_graph::Submission"]
1251 pub type Resolver = crate::Submission;
1252}
1253
1254#[allow(deprecated)]
1255#[allow(unused)]
1256#[doc(hidden)]
1257pub(crate) mod deprecated {
1258 use {
1259 crate::{
1260 AnyResource, Graph, Node, Resource,
1261 driver::{
1262 DriverError,
1263 accel_struct::{AccelerationStructure, AccelerationStructureInfo},
1264 buffer::{Buffer, BufferInfo},
1265 cmd_buf::{CommandBuffer, CommandBufferInfo},
1266 descriptor_set::{DescriptorPool, DescriptorPoolInfo},
1267 device::Device,
1268 image::{Image, ImageInfo},
1269 render_pass::{RenderPass, RenderPassInfo},
1270 swapchain::{Swapchain, SwapchainImage, SwapchainInfo},
1271 },
1272 node::{
1273 AccelerationStructureLeaseNode, AccelerationStructureNode,
1274 AnyAccelerationStructureNode, AnyBufferNode, AnyImageNode, BufferLeaseNode,
1275 BufferNode, ImageLeaseNode, ImageNode, SwapchainImageNode,
1276 },
1277 pool::{Lease, Pool},
1278 },
1279 ash::vk,
1280 std::{error, fmt, ops::Range, sync::Arc},
1281 };
1282
1283 #[derive(Clone, Copy, Debug)]
1285 pub struct ClearColorValue(pub [f32; 4]);
1286
1287 impl From<[f32; 3]> for ClearColorValue {
1288 fn from(color: [f32; 3]) -> Self {
1289 [color[0], color[1], color[2], 1.0].into()
1290 }
1291 }
1292
1293 impl From<[f32; 4]> for ClearColorValue {
1294 fn from(color: [f32; 4]) -> Self {
1295 Self(color)
1296 }
1297 }
1298
1299 impl From<[u8; 3]> for ClearColorValue {
1300 fn from(color: [u8; 3]) -> Self {
1301 [color[0], color[1], color[2], u8::MAX].into()
1302 }
1303 }
1304
1305 impl From<[u8; 4]> for ClearColorValue {
1306 fn from(color: [u8; 4]) -> Self {
1307 [
1308 color[0] as f32 / u8::MAX as f32,
1309 color[1] as f32 / u8::MAX as f32,
1310 color[2] as f32 / u8::MAX as f32,
1311 color[3] as f32 / u8::MAX as f32,
1312 ]
1313 .into()
1314 }
1315 }
1316
1317 #[deprecated = "use Swapchain from vk_graph_window crate"]
1318 #[derive(Debug)]
1319 #[doc(hidden)]
1320 pub struct Display {
1321 swapchain_info: SwapchainInfo,
1322 }
1323
1324 impl Display {
1325 pub fn new(
1326 device: &Arc<Device>,
1327 swapchain: Swapchain,
1328 info: impl Into<DisplayInfo>,
1329 ) -> Result<Self, DriverError> {
1330 let _ = device;
1331 let _ = swapchain;
1332 let _ = info.into();
1333
1334 Err(DriverError::Unsupported)
1335 }
1336
1337 pub fn acquire_next_image(&mut self) -> Result<Option<SwapchainImage>, DisplayError> {
1338 Err(DisplayError)
1339 }
1340
1341 pub fn present_image(
1342 &mut self,
1343 pool: &mut impl ResolverPool,
1344 render_graph: crate::graph::RenderGraph,
1345 swapchain_image: SwapchainImageNode,
1346 queue_index: u32,
1347 ) -> Result<(), DisplayError> {
1348 let _ = pool;
1349 let _ = render_graph;
1350 let _ = swapchain_image;
1351 let _ = queue_index;
1352
1353 Err(DisplayError)
1354 }
1355
1356 pub fn set_swapchain_info(&mut self, info: impl Into<SwapchainInfo>) {
1357 self.swapchain_info = info.into();
1358 }
1359
1360 pub fn swapchain_info(&self) -> SwapchainInfo {
1361 self.swapchain_info
1362 }
1363 }
1364
1365 #[deprecated = "use vk_graph_window::SwapchainError"]
1366 #[derive(Clone, Copy, Debug, Default)]
1367 #[doc(hidden)]
1368 pub struct DisplayError;
1369
1370 impl fmt::Display for DisplayError {
1371 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1372 f.write_str("deprecated Display API is unsupported; use vk_graph_window swapchain APIs")
1373 }
1374 }
1375
1376 impl error::Error for DisplayError {}
1377
1378 #[deprecated = "use vk_graph_window::SwapchainInfo"]
1379 #[derive(Clone, Copy, Debug, Default)]
1380 #[doc(hidden)]
1381 pub struct DisplayInfo;
1382
1383 #[deprecated = "use vk_graph_window::SwapchainInfoBuilder"]
1384 #[derive(Clone, Copy, Debug, Default)]
1385 #[doc(hidden)]
1386 pub struct DisplayInfoBuilder;
1387
1388 impl Graph {
1390 #[deprecated = "use begin_cmd function"]
1391 #[doc(hidden)]
1392 pub fn begin_pass(&mut self, name: impl AsRef<str>) -> crate::graph::pass_ref::PassRef<'_> {
1393 self.begin_cmd().debug_name(name.as_ref().to_owned())
1394 }
1395
1396 #[deprecated = "use bind_resource function"]
1397 #[doc(hidden)]
1398 pub fn bind_node<R>(&mut self, resource: R) -> R::Node
1399 where
1400 R: Resource,
1401 {
1402 self.bind_resource(resource)
1403 }
1404
1405 #[deprecated = "use blit_image_region function"]
1406 #[doc(hidden)]
1407 pub fn blit_image_regions(
1408 &mut self,
1409 src_node: impl Into<AnyImageNode>,
1410 dst_node: impl Into<AnyImageNode>,
1411 filter: vk::Filter,
1412 regions: impl AsRef<[vk::ImageBlit]> + 'static + Send,
1413 ) -> &mut Self {
1414 self.blit_image_region(src_node, dst_node, filter, regions)
1415 }
1416
1417 #[deprecated = "use clear_color_image function"]
1418 #[doc(hidden)]
1419 pub fn clear_color_image_value(
1420 &mut self,
1421 image_node: impl Into<AnyImageNode>,
1422 color_value: impl Into<ClearColorValue>,
1423 ) -> &mut Self {
1424 self.clear_color_image(image_node, color_value.into().0)
1425 }
1426
1427 #[deprecated = "use clear_depth_stencil_image function"]
1428 #[doc(hidden)]
1429 pub fn clear_depth_stencil_image_value(
1430 &mut self,
1431 image_node: impl Into<AnyImageNode>,
1432 depth: f32,
1433 stencil: u32,
1434 ) -> &mut Self {
1435 self.clear_depth_stencil_image(image_node, depth, stencil)
1436 }
1437
1438 #[deprecated = "use copy_buffer_region function"]
1439 #[doc(hidden)]
1440 pub fn copy_buffer_regions(
1441 &mut self,
1442 src_node: impl Into<AnyBufferNode>,
1443 dst_node: impl Into<AnyBufferNode>,
1444 regions: impl AsRef<[vk::BufferCopy]> + 'static + Send,
1445 ) -> &mut Self {
1446 self.copy_buffer_region(src_node, dst_node, regions)
1447 }
1448
1449 #[deprecated = "use copy_buffer_to_image_region function"]
1450 #[doc(hidden)]
1451 pub fn copy_buffer_to_image_regions(
1452 &mut self,
1453 src_node: impl Into<AnyBufferNode>,
1454 dst_node: impl Into<AnyImageNode>,
1455 regions: impl AsRef<[vk::BufferImageCopy]> + 'static + Send,
1456 ) -> &mut Self {
1457 self.copy_buffer_to_image_region(src_node, dst_node, regions)
1458 }
1459
1460 #[deprecated = "use copy_image_region function"]
1461 #[doc(hidden)]
1462 pub fn copy_image_regions(
1463 &mut self,
1464 src_node: impl Into<AnyImageNode>,
1465 dst_node: impl Into<AnyImageNode>,
1466 regions: impl AsRef<[vk::ImageCopy]> + 'static + Send,
1467 ) -> &mut Self {
1468 self.copy_image_region(src_node, dst_node, regions)
1469 }
1470
1471 #[deprecated = "use copy_image_to_buffer_region function"]
1472 #[doc(hidden)]
1473 pub fn copy_image_to_buffer_regions(
1474 &mut self,
1475 src_node: impl Into<AnyImageNode>,
1476 dst_node: impl Into<AnyBufferNode>,
1477 regions: impl AsRef<[vk::BufferImageCopy]> + 'static + Send,
1478 ) -> &mut Self {
1479 self.copy_image_to_buffer_region(src_node, dst_node, regions)
1480 }
1481
1482 #[deprecated = "use fill_buffer function"]
1483 #[doc(hidden)]
1484 pub fn fill_buffer_region(
1485 &mut self,
1486 buffer_node: impl Into<AnyBufferNode>,
1487 data: u32,
1488 region: Range<vk::DeviceSize>,
1489 ) -> &mut Self {
1490 self.fill_buffer(buffer_node, region, data)
1491 }
1492
1493 #[deprecated = "use device_address function of resource function result"]
1494 #[doc(hidden)]
1495 pub fn node_device_address(&self, node: impl Node) -> vk::DeviceAddress {
1496 let idx = node.index();
1497
1498 self.resources[idx]
1499 .as_buffer()
1500 .expect("missing buffer resource")
1501 .device_address()
1502 }
1503
1504 #[deprecated = "dereference info field of resource function result"]
1505 #[doc(hidden)]
1506 pub fn node_info<N>(&self, node: N) -> N::Type
1507 where
1508 N: Node + Info,
1509 {
1510 node.info(&self.resources)
1511 }
1512
1513 #[deprecated = "use into_submission function"]
1514 #[doc(hidden)]
1515 pub fn resolve(self) -> crate::graph::Resolver {
1516 self.into_submission()
1517 }
1518
1519 #[deprecated = "use resource and clone functions"]
1520 #[doc(hidden)]
1521 pub fn unbind_node<N>(&mut self, node: N) -> N::Result
1522 where
1523 N: Unbind,
1524 {
1525 node.unbind(&self.resources)
1526 }
1527
1528 #[deprecated = "use update_buffer function"]
1529 #[doc(hidden)]
1530 pub fn update_buffer_offset(
1531 &mut self,
1532 buffer_node: impl Into<AnyBufferNode>,
1533 offset: vk::DeviceSize,
1534 data: impl AsRef<[u8]> + 'static + Send,
1535 ) -> &mut Self {
1536 self.update_buffer(buffer_node, offset, data)
1537 }
1538 }
1539
1540 pub trait Info {
1541 type Type;
1542
1543 fn info(&self, _: &[AnyResource]) -> Self::Type
1544 where
1545 Self: Node;
1546 }
1547
1548 impl Info for SwapchainImageNode {
1549 type Type = ImageInfo;
1550
1551 fn info(&self, resources: &[AnyResource]) -> Self::Type
1552 where
1553 Self: Node,
1554 {
1555 resources[self.index()]
1556 .as_swapchain_image()
1557 .expect("missing swapchain image")
1558 .info
1559 }
1560 }
1561
1562 macro_rules! info {
1563 ($name:ident) => {
1564 paste::paste! {
1565 impl Info for [<$name Node>] {
1566 type Type = [<$name Info>];
1567
1568 fn info(&self, resources: &[AnyResource]) -> Self::Type
1569 where
1570 Self: Node,
1571 {
1572 let AnyResource::$name(resource) = &resources[self.index()] else {
1573 panic!("invalid node");
1574 };
1575
1576 resource.info
1577 }
1578 }
1579
1580 impl Info for [<Any $name Node>] {
1581 type Type = [<$name Info>];
1582
1583 fn info(&self, resources: &[AnyResource]) -> Self::Type
1584 where
1585 Self: Node,
1586 {
1587 let AnyResource::$name(resource) = &resources[self.index()] else {
1588 panic!("invalid node");
1589 };
1590
1591 resource.info
1592 }
1593 }
1594
1595 impl Info for [<$name LeaseNode>] {
1596 type Type = [<$name Info>];
1597
1598 fn info(&self, resources: &[AnyResource]) -> Self::Type
1599 where
1600 Self: Node,
1601 {
1602 let AnyResource::[<$name Lease>](resource) = &resources[self.index()] else {
1603 panic!("invalid node");
1604 };
1605
1606 resource.info
1607 }
1608 }
1609
1610 impl Unbind for [<$name Node>] {
1611 type Result = Arc<$name>;
1612
1613 fn unbind(&self, resources: &[AnyResource]) -> Self::Result {
1614 let AnyResource::$name(resource) = &resources[self.index()] else {
1615 panic!("invalid node");
1616 };
1617
1618 resource.clone()
1619 }
1620 }
1621
1622 impl Unbind for [<$name LeaseNode>] {
1623 type Result = Arc<Lease<$name>>;
1624
1625 fn unbind(&self, resources: &[AnyResource]) -> Self::Result {
1626 let AnyResource::[<$name Lease>](resource) = &resources[self.index()] else {
1627 panic!("invalid node");
1628 };
1629
1630 resource.clone()
1631 }
1632 }
1633 }
1634 };
1635 }
1636
1637 info!(AccelerationStructure);
1638 info!(Buffer);
1639 info!(Image);
1640
1641 #[deprecated = "remove"]
1642 pub trait ResolverPool:
1643 Pool<DescriptorPoolInfo, DescriptorPool>
1644 + Pool<RenderPassInfo, RenderPass>
1645 + Pool<CommandBufferInfo, CommandBuffer>
1646 + Send
1647 {
1648 }
1649
1650 pub trait Unbind: Node {
1651 type Result;
1652
1653 fn unbind(&self, _: &[AnyResource]) -> Self::Result;
1654 }
1655}