1use {
2 super::{AttachmentIndex, cmd_ref::CommandRef, pipeline::PipelineCommand},
3 crate::{
4 Attachment, ColorAttachment, ColorResolve, DepthStencilAttachment, DepthStencilResolve,
5 LoadOp, Node, StoreOp, SubresourceAccess,
6 cmd::SubresourceRange,
7 driver::{
8 graphics::{DepthStencilInfo, GraphicsPipeline},
9 image::{
10 ImageInfo, ImageViewInfo, image_subresource_range_contains,
11 image_subresource_range_intersects,
12 },
13 render_pass::ResolveMode,
14 },
15 node::{AnyBufferNode, AnyImageNode},
16 },
17 ash::vk,
18 std::{cell::RefCell, ops::Deref, slice},
19 vk_sync::AccessType,
20};
21
22impl PipelineCommand<'_, GraphicsPipeline> {
23 pub fn color_attachment_image(
33 mut self,
34 color_attachment: AttachmentIndex,
35 image: impl Into<AnyImageNode>,
36 load: LoadOp<ClearColorValue>,
37 store: StoreOp,
38 ) -> Self {
39 self.set_color_attachment_image(color_attachment, image, load, store);
40 self
41 }
42
43 pub fn color_attachment_image_view(
48 mut self,
49 color_attachment: AttachmentIndex,
50 image: impl Into<AnyImageNode>,
51 image_view_info: impl Into<ImageViewInfo>,
52 load: LoadOp<ClearColorValue>,
53 store: StoreOp,
54 ) -> Self {
55 self.set_color_attachment_image_view(color_attachment, image, image_view_info, load, store);
56 self
57 }
58
59 pub fn color_attachment_resolve_image(
66 mut self,
67 msaa_attachment: AttachmentIndex,
68 color_attachment: AttachmentIndex,
69 image: impl Into<AnyImageNode>,
70 ) -> Self {
71 self.set_color_attachment_resolve_image(msaa_attachment, color_attachment, image);
72 self
73 }
74
75 pub fn color_attachment_resolve_image_view(
80 mut self,
81 msaa_attachment: AttachmentIndex,
82 color_attachment: AttachmentIndex,
83 image: impl Into<AnyImageNode>,
84 image_view_info: impl Into<ImageViewInfo>,
85 ) -> Self {
86 self.set_color_attachment_resolve_image_view(
87 msaa_attachment,
88 color_attachment,
89 image,
90 image_view_info,
91 );
92 self
93 }
94
95 pub fn depth_stencil(mut self, depth_stencil: impl Into<DepthStencilInfo>) -> Self {
98 self.set_depth_stencil(depth_stencil);
99 self
100 }
101
102 pub fn depth_stencil_attachment_image(
112 mut self,
113 image: impl Into<AnyImageNode>,
114 load: LoadOp<vk::ClearDepthStencilValue>,
115 store: StoreOp,
116 ) -> Self {
117 self.set_depth_stencil_attachment_image(image, load, store);
118 self
119 }
120
121 pub fn depth_stencil_attachment_image_view(
131 mut self,
132 image: impl Into<AnyImageNode>,
133 image_view_info: impl Into<ImageViewInfo>,
134 load: LoadOp<vk::ClearDepthStencilValue>,
135 store: StoreOp,
136 ) -> Self {
137 self.set_depth_stencil_attachment_image_view(image, image_view_info, load, store);
138 self
139 }
140
141 pub fn depth_stencil_attachment_resolve_image(
148 mut self,
149 depth_stencil_attachment: AttachmentIndex,
150 image: impl Into<AnyImageNode>,
151 depth_mode: Option<ResolveMode>,
152 stencil_mode: Option<ResolveMode>,
153 ) -> Self {
154 self.set_depth_stencil_attachment_resolve_image(
155 depth_stencil_attachment,
156 image,
157 depth_mode,
158 stencil_mode,
159 );
160 self
161 }
162
163 pub fn depth_stencil_attachment_resolve_image_view(
170 mut self,
171 depth_stencil_attachment: AttachmentIndex,
172 image: impl Into<AnyImageNode>,
173 image_view_info: impl Into<ImageViewInfo>,
174 depth_mode: Option<ResolveMode>,
175 stencil_mode: Option<ResolveMode>,
176 ) -> Self {
177 self.set_depth_stencil_attachment_resolve_image_view(
178 depth_stencil_attachment,
179 image,
180 image_view_info,
181 depth_mode,
182 stencil_mode,
183 );
184 self
185 }
186
187 pub fn multiview(mut self, view_mask: u32, correlated_view_mask: u32) -> Self {
192 self.set_multiview(view_mask, correlated_view_mask);
193 self
194 }
195
196 pub fn record_cmd(
198 mut self,
199 func: impl FnOnce(GraphicsCommandRef<'_>) + Send + 'static,
200 ) -> Self {
201 self.record_cmd_mut(func);
202 self
203 }
204
205 pub fn record_cmd_mut(&mut self, func: impl FnOnce(GraphicsCommandRef<'_>) + Send + 'static) {
207 let pipeline = self
208 .cmd
209 .cmd()
210 .expect_last_pipeline()
211 .expect_graphics()
212 .clone();
213
214 self.cmd.push_exec(move |cmd| {
215 func(GraphicsCommandRef { cmd, pipeline });
216 });
217 }
218
219 pub(crate) fn record_stream_mut(
220 &mut self,
221 func: impl for<'r> Fn(GraphicsCommandRef<'r>) + Send + Sync + 'static,
222 ) {
223 let pipeline = self
224 .cmd
225 .cmd()
226 .expect_last_pipeline()
227 .expect_graphics()
228 .clone();
229
230 self.cmd.push_reusable_exec(move |cmd| {
231 func(GraphicsCommandRef {
232 cmd,
233 pipeline: pipeline.clone(),
234 });
235 });
236 }
237
238 pub fn render_area(mut self, area: vk::Rect2D) -> Self {
251 self.set_render_area(area);
252 self
253 }
254
255 pub fn set_color_attachment_image(
257 &mut self,
258 color_attachment: AttachmentIndex,
259 image: impl Into<AnyImageNode>,
260 load: LoadOp<ClearColorValue>,
261 store: StoreOp,
262 ) -> &mut Self {
263 let image = image.into();
264 let image_view: ImageViewInfo = self.cmd.graph.resources[image.index()]
265 .expect_image_info()
266 .into();
267
268 self.set_color_attachment_image_view(color_attachment, image, image_view, load, store);
269
270 self
271 }
272
273 pub fn set_color_attachment_image_view(
275 &mut self,
276 color_attachment: AttachmentIndex,
277 image: impl Into<AnyImageNode>,
278 image_view_info: impl Into<ImageViewInfo>,
279 load: LoadOp<ClearColorValue>,
280 store: StoreOp,
281 ) -> &mut Self {
282 let image = image.into();
283 let image_view_info = image_view_info.into();
284
285 match load {
286 LoadOp::Clear(color) => {
287 self.clear_color_value(color_attachment, image, color, image_view_info);
288 }
289 LoadOp::DontCare => {
290 self.attach_color(image, color_attachment, image_view_info);
291 }
292 LoadOp::Load => {
293 self.load_color(image, color_attachment, image_view_info);
294 }
295 }
296
297 if let StoreOp::Store = store {
298 self.store_color(image, color_attachment, image_view_info);
299 }
300
301 self
302 }
303
304 pub fn set_color_attachment_resolve_image(
306 &mut self,
307 msaa_attachment: AttachmentIndex,
308 color_attachment: AttachmentIndex,
309 image: impl Into<AnyImageNode>,
310 ) -> &mut Self {
311 let image = image.into();
312 let image_view: ImageViewInfo = self.cmd.graph.resources[image.index()]
313 .expect_image_info()
314 .into();
315
316 self.set_color_attachment_resolve_image_view(
317 msaa_attachment,
318 color_attachment,
319 image,
320 image_view,
321 );
322
323 self
324 }
325
326 pub fn set_color_attachment_resolve_image_view(
328 &mut self,
329 msaa_attachment: AttachmentIndex,
330 color_attachment: AttachmentIndex,
331 image: impl Into<AnyImageNode>,
332 image_view_info: impl Into<ImageViewInfo>,
333 ) -> &mut Self {
334 let image = image.into();
335 let image_view_info = image_view_info.into();
336
337 self.resolve_color(image, msaa_attachment, color_attachment, image_view_info);
338
339 self
340 }
341
342 pub fn set_depth_stencil(&mut self, depth_stencil: impl Into<DepthStencilInfo>) -> &mut Self {
344 let depth_stencil = depth_stencil.into();
345 let cmd = self.cmd.cmd_mut();
346 let exec = cmd.expect_last_exec_mut();
347
348 assert!(exec.depth_stencil.is_none());
349
350 exec.depth_stencil = Some(depth_stencil);
351
352 self
353 }
354
355 pub fn set_depth_stencil_attachment_image(
357 &mut self,
358 image: impl Into<AnyImageNode>,
359 load: LoadOp<vk::ClearDepthStencilValue>,
360 store: StoreOp,
361 ) -> &mut Self {
362 let image = image.into();
363 let image_view_info: ImageViewInfo = self.cmd.graph.resources[image.index()]
364 .expect_image_info()
365 .into();
366
367 self.set_depth_stencil_attachment_image_view(image, image_view_info, load, store);
368
369 self
370 }
371
372 pub fn set_depth_stencil_attachment_image_view(
374 &mut self,
375 image: impl Into<AnyImageNode>,
376 image_view_info: impl Into<ImageViewInfo>,
377 load: LoadOp<vk::ClearDepthStencilValue>,
378 store: StoreOp,
379 ) -> &mut Self {
380 let image = image.into();
381 let image_view_info = image_view_info.into();
382
383 match load {
384 LoadOp::Clear(color) => {
385 self.clear_depth_stencil_value(image, color.depth, color.stencil, image_view_info);
386 }
387 LoadOp::DontCare => {
388 self.attach_depth_stencil(image, image_view_info);
389 }
390 LoadOp::Load => {
391 self.load_depth_stencil(image, image_view_info);
392 }
393 }
394
395 if let StoreOp::Store = store {
396 self.store_depth_stencil(image, image_view_info);
397 }
398
399 self
400 }
401
402 pub fn set_depth_stencil_attachment_resolve_image(
404 &mut self,
405 depth_stencil_attachment: AttachmentIndex,
406 image: impl Into<AnyImageNode>,
407 depth_mode: Option<ResolveMode>,
408 stencil_mode: Option<ResolveMode>,
409 ) -> &mut Self {
410 let image = image.into();
411 let image_view: ImageViewInfo = self.cmd.graph.resources[image.index()]
412 .expect_image_info()
413 .into();
414
415 self.set_depth_stencil_attachment_resolve_image_view(
416 depth_stencil_attachment,
417 image,
418 image_view,
419 depth_mode,
420 stencil_mode,
421 );
422
423 self
424 }
425
426 pub fn set_depth_stencil_attachment_resolve_image_view(
428 &mut self,
429 depth_stencil_attachment: AttachmentIndex,
430 image: impl Into<AnyImageNode>,
431 image_view_info: impl Into<ImageViewInfo>,
432 depth_mode: Option<ResolveMode>,
433 stencil_mode: Option<ResolveMode>,
434 ) -> &mut Self {
435 let image = image.into();
436 let image_view_info = image_view_info.into();
437
438 self.resolve_depth_stencil(
439 image,
440 depth_stencil_attachment,
441 image_view_info,
442 depth_mode,
443 stencil_mode,
444 );
445
446 self
447 }
448
449 pub fn set_multiview(&mut self, view_mask: u32, correlated_view_mask: u32) -> &mut Self {
451 let cmd = self.cmd.cmd_mut();
452 let exec = cmd.expect_last_exec_mut();
453
454 exec.correlated_view_mask = correlated_view_mask;
455 exec.view_mask = view_mask;
456
457 self
458 }
459
460 pub fn set_render_area(&mut self, area: vk::Rect2D) -> &mut Self {
462 self.cmd.cmd_mut().expect_last_exec_mut().render_area = Some(area);
463 self
464 }
465}
466
467impl PipelineCommand<'_, GraphicsPipeline> {
468 fn is_input_attachment(&self, attachment_idx: AttachmentIndex) -> bool {
469 self.cmd
470 .cmd()
471 .expect_last_pipeline()
472 .expect_graphics()
473 .inner
474 .input_attachments
475 .contains(&attachment_idx)
476 }
477
478 fn set_color_attachment(
479 &mut self,
480 attachment_idx: AttachmentIndex,
481 attachment: Attachment,
482 load: LoadOp<[f32; 4]>,
483 ) {
484 let is_input = self.is_input_attachment(attachment_idx);
485 let exec = self.cmd.cmd_mut().expect_last_exec_mut();
486
487 if let Some(state) = exec.attachments.color_attachment_mut(attachment_idx) {
488 #[cfg(feature = "checked")]
489 assert!(
490 Attachment::are_compatible(Some(attachment), Some(state.attachment)),
491 "incompatible with existing attachment"
492 );
493
494 state.attachment = attachment;
495 state.load = load;
496 state.is_input = is_input;
497 state.is_attachment = true;
498 } else {
499 exec.attachments.set_color_attachment(
500 attachment_idx,
501 ColorAttachment {
502 attachment,
503 load,
504 store: StoreOp::DontCare,
505 resolve: None,
506 is_input,
507 is_attachment: true,
508 },
509 );
510 }
511 }
512
513 fn set_depth_stencil_attachment(
514 &mut self,
515 attachment: Attachment,
516 load: LoadOp<vk::ClearDepthStencilValue>,
517 ) {
518 let exec = self.cmd.cmd_mut().expect_last_exec_mut();
519
520 if let Some(state) = exec.attachments.depth_stencil_attachment_mut() {
521 #[cfg(feature = "checked")]
522 assert!(
523 Attachment::are_compatible(Some(attachment), Some(state.attachment)),
524 "incompatible with existing attachment"
525 );
526
527 state.attachment = attachment;
528 state.load = load;
529 state.is_attachment = true;
530 } else {
531 exec.attachments
532 .set_depth_stencil_attachment(DepthStencilAttachment {
533 attachment,
534 load,
535 store: StoreOp::DontCare,
536 resolve: None,
537 is_attachment: true,
538 });
539 }
540 }
541
542 fn set_color_store(&mut self, attachment_idx: AttachmentIndex, attachment: Attachment) {
543 let is_input = self.is_input_attachment(attachment_idx);
544 let exec = self.cmd.cmd_mut().expect_last_exec_mut();
545
546 if let Some(state) = exec.attachments.color_attachment_mut(attachment_idx) {
547 #[cfg(feature = "checked")]
548 assert!(
549 Attachment::are_compatible(Some(attachment), Some(state.attachment)),
550 "incompatible with existing attachment"
551 );
552
553 state.attachment = attachment;
554 state.store = StoreOp::Store;
555 state.is_attachment = true;
556 state.is_input = is_input;
557 } else {
558 exec.attachments.set_color_attachment(
559 attachment_idx,
560 ColorAttachment {
561 attachment,
562 load: LoadOp::DontCare,
563 store: StoreOp::Store,
564 resolve: None,
565 is_input,
566 is_attachment: true,
567 },
568 );
569 }
570 }
571
572 fn set_depth_stencil_store(&mut self, attachment: Attachment) {
573 let exec = self.cmd.cmd_mut().expect_last_exec_mut();
574
575 if let Some(state) = exec.attachments.depth_stencil_attachment_mut() {
576 #[cfg(feature = "checked")]
577 assert!(
578 Attachment::are_compatible(Some(attachment), Some(state.attachment)),
579 "incompatible with existing attachment"
580 );
581
582 state.attachment = attachment;
583 state.store = StoreOp::Store;
584 state.is_attachment = true;
585 } else {
586 exec.attachments
587 .set_depth_stencil_attachment(DepthStencilAttachment {
588 attachment,
589 load: LoadOp::DontCare,
590 store: StoreOp::Store,
591 resolve: None,
592 is_attachment: true,
593 });
594 }
595 }
596
597 fn set_color_resolve(
598 &mut self,
599 src_attachment_idx: AttachmentIndex,
600 dst_attachment_idx: AttachmentIndex,
601 attachment: Attachment,
602 ) {
603 let is_input = self.is_input_attachment(dst_attachment_idx);
604 let exec = self.cmd.cmd_mut().expect_last_exec_mut();
605
606 if let Some(state) = exec.attachments.color_attachment_mut(dst_attachment_idx) {
607 state.resolve = Some(ColorResolve {
608 attachment,
609 src_attachment_idx,
610 });
611 state.is_input = is_input;
612 } else {
613 exec.attachments.set_color_attachment(
614 dst_attachment_idx,
615 ColorAttachment {
616 attachment,
617 load: LoadOp::DontCare,
618 store: StoreOp::DontCare,
619 resolve: Some(ColorResolve {
620 attachment,
621 src_attachment_idx,
622 }),
623 is_input,
624 is_attachment: false,
625 },
626 );
627 }
628 }
629
630 fn set_depth_stencil_resolve(
631 &mut self,
632 dst_attachment_idx: AttachmentIndex,
633 attachment: Attachment,
634 depth_mode: Option<ResolveMode>,
635 stencil_mode: Option<ResolveMode>,
636 ) {
637 let exec = self.cmd.cmd_mut().expect_last_exec_mut();
638
639 if let Some(state) = exec.attachments.depth_stencil_attachment_mut() {
640 state.resolve = Some(DepthStencilResolve {
641 attachment,
642 dst_attachment_idx,
643 depth_mode,
644 stencil_mode,
645 });
646 } else {
647 exec.attachments
648 .set_depth_stencil_attachment(DepthStencilAttachment {
649 attachment,
650 load: LoadOp::DontCare,
651 store: StoreOp::DontCare,
652 resolve: Some(DepthStencilResolve {
653 attachment,
654 dst_attachment_idx,
655 depth_mode,
656 stencil_mode,
657 }),
658 is_attachment: false,
659 });
660 }
661 }
662
663 fn attach_color(
664 &mut self,
665 image: impl Into<AnyImageNode>,
666 attachment_idx: AttachmentIndex,
667 image_view_info: impl Into<ImageViewInfo>,
668 ) -> &mut Self {
669 let image = image.into();
670 let image_view_info = image_view_info.into();
671 let node_idx = image.index();
672 let ImageInfo { sample_count, .. } =
673 self.cmd.graph.resources[image.index()].expect_image_info();
674
675 self.set_color_attachment(
676 attachment_idx,
677 Attachment::new(image_view_info, sample_count, node_idx),
678 LoadOp::DontCare,
679 );
680
681 self.cmd.push_subresource_access(
682 image,
683 SubresourceRange::Image(image_view_info.into()),
684 AccessType::ColorAttachmentWrite,
685 );
686
687 self
688 }
689
690 fn attach_depth_stencil(
691 &mut self,
692 image: impl Into<AnyImageNode>,
693 image_view_info: impl Into<ImageViewInfo>,
694 ) -> &mut Self {
695 let image = image.into();
696 let image_view_info = image_view_info.into();
697 let node_idx = image.index();
698 let ImageInfo { sample_count, .. } =
699 self.cmd.graph.resources[image.index()].expect_image_info();
700
701 self.set_depth_stencil_attachment(
702 Attachment::new(image_view_info, sample_count, node_idx),
703 LoadOp::DontCare,
704 );
705
706 self.cmd.push_subresource_access(
707 image,
708 SubresourceRange::Image(image_view_info.into()),
709 if image_view_info
710 .aspect_mask
711 .contains(vk::ImageAspectFlags::DEPTH | vk::ImageAspectFlags::STENCIL)
712 {
713 AccessType::DepthStencilAttachmentWrite
714 } else if image_view_info
715 .aspect_mask
716 .contains(vk::ImageAspectFlags::DEPTH)
717 {
718 AccessType::DepthAttachmentWriteStencilReadOnly
719 } else {
720 AccessType::StencilAttachmentWriteDepthReadOnly
721 },
722 );
723
724 self
725 }
726
727 fn clear_color_value(
728 &mut self,
729 attachment_idx: AttachmentIndex,
730 image: impl Into<AnyImageNode>,
731 color: impl Into<ClearColorValue>,
732 image_view_info: impl Into<ImageViewInfo>,
733 ) -> &mut Self {
734 let image = image.into();
735 let image_view_info = image_view_info.into();
736 let node_idx = image.index();
737 let ImageInfo { sample_count, .. } =
738 self.cmd.graph.resources[image.index()].expect_image_info();
739
740 let color = color.into();
741 let color: vk::ClearColorValue = color.into();
742 let color = unsafe { color.float32 };
743
744 self.set_color_attachment(
745 attachment_idx,
746 Attachment::new(image_view_info, sample_count, node_idx),
747 LoadOp::Clear(color),
748 );
749
750 let mut image_access = AccessType::ColorAttachmentWrite;
751 let image_range = image_view_info.into();
752
753 if let Some(accesses) = self
754 .cmd
755 .cmd_mut()
756 .expect_last_exec_mut()
757 .accesses
758 .get_mut(&node_idx)
759 {
760 for SubresourceAccess {
761 access,
762 subresource,
763 } in accesses
764 {
765 let access_image_range = *subresource.expect_image();
766 if !image_subresource_range_intersects(access_image_range, image_range) {
767 continue;
768 }
769
770 image_access = match *access {
771 AccessType::ColorAttachmentRead | AccessType::ColorAttachmentReadWrite => {
772 AccessType::ColorAttachmentReadWrite
773 }
774 AccessType::ColorAttachmentWrite => AccessType::ColorAttachmentWrite,
775 _ => continue,
776 };
777
778 *access = image_access;
779
780 if image_subresource_range_contains(access_image_range, image_range) {
781 return self;
782 }
783 }
784 }
785
786 self.cmd
787 .push_subresource_access(image, SubresourceRange::Image(image_range), image_access);
788
789 self
790 }
791
792 fn clear_depth_stencil_value(
793 &mut self,
794 image: impl Into<AnyImageNode>,
795 depth: f32,
796 stencil: u32,
797 image_view_info: impl Into<ImageViewInfo>,
798 ) -> &mut Self {
799 let image = image.into();
800 let image_view_info = image_view_info.into();
801 let node_idx = image.index();
802 let ImageInfo { sample_count, .. } =
803 self.cmd.graph.resources[image.index()].expect_image_info();
804
805 self.set_depth_stencil_attachment(
806 Attachment::new(image_view_info, sample_count, node_idx),
807 LoadOp::Clear(vk::ClearDepthStencilValue { depth, stencil }),
808 );
809
810 let mut image_access = if image_view_info
811 .aspect_mask
812 .contains(vk::ImageAspectFlags::DEPTH | vk::ImageAspectFlags::STENCIL)
813 {
814 AccessType::DepthStencilAttachmentWrite
815 } else if image_view_info
816 .aspect_mask
817 .contains(vk::ImageAspectFlags::DEPTH)
818 {
819 AccessType::DepthAttachmentWriteStencilReadOnly
820 } else {
821 debug_assert!(
822 image_view_info
823 .aspect_mask
824 .contains(vk::ImageAspectFlags::STENCIL)
825 );
826
827 AccessType::StencilAttachmentWriteDepthReadOnly
828 };
829 let image_range = image_view_info.into();
830
831 if let Some(accesses) = self
832 .cmd
833 .cmd_mut()
834 .expect_last_exec_mut()
835 .accesses
836 .get_mut(&node_idx)
837 {
838 for SubresourceAccess {
839 access,
840 subresource,
841 } in accesses
842 {
843 let access_image_range = *subresource.expect_image();
844 if !image_subresource_range_intersects(access_image_range, image_range) {
845 continue;
846 }
847
848 image_access = match *access {
849 AccessType::DepthAttachmentWriteStencilReadOnly => {
850 if image_view_info
851 .aspect_mask
852 .contains(vk::ImageAspectFlags::STENCIL)
853 {
854 AccessType::DepthStencilAttachmentReadWrite
855 } else {
856 AccessType::DepthAttachmentWriteStencilReadOnly
857 }
858 }
859 AccessType::DepthStencilAttachmentRead => {
860 if !image_view_info
861 .aspect_mask
862 .contains(vk::ImageAspectFlags::DEPTH)
863 {
864 AccessType::StencilAttachmentWriteDepthReadOnly
865 } else {
866 AccessType::DepthStencilAttachmentReadWrite
867 }
868 }
869 AccessType::DepthStencilAttachmentWrite => {
870 AccessType::DepthStencilAttachmentWrite
871 }
872 AccessType::StencilAttachmentWriteDepthReadOnly => {
873 if image_view_info
874 .aspect_mask
875 .contains(vk::ImageAspectFlags::DEPTH)
876 {
877 AccessType::DepthStencilAttachmentReadWrite
878 } else {
879 AccessType::StencilAttachmentWriteDepthReadOnly
880 }
881 }
882 _ => continue,
883 };
884
885 *access = image_access;
886
887 if image_subresource_range_contains(access_image_range, image_range) {
888 return self;
889 }
890 }
891 }
892
893 self.cmd
894 .push_subresource_access(image, SubresourceRange::Image(image_range), image_access);
895
896 self
897 }
898
899 fn load_color(
900 &mut self,
901 image: impl Into<AnyImageNode>,
902 attachment_idx: AttachmentIndex,
903 image_view_info: impl Into<ImageViewInfo>,
904 ) -> &mut Self {
905 let image = image.into();
906 let image_view_info = image_view_info.into();
907 let node_idx = image.index();
908 let ImageInfo { sample_count, .. } =
909 self.cmd.graph.resources[image.index()].expect_image_info();
910
911 self.set_color_attachment(
912 attachment_idx,
913 Attachment::new(image_view_info, sample_count, node_idx),
914 LoadOp::Load,
915 );
916
917 let mut image_access = AccessType::ColorAttachmentRead;
918 let image_range = image_view_info.into();
919
920 if let Some(accesses) = self
921 .cmd
922 .cmd_mut()
923 .expect_last_exec_mut()
924 .accesses
925 .get_mut(&node_idx)
926 {
927 for SubresourceAccess {
928 access,
929 subresource,
930 } in accesses
931 {
932 let access_image_range = *subresource.expect_image();
933 if !image_subresource_range_intersects(access_image_range, image_range) {
934 continue;
935 }
936
937 image_access = match *access {
938 AccessType::ColorAttachmentRead => AccessType::ColorAttachmentRead,
939 AccessType::ColorAttachmentReadWrite | AccessType::ColorAttachmentWrite => {
940 AccessType::ColorAttachmentReadWrite
941 }
942 _ => continue,
943 };
944
945 *access = image_access;
946
947 if image_subresource_range_contains(access_image_range, image_range) {
948 return self;
949 }
950 }
951 }
952
953 self.cmd
954 .push_subresource_access(image, SubresourceRange::Image(image_range), image_access);
955
956 self
957 }
958
959 fn load_depth_stencil(
960 &mut self,
961 image: impl Into<AnyImageNode>,
962 image_view_info: impl Into<ImageViewInfo>,
963 ) -> &mut Self {
964 let image = image.into();
965 let image_view_info = image_view_info.into();
966 let node_idx = image.index();
967 let ImageInfo { sample_count, .. } =
968 self.cmd.graph.resources[image.index()].expect_image_info();
969
970 self.set_depth_stencil_attachment(
971 Attachment::new(image_view_info, sample_count, node_idx),
972 LoadOp::Load,
973 );
974
975 let mut image_access = AccessType::DepthStencilAttachmentRead;
976 let image_range = image_view_info.into();
977
978 if let Some(accesses) = self
979 .cmd
980 .cmd_mut()
981 .expect_last_exec_mut()
982 .accesses
983 .get_mut(&node_idx)
984 {
985 for SubresourceAccess {
986 access,
987 subresource,
988 } in accesses
989 {
990 let access_image_range = *subresource.expect_image();
991 if !image_subresource_range_intersects(access_image_range, image_range) {
992 continue;
993 }
994
995 image_access = match *access {
996 AccessType::DepthAttachmentWriteStencilReadOnly => {
997 AccessType::DepthAttachmentWriteStencilReadOnly
998 }
999 AccessType::DepthStencilAttachmentRead => {
1000 AccessType::DepthStencilAttachmentRead
1001 }
1002 AccessType::DepthStencilAttachmentWrite => {
1003 AccessType::DepthStencilAttachmentReadWrite
1004 }
1005 AccessType::StencilAttachmentWriteDepthReadOnly => {
1006 AccessType::DepthStencilAttachmentReadWrite
1007 }
1008 _ => continue,
1009 };
1010
1011 *access = image_access;
1012
1013 if image_subresource_range_contains(access_image_range, image_range) {
1014 return self;
1015 }
1016 }
1017 }
1018
1019 self.cmd
1020 .push_subresource_access(image, SubresourceRange::Image(image_range), image_access);
1021
1022 self
1023 }
1024
1025 fn store_color(
1026 &mut self,
1027 image: impl Into<AnyImageNode>,
1028 attachment_idx: AttachmentIndex,
1029 image_view_info: impl Into<ImageViewInfo>,
1030 ) -> &mut Self {
1031 let image = image.into();
1032 let image_view_info = image_view_info.into();
1033 let node_idx = image.index();
1034 let ImageInfo { sample_count, .. } =
1035 self.cmd.graph.resources[image.index()].expect_image_info();
1036
1037 self.set_color_store(
1038 attachment_idx,
1039 Attachment::new(image_view_info, sample_count, node_idx),
1040 );
1041
1042 let mut image_access = AccessType::ColorAttachmentWrite;
1043 let image_range = image_view_info.into();
1044
1045 if let Some(accesses) = self
1046 .cmd
1047 .cmd_mut()
1048 .expect_last_exec_mut()
1049 .accesses
1050 .get_mut(&node_idx)
1051 {
1052 for SubresourceAccess {
1053 access,
1054 subresource,
1055 } in accesses
1056 {
1057 let access_image_range = *subresource.expect_image();
1058 if !image_subresource_range_intersects(access_image_range, image_range) {
1059 continue;
1060 }
1061
1062 image_access = match *access {
1063 AccessType::ColorAttachmentRead | AccessType::ColorAttachmentReadWrite => {
1064 AccessType::ColorAttachmentReadWrite
1065 }
1066 AccessType::ColorAttachmentWrite => AccessType::ColorAttachmentWrite,
1067 _ => continue,
1068 };
1069
1070 *access = image_access;
1071
1072 if image_subresource_range_contains(access_image_range, image_range) {
1073 return self;
1074 }
1075 }
1076 }
1077
1078 self.cmd
1079 .push_subresource_access(image, SubresourceRange::Image(image_range), image_access);
1080
1081 self
1082 }
1083
1084 fn store_depth_stencil(
1085 &mut self,
1086 image: impl Into<AnyImageNode>,
1087 image_view_info: impl Into<ImageViewInfo>,
1088 ) -> &mut Self {
1089 let image = image.into();
1090 let image_view_info = image_view_info.into();
1091 let node_idx = image.index();
1092 let ImageInfo { sample_count, .. } =
1093 self.cmd.graph.resources[image.index()].expect_image_info();
1094
1095 self.set_depth_stencil_store(Attachment::new(image_view_info, sample_count, node_idx));
1096
1097 let mut image_access = if image_view_info
1098 .aspect_mask
1099 .contains(vk::ImageAspectFlags::DEPTH | vk::ImageAspectFlags::STENCIL)
1100 {
1101 AccessType::DepthStencilAttachmentWrite
1102 } else if image_view_info
1103 .aspect_mask
1104 .contains(vk::ImageAspectFlags::DEPTH)
1105 {
1106 AccessType::DepthAttachmentWriteStencilReadOnly
1107 } else {
1108 debug_assert!(
1109 image_view_info
1110 .aspect_mask
1111 .contains(vk::ImageAspectFlags::STENCIL)
1112 );
1113
1114 AccessType::StencilAttachmentWriteDepthReadOnly
1115 };
1116 let image_range = image_view_info.into();
1117
1118 if let Some(accesses) = self
1119 .cmd
1120 .cmd_mut()
1121 .expect_last_exec_mut()
1122 .accesses
1123 .get_mut(&node_idx)
1124 {
1125 for SubresourceAccess {
1126 access,
1127 subresource,
1128 } in accesses
1129 {
1130 let access_image_range = *subresource.expect_image();
1131 if !image_subresource_range_intersects(access_image_range, image_range) {
1132 continue;
1133 }
1134
1135 image_access = match *access {
1136 AccessType::DepthAttachmentWriteStencilReadOnly => {
1137 if image_view_info
1138 .aspect_mask
1139 .contains(vk::ImageAspectFlags::STENCIL)
1140 {
1141 AccessType::DepthStencilAttachmentReadWrite
1142 } else {
1143 AccessType::DepthAttachmentWriteStencilReadOnly
1144 }
1145 }
1146 AccessType::DepthStencilAttachmentRead => {
1147 if !image_view_info
1148 .aspect_mask
1149 .contains(vk::ImageAspectFlags::DEPTH)
1150 {
1151 AccessType::StencilAttachmentWriteDepthReadOnly
1152 } else {
1153 AccessType::DepthStencilAttachmentReadWrite
1154 }
1155 }
1156 AccessType::DepthStencilAttachmentWrite => {
1157 AccessType::DepthStencilAttachmentWrite
1158 }
1159 AccessType::StencilAttachmentWriteDepthReadOnly => {
1160 if image_view_info
1161 .aspect_mask
1162 .contains(vk::ImageAspectFlags::DEPTH)
1163 {
1164 AccessType::DepthStencilAttachmentReadWrite
1165 } else {
1166 AccessType::StencilAttachmentWriteDepthReadOnly
1167 }
1168 }
1169 _ => continue,
1170 };
1171
1172 *access = image_access;
1173
1174 if image_subresource_range_contains(access_image_range, image_range) {
1175 return self;
1176 }
1177 }
1178 }
1179
1180 self.cmd
1181 .push_subresource_access(image, SubresourceRange::Image(image_range), image_access);
1182
1183 self
1184 }
1185
1186 fn resolve_color(
1187 &mut self,
1188 image: impl Into<AnyImageNode>,
1189 src_attachment_idx: AttachmentIndex,
1190 dst_attachment_idx: AttachmentIndex,
1191 image_view_info: impl Into<ImageViewInfo>,
1192 ) -> &mut Self {
1193 let image = image.into();
1194 let image_view_info = image_view_info.into();
1195 let node_idx = image.index();
1196 let ImageInfo { sample_count, .. } =
1197 self.cmd.graph.resources[image.index()].expect_image_info();
1198
1199 self.set_color_resolve(
1200 src_attachment_idx,
1201 dst_attachment_idx,
1202 Attachment::new(image_view_info, sample_count, node_idx),
1203 );
1204
1205 let mut image_access = AccessType::ColorAttachmentWrite;
1206 let image_range = image_view_info.into();
1207
1208 if let Some(accesses) = self
1209 .cmd
1210 .cmd_mut()
1211 .expect_last_exec_mut()
1212 .accesses
1213 .get_mut(&node_idx)
1214 {
1215 for SubresourceAccess {
1216 access,
1217 subresource,
1218 } in accesses
1219 {
1220 let access_image_range = *subresource.expect_image();
1221 if !image_subresource_range_intersects(access_image_range, image_range) {
1222 continue;
1223 }
1224
1225 image_access = match *access {
1226 AccessType::ColorAttachmentRead | AccessType::ColorAttachmentReadWrite => {
1227 AccessType::ColorAttachmentReadWrite
1228 }
1229 AccessType::ColorAttachmentWrite => AccessType::ColorAttachmentWrite,
1230 _ => continue,
1231 };
1232
1233 *access = image_access;
1234
1235 if image_subresource_range_contains(access_image_range, image_range) {
1236 return self;
1237 }
1238 }
1239 }
1240
1241 self.cmd
1242 .push_subresource_access(image, SubresourceRange::Image(image_range), image_access);
1243
1244 self
1245 }
1246
1247 fn resolve_depth_stencil(
1248 &mut self,
1249 image: impl Into<AnyImageNode>,
1250 dst_attachment_idx: AttachmentIndex,
1251 image_view_info: impl Into<ImageViewInfo>,
1252 depth_mode: Option<ResolveMode>,
1253 stencil_mode: Option<ResolveMode>,
1254 ) -> &mut Self {
1255 let image = image.into();
1256 let image_view_info = image_view_info.into();
1257 let node_idx = image.index();
1258 let ImageInfo { sample_count, .. } =
1259 self.cmd.graph.resources[image.index()].expect_image_info();
1260
1261 self.set_depth_stencil_resolve(
1262 dst_attachment_idx,
1263 Attachment::new(image_view_info, sample_count, node_idx),
1264 depth_mode,
1265 stencil_mode,
1266 );
1267
1268 let mut image_access = if image_view_info
1269 .aspect_mask
1270 .contains(vk::ImageAspectFlags::DEPTH | vk::ImageAspectFlags::STENCIL)
1271 {
1272 AccessType::DepthStencilAttachmentWrite
1273 } else if image_view_info
1274 .aspect_mask
1275 .contains(vk::ImageAspectFlags::DEPTH)
1276 {
1277 AccessType::DepthAttachmentWriteStencilReadOnly
1278 } else {
1279 debug_assert!(
1280 image_view_info
1281 .aspect_mask
1282 .contains(vk::ImageAspectFlags::STENCIL)
1283 );
1284
1285 AccessType::StencilAttachmentWriteDepthReadOnly
1286 };
1287 let image_range = image_view_info.into();
1288
1289 if let Some(accesses) = self
1290 .cmd
1291 .cmd_mut()
1292 .expect_last_exec_mut()
1293 .accesses
1294 .get_mut(&node_idx)
1295 {
1296 for SubresourceAccess {
1297 access,
1298 subresource,
1299 } in accesses
1300 {
1301 let access_image_range = *subresource.expect_image();
1302 if !image_subresource_range_intersects(access_image_range, image_range) {
1303 continue;
1304 }
1305
1306 image_access = match *access {
1307 AccessType::DepthAttachmentWriteStencilReadOnly => {
1308 if image_view_info
1309 .aspect_mask
1310 .contains(vk::ImageAspectFlags::STENCIL)
1311 {
1312 AccessType::DepthStencilAttachmentReadWrite
1313 } else {
1314 AccessType::DepthAttachmentWriteStencilReadOnly
1315 }
1316 }
1317 AccessType::DepthStencilAttachmentRead => {
1318 if !image_view_info
1319 .aspect_mask
1320 .contains(vk::ImageAspectFlags::DEPTH)
1321 {
1322 AccessType::StencilAttachmentWriteDepthReadOnly
1323 } else {
1324 AccessType::DepthStencilAttachmentReadWrite
1325 }
1326 }
1327 AccessType::DepthStencilAttachmentWrite => {
1328 AccessType::DepthStencilAttachmentWrite
1329 }
1330 AccessType::StencilAttachmentWriteDepthReadOnly => {
1331 if image_view_info
1332 .aspect_mask
1333 .contains(vk::ImageAspectFlags::DEPTH)
1334 {
1335 AccessType::DepthStencilAttachmentReadWrite
1336 } else {
1337 AccessType::StencilAttachmentWriteDepthReadOnly
1338 }
1339 }
1340 _ => continue,
1341 };
1342
1343 *access = image_access;
1344
1345 if image_subresource_range_contains(access_image_range, image_range) {
1346 return self;
1347 }
1348 }
1349 }
1350
1351 self.cmd
1352 .push_subresource_access(image, SubresourceRange::Image(image_range), image_access);
1353
1354 self
1355 }
1356}
1357
1358#[derive(Clone, Copy, Debug)]
1360pub enum ClearColorValue {
1361 Float32([f32; 4]),
1368
1369 Int32([i32; 4]),
1377
1378 Uint32([u32; 4]),
1384}
1385
1386impl ClearColorValue {
1387 pub const BLACK_ALPHA_ONE: Self = Self::Float32([0.0, 0.0, 0.0, 1.0]);
1389
1390 pub const BLACK_ALPHA_ZERO: Self = Self::Float32([0.0, 0.0, 0.0, 0.0]);
1392
1393 pub const WHITE_ALPHA_ONE: Self = Self::Float32([1.0, 1.0, 1.0, 1.0]);
1395
1396 pub const WHITE_ALPHA_ZERO: Self = Self::Float32([1.0, 1.0, 1.0, 0.0]);
1398
1399 pub const fn rgba(r: f32, g: f32, b: f32, a: f32) -> Self {
1401 Self::Float32([r, g, b, a])
1402 }
1403
1404 pub const fn from_f32(r: f32, g: f32, b: f32, a: f32) -> Self {
1406 Self::rgba(r, g, b, a)
1407 }
1408
1409 pub const fn from_u8(r: u8, g: u8, b: u8, a: u8) -> Self {
1411 Self::from_f32(
1412 r as f32 / u8::MAX as f32,
1413 g as f32 / u8::MAX as f32,
1414 b as f32 / u8::MAX as f32,
1415 a as f32 / u8::MAX as f32,
1416 )
1417 }
1418}
1419
1420impl Default for ClearColorValue {
1421 fn default() -> Self {
1422 Self::from_f32(0.0, 0.0, 0.0, 0.0)
1423 }
1424}
1425
1426impl From<[f32; 4]> for ClearColorValue {
1427 fn from(float32: [f32; 4]) -> Self {
1428 Self::Float32(float32)
1429 }
1430}
1431
1432impl From<[i32; 4]> for ClearColorValue {
1433 fn from(int32: [i32; 4]) -> Self {
1434 Self::Int32(int32)
1435 }
1436}
1437
1438impl From<[u8; 4]> for ClearColorValue {
1439 fn from(uint8: [u8; 4]) -> Self {
1440 Self::from_u8(uint8[0], uint8[1], uint8[2], uint8[3])
1441 }
1442}
1443
1444impl From<[u32; 4]> for ClearColorValue {
1445 fn from(uint32: [u32; 4]) -> Self {
1446 Self::Uint32(uint32)
1447 }
1448}
1449
1450impl From<ClearColorValue> for vk::ClearColorValue {
1451 fn from(value: ClearColorValue) -> Self {
1452 match value {
1453 ClearColorValue::Float32(float32) => Self { float32 },
1454 ClearColorValue::Int32(int32) => Self { int32 },
1455 ClearColorValue::Uint32(uint32) => Self { uint32 },
1456 }
1457 }
1458}
1459
1460pub struct GraphicsCommandRef<'a> {
1508 cmd: CommandRef<'a>,
1509 pipeline: GraphicsPipeline,
1510}
1511
1512impl GraphicsCommandRef<'_> {
1513 #[profiling::function]
1571 pub fn bind_index_buffer(
1572 &self,
1573 buffer: impl Into<AnyBufferNode>,
1574 offset: vk::DeviceSize,
1575 index_ty: vk::IndexType,
1576 ) -> &Self {
1577 let buffer = buffer.into();
1578 let buffer = self.resource(buffer);
1579
1580 unsafe {
1581 self.cmd
1582 .device
1583 .cmd_bind_index_buffer(self.cmd.handle, buffer.handle, offset, index_ty);
1584 }
1585
1586 self
1587 }
1588
1589 #[profiling::function]
1641 pub fn bind_vertex_buffer(
1642 &self,
1643 binding: u32,
1644 buffer: impl Into<AnyBufferNode>,
1645 offset: vk::DeviceSize,
1646 ) -> &Self {
1647 let buffer = buffer.into();
1648 let buffer = self.resource(buffer);
1649
1650 unsafe {
1651 self.cmd.device.cmd_bind_vertex_buffers(
1652 self.cmd.handle,
1653 binding,
1654 slice::from_ref(&buffer.handle),
1655 slice::from_ref(&offset),
1656 );
1657 }
1658
1659 self
1660 }
1661
1662 #[profiling::function]
1671 pub fn bind_vertex_buffers<N>(
1672 &self,
1673 first_binding: u32,
1674 buffer_offsets: impl IntoIterator<Item = (N, vk::DeviceSize)>,
1675 ) -> &Self
1676 where
1677 N: Into<AnyBufferNode>,
1678 {
1679 #[derive(Default)]
1680 struct Tls {
1681 buffers: Vec<vk::Buffer>,
1682 offsets: Vec<vk::DeviceSize>,
1683 }
1684
1685 thread_local! {
1686 static TLS: RefCell<Tls> = Default::default();
1687 }
1688
1689 TLS.with_borrow_mut(|tls| {
1690 tls.buffers.clear();
1691 tls.offsets.clear();
1692
1693 for (buffer, offset) in buffer_offsets {
1694 let buffer = buffer.into();
1695 let buffer = self.resource(buffer);
1696
1697 tls.buffers.push(buffer.handle);
1698 tls.offsets.push(offset);
1699 }
1700
1701 unsafe {
1702 self.cmd.device.cmd_bind_vertex_buffers(
1703 self.cmd.handle,
1704 first_binding,
1705 tls.buffers.as_slice(),
1706 tls.offsets.as_slice(),
1707 );
1708 }
1709 });
1710
1711 self
1712 }
1713
1714 #[profiling::function]
1721 pub fn draw(
1722 &self,
1723 vertex_count: u32,
1724 instance_count: u32,
1725 first_vertex: u32,
1726 first_instance: u32,
1727 ) -> &Self {
1728 unsafe {
1729 self.cmd.device.cmd_draw(
1730 self.cmd.handle,
1731 vertex_count,
1732 instance_count,
1733 first_vertex,
1734 first_instance,
1735 );
1736 }
1737
1738 self
1739 }
1740
1741 #[profiling::function]
1748 pub fn draw_indexed(
1749 &self,
1750 index_count: u32,
1751 instance_count: u32,
1752 first_index: u32,
1753 vertex_offset: i32,
1754 first_instance: u32,
1755 ) -> &Self {
1756 unsafe {
1757 self.cmd.device.cmd_draw_indexed(
1758 self.cmd.handle,
1759 index_count,
1760 instance_count,
1761 first_index,
1762 vertex_offset,
1763 first_instance,
1764 );
1765 }
1766
1767 self
1768 }
1769
1770 #[profiling::function]
1852 pub fn draw_indexed_indirect(
1853 &self,
1854 buffer: impl Into<AnyBufferNode>,
1855 offset: vk::DeviceSize,
1856 draw_count: u32,
1857 stride: u32,
1858 ) -> &Self {
1859 let buffer = buffer.into();
1860 let buffer = self.resource(buffer);
1861
1862 unsafe {
1863 self.cmd.device.cmd_draw_indexed_indirect(
1864 self.cmd.handle,
1865 buffer.handle,
1866 offset,
1867 draw_count,
1868 stride,
1869 );
1870 }
1871
1872 self
1873 }
1874
1875 #[profiling::function]
1888 pub fn draw_indexed_indirect_count(
1889 &self,
1890 buffer: impl Into<AnyBufferNode>,
1891 offset: vk::DeviceSize,
1892 count_buf: impl Into<AnyBufferNode>,
1893 count_buf_offset: vk::DeviceSize,
1894 max_draw_count: u32,
1895 stride: u32,
1896 ) -> &Self {
1897 let buffer = buffer.into();
1898 let buffer = self.resource(buffer);
1899
1900 let count_buf = count_buf.into();
1901 let count_buf = self.resource(count_buf);
1902
1903 unsafe {
1904 self.cmd.device.cmd_draw_indexed_indirect_count(
1905 self.cmd.handle,
1906 buffer.handle,
1907 offset,
1908 count_buf.handle,
1909 count_buf_offset,
1910 max_draw_count,
1911 stride,
1912 );
1913 }
1914
1915 self
1916 }
1917
1918 #[profiling::function]
1922 pub fn draw_indirect(
1923 &self,
1924 buffer: impl Into<AnyBufferNode>,
1925 offset: vk::DeviceSize,
1926 draw_count: u32,
1927 stride: u32,
1928 ) -> &Self {
1929 let buffer = buffer.into();
1930 let buffer = self.resource(buffer);
1931
1932 unsafe {
1933 self.cmd.device.cmd_draw_indirect(
1934 self.cmd.handle,
1935 buffer.handle,
1936 offset,
1937 draw_count,
1938 stride,
1939 );
1940 }
1941
1942 self
1943 }
1944
1945 #[profiling::function]
1949 pub fn draw_indirect_count(
1950 &self,
1951 buffer: impl Into<AnyBufferNode>,
1952 offset: vk::DeviceSize,
1953 count_buf: impl Into<AnyBufferNode>,
1954 count_buf_offset: vk::DeviceSize,
1955 max_draw_count: u32,
1956 stride: u32,
1957 ) -> &Self {
1958 let buffer = buffer.into();
1959 let buffer = self.resource(buffer);
1960
1961 let count_buf = count_buf.into();
1962 let count_buf = self.resource(count_buf);
1963
1964 unsafe {
1965 self.cmd.device.cmd_draw_indirect_count(
1966 self.cmd.handle,
1967 buffer.handle,
1968 offset,
1969 count_buf.handle,
1970 count_buf_offset,
1971 max_draw_count,
1972 stride,
1973 );
1974 }
1975
1976 self
1977 }
1978
1979 #[profiling::function]
2054 pub fn push_constants(&self, offset: u32, data: &[u8]) -> &Self {
2055 self.cmd_push_constants(
2056 self.pipeline.inner.layout,
2057 &self.pipeline.inner.push_constants,
2058 offset,
2059 data,
2060 );
2061
2062 self
2063 }
2064
2065 #[profiling::function]
2071 pub fn set_scissor(&self, first_scissor: u32, scissors: &[vk::Rect2D]) -> &Self {
2072 unsafe {
2073 self.cmd
2074 .device
2075 .cmd_set_scissor(self.cmd.handle, first_scissor, scissors);
2076 }
2077
2078 self
2079 }
2080
2081 #[profiling::function]
2088 pub fn set_viewport(&self, first_viewport: u32, viewports: &[vk::Viewport]) -> &Self {
2089 unsafe {
2090 self.cmd
2091 .device
2092 .cmd_set_viewport(self.cmd.handle, first_viewport, viewports);
2093 }
2094
2095 self
2096 }
2097}
2098
2099impl<'a> Deref for GraphicsCommandRef<'a> {
2100 type Target = CommandRef<'a>;
2101
2102 fn deref(&self) -> &Self::Target {
2103 &self.cmd
2104 }
2105}
2106
2107impl LoadOp<ClearColorValue> {
2108 pub const CLEAR_BLACK_ALPHA_ONE: Self = Self::Clear(ClearColorValue::BLACK_ALPHA_ONE);
2110
2111 pub const CLEAR_BLACK_ALPHA_ZERO: Self = Self::Clear(ClearColorValue::BLACK_ALPHA_ZERO);
2113
2114 pub const CLEAR_WHITE_ALPHA_ONE: Self = Self::Clear(ClearColorValue::WHITE_ALPHA_ONE);
2116
2117 pub const CLEAR_WHITE_ALPHA_ZERO: Self = Self::Clear(ClearColorValue::WHITE_ALPHA_ZERO);
2119
2120 pub fn clear_rgba(r: f32, g: f32, b: f32, a: f32) -> Self {
2122 Self::Clear(ClearColorValue::rgba(r, g, b, a))
2123 }
2124}
2125
2126impl LoadOp<vk::ClearDepthStencilValue> {
2127 pub const CLEAR_ONE_STENCIL_ZERO: Self = Self::Clear(vk::ClearDepthStencilValue {
2130 depth: 1.0,
2131 stencil: 0,
2132 });
2133
2134 pub const CLEAR_ZERO_STENCIL_ZERO: Self = Self::Clear(vk::ClearDepthStencilValue {
2136 depth: 0.0,
2137 stencil: 0,
2138 });
2139
2140 pub fn clear_depth_stencil(depth: f32, stencil: u32) -> Self {
2142 Self::Clear(vk::ClearDepthStencilValue { depth, stencil })
2143 }
2144}