1use {
4 super::{DriverError, device::Device, format_aspect_mask, vk_sync::AccessType},
5 ash::vk,
6 derive_builder::{Builder, UninitializedFieldError},
7 gpu_allocator::{
8 MemoryLocation,
9 vulkan::{Allocation, AllocationCreateDesc, AllocationScheme},
10 },
11 log::{trace, warn},
12 std::{
13 collections::{HashMap, hash_map::Entry},
14 fmt::{Debug, Formatter},
15 mem::{replace, take},
16 ops::{Deref, DerefMut},
17 sync::Arc,
18 thread::panicking,
19 },
20};
21
22#[cfg(feature = "parking_lot")]
23use parking_lot::Mutex;
24
25#[cfg(not(feature = "parking_lot"))]
26use std::sync::Mutex;
27
28#[cfg(debug_assertions)]
29fn assert_aspect_mask_supported(aspect_mask: vk::ImageAspectFlags) {
30 use vk::ImageAspectFlags as A;
31
32 const COLOR: A = A::COLOR;
33 const DEPTH: A = A::DEPTH;
34 const DEPTH_STENCIL: A = A::from_raw(A::DEPTH.as_raw() | A::STENCIL.as_raw());
35 const STENCIL: A = A::STENCIL;
36
37 assert!(matches!(
38 aspect_mask,
39 COLOR | DEPTH | DEPTH_STENCIL | STENCIL
40 ));
41}
42
43pub(crate) fn image_subresource_range_contains(
44 lhs: vk::ImageSubresourceRange,
45 rhs: vk::ImageSubresourceRange,
46) -> bool {
47 lhs.aspect_mask.contains(rhs.aspect_mask)
48 && lhs.base_array_layer <= rhs.base_array_layer
49 && lhs.base_array_layer + lhs.layer_count >= rhs.base_array_layer + rhs.layer_count
50 && lhs.base_mip_level <= rhs.base_mip_level
51 && lhs.base_mip_level + lhs.level_count >= rhs.base_mip_level + rhs.level_count
52}
53
54pub(crate) fn image_subresource_range_intersects(
55 lhs: vk::ImageSubresourceRange,
56 rhs: vk::ImageSubresourceRange,
57) -> bool {
58 lhs.aspect_mask.intersects(rhs.aspect_mask)
59 && lhs.base_array_layer < rhs.base_array_layer + rhs.layer_count
60 && lhs.base_array_layer + lhs.layer_count > rhs.base_array_layer
61 && lhs.base_mip_level < rhs.base_mip_level + rhs.level_count
62 && lhs.base_mip_level + lhs.level_count > rhs.base_mip_level
63}
64
65pub struct Image {
95 accesses: Mutex<ImageAccess<AccessType>>,
96 allocation: Option<Allocation>, pub(super) device: Arc<Device>,
98 image: vk::Image,
99 #[allow(clippy::type_complexity)]
100 image_view_cache: Mutex<HashMap<ImageViewInfo, ImageView>>,
101
102 pub info: ImageInfo,
104
105 pub name: Option<String>,
107}
108
109impl Image {
110 #[profiling::function]
133 pub fn create(device: &Arc<Device>, info: impl Into<ImageInfo>) -> Result<Self, DriverError> {
134 let info: ImageInfo = info.into();
135
136 trace!("create");
138
139 assert!(
140 !info.usage.is_empty(),
141 "Unspecified image usage {:?}",
142 info.usage
143 );
144
145 let accesses = Mutex::new(ImageAccess::new(info, AccessType::Nothing));
146
147 let device = Arc::clone(device);
148 let create_info = info
149 .image_create_info()
150 .queue_family_indices(&device.physical_device.queue_family_indices);
151 let image = unsafe {
152 device.create_image(&create_info, None).map_err(|err| {
153 warn!("{err}");
154
155 DriverError::Unsupported
156 })?
157 };
158 let requirements = unsafe { device.get_image_memory_requirements(image) };
159 let allocation = {
160 profiling::scope!("allocate");
161
162 #[cfg_attr(not(feature = "parking_lot"), allow(unused_mut))]
163 let mut allocator = device.allocator.lock();
164
165 #[cfg(not(feature = "parking_lot"))]
166 let mut allocator = allocator.unwrap();
167
168 allocator
169 .allocate(&AllocationCreateDesc {
170 name: "image",
171 requirements,
172 location: MemoryLocation::GpuOnly,
173 linear: false,
174 allocation_scheme: AllocationScheme::GpuAllocatorManaged,
175 })
176 .map_err(|err| {
177 warn!("{err}");
178
179 DriverError::Unsupported
180 })
181 }?;
182
183 unsafe {
184 device
185 .bind_image_memory(image, allocation.memory(), allocation.offset())
186 .map_err(|err| {
187 warn!("{err}");
188
189 DriverError::Unsupported
190 })?;
191 }
192
193 Ok(Self {
194 accesses,
195 allocation: Some(allocation),
196 device,
197 image,
198 image_view_cache: Mutex::new(Default::default()),
199 info,
200 name: None,
201 })
202 }
203
204 #[profiling::function]
248 pub fn access(
249 this: &Self,
250 access: AccessType,
251 mut access_range: vk::ImageSubresourceRange,
252 ) -> impl Iterator<Item = (AccessType, vk::ImageSubresourceRange)> + '_ {
253 #[cfg(debug_assertions)]
254 {
255 assert_aspect_mask_supported(access_range.aspect_mask);
256
257 assert!(format_aspect_mask(this.info.fmt).contains(access_range.aspect_mask));
258 }
259
260 if access_range.layer_count == vk::REMAINING_ARRAY_LAYERS {
261 debug_assert!(access_range.base_array_layer < this.info.array_layer_count);
262
263 access_range.layer_count = this.info.array_layer_count - access_range.base_array_layer
264 }
265
266 debug_assert!(
267 access_range.base_array_layer + access_range.layer_count <= this.info.array_layer_count
268 );
269
270 if access_range.level_count == vk::REMAINING_MIP_LEVELS {
271 debug_assert!(access_range.base_mip_level < this.info.mip_level_count);
272
273 access_range.level_count = this.info.mip_level_count - access_range.base_mip_level
274 }
275
276 debug_assert!(
277 access_range.base_mip_level + access_range.level_count <= this.info.mip_level_count
278 );
279
280 let accesses = this.accesses.lock();
281
282 #[cfg(not(feature = "parking_lot"))]
283 let accesses = accesses.unwrap();
284
285 ImageAccessIter::new(accesses, access, access_range)
286 }
287
288 #[profiling::function]
289 pub(super) fn clone_swapchain(this: &Self) -> Self {
290 #[cfg_attr(not(feature = "parking_lot"), allow(unused_mut))]
292 let mut image_view_cache = this.image_view_cache.lock();
293
294 #[cfg(not(feature = "parking_lot"))]
295 let mut image_view_cache = image_view_cache.unwrap();
296
297 let image_view_cache = take(&mut *image_view_cache);
298
299 let Self { image, info, .. } = *this;
302 let accesses = ImageAccess::new(info, AccessType::General);
303 let accesses = Mutex::new(accesses);
304
305 Self {
306 accesses,
307 allocation: None,
308 device: Arc::clone(&this.device),
309 image,
310 image_view_cache: Mutex::new(image_view_cache),
311 info,
312 name: this.name.clone(),
313 }
314 }
315
316 #[profiling::function]
317 fn drop_allocation(this: &Self, allocation: Allocation) {
318 {
319 profiling::scope!("views");
320
321 #[cfg_attr(not(feature = "parking_lot"), allow(unused_mut))]
322 let mut image_view_cache = this.image_view_cache.lock();
323
324 #[cfg(not(feature = "parking_lot"))]
325 let mut image_view_cache = image_view_cache.unwrap();
326
327 image_view_cache.clear();
328 }
329
330 unsafe {
331 this.device.destroy_image(this.image, None);
332 }
333
334 {
335 profiling::scope!("deallocate");
336
337 #[cfg_attr(not(feature = "parking_lot"), allow(unused_mut))]
338 let mut allocator = this.device.allocator.lock();
339
340 #[cfg(not(feature = "parking_lot"))]
341 let mut allocator = allocator.unwrap();
342
343 allocator.free(allocation)
344 }
345 .unwrap_or_else(|_| warn!("Unable to free image allocation"));
346 }
347
348 #[profiling::function]
353 pub fn from_raw(device: &Arc<Device>, image: vk::Image, info: impl Into<ImageInfo>) -> Self {
354 let device = Arc::clone(device);
355 let info = info.into();
356
357 let accesses = ImageAccess::new(info, AccessType::General);
362
363 Self {
364 accesses: Mutex::new(accesses),
365 allocation: None,
366 device,
367 image,
368 image_view_cache: Mutex::new(Default::default()),
369 info,
370 name: None,
371 }
372 }
373
374 #[profiling::function]
375 pub(crate) fn view(this: &Self, info: ImageViewInfo) -> Result<vk::ImageView, DriverError> {
376 #[cfg_attr(not(feature = "parking_lot"), allow(unused_mut))]
377 let mut image_view_cache = this.image_view_cache.lock();
378
379 #[cfg(not(feature = "parking_lot"))]
380 let mut image_view_cache = image_view_cache.unwrap();
381
382 Ok(match image_view_cache.entry(info) {
383 Entry::Occupied(entry) => entry.get().image_view,
384 Entry::Vacant(entry) => {
385 entry
386 .insert(ImageView::create(&this.device, info, this.image)?)
387 .image_view
388 }
389 })
390 }
391}
392
393impl Debug for Image {
394 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
395 if let Some(name) = &self.name {
396 write!(f, "{} ({:?})", name, self.image)
397 } else {
398 write!(f, "{:?}", self.image)
399 }
400 }
401}
402
403impl Deref for Image {
404 type Target = vk::Image;
405
406 fn deref(&self) -> &Self::Target {
407 &self.image
408 }
409}
410
411impl Drop for Image {
412 fn drop(&mut self) {
414 if panicking() {
415 return;
416 }
417
418 if let Some(allocation) = self.allocation.take() {
421 Self::drop_allocation(self, allocation);
422 }
423 }
424}
425
426#[derive(Debug)]
427pub(crate) struct ImageAccess<A> {
428 accesses: Box<[A]>,
429
430 #[cfg(debug_assertions)]
431 array_layer_count: u32,
432
433 aspect_count: u8,
434 mip_level_count: u32,
435}
436
437impl<A> ImageAccess<A> {
438 pub fn new(info: ImageInfo, access: A) -> Self
439 where
440 A: Copy,
441 {
442 let aspect_mask = format_aspect_mask(info.fmt);
443
444 #[cfg(debug_assertions)]
445 assert_aspect_mask_supported(aspect_mask);
446
447 let aspect_count = aspect_mask.as_raw().count_ones() as u8;
448 let array_layer_count = info.array_layer_count;
449 let mip_level_count = info.mip_level_count;
450
451 Self {
452 accesses: vec![
453 access;
454 (aspect_count as u32 * array_layer_count * mip_level_count) as _
455 ]
456 .into_boxed_slice(),
457
458 #[cfg(debug_assertions)]
459 array_layer_count,
460
461 aspect_count,
462 mip_level_count,
463 }
464 }
465
466 pub fn access(
467 &mut self,
468 access: A,
469 access_range: vk::ImageSubresourceRange,
470 ) -> impl Iterator<Item = (A, vk::ImageSubresourceRange)> + '_
471 where
472 A: Copy + PartialEq,
473 {
474 ImageAccessIter::new(self, access, access_range)
475 }
476
477 fn idx(&self, aspect: u8, array_layer: u32, mip_level: u32) -> usize {
478 let idx = (array_layer * self.aspect_count as u32 * self.mip_level_count
482 + mip_level * self.aspect_count as u32
483 + aspect as u32) as _;
484
485 debug_assert!(idx < self.accesses.len());
486
487 idx
488 }
489}
490
491struct ImageAccessIter<I, A> {
492 access: A,
493 access_range: ImageAccessRange,
494 array_layer: u32,
495 aspect: u8,
496 image: I,
497 mip_level: u32,
498}
499
500impl<I, A> ImageAccessIter<I, A> {
501 fn new(image: I, access: A, access_range: vk::ImageSubresourceRange) -> Self
502 where
503 I: DerefMut<Target = ImageAccess<A>>,
504 {
505 #[cfg(debug_assertions)]
506 assert_aspect_mask_supported(access_range.aspect_mask);
507
508 #[cfg(debug_assertions)]
509 assert!(access_range.base_array_layer < image.array_layer_count);
510
511 debug_assert!(access_range.base_mip_level < image.mip_level_count);
512 debug_assert_ne!(access_range.layer_count, 0);
513 debug_assert_ne!(access_range.level_count, 0);
514
515 let aspect_count = access_range.aspect_mask.as_raw().count_ones() as _;
516
517 debug_assert!(aspect_count <= image.aspect_count);
518
519 let base_aspect = access_range.aspect_mask.as_raw().trailing_zeros() as _;
520
521 Self {
522 access,
523 array_layer: 0,
524 aspect: 0,
525 image,
526 mip_level: 0,
527 access_range: ImageAccessRange {
528 aspect_count,
529 base_array_layer: access_range.base_array_layer,
530 base_aspect,
531 base_mip_level: access_range.base_mip_level,
532 layer_count: access_range.layer_count,
533 level_count: access_range.level_count,
534 },
535 }
536 }
537}
538
539impl<I, A> Iterator for ImageAccessIter<I, A>
540where
541 I: DerefMut<Target = ImageAccess<A>>,
542 A: Copy + PartialEq,
543{
544 type Item = (A, vk::ImageSubresourceRange);
545
546 fn next(&mut self) -> Option<Self::Item> {
547 if self.aspect == self.access_range.aspect_count {
548 return None;
549 }
550
551 let mut res = vk::ImageSubresourceRange {
552 aspect_mask: vk::ImageAspectFlags::from_raw(
553 (1 << (self.access_range.base_aspect + self.aspect)) as _,
554 ),
555 base_array_layer: self.access_range.base_array_layer + self.array_layer,
556 base_mip_level: self.access_range.base_mip_level + self.mip_level,
557 layer_count: 1,
558 level_count: 1,
559 };
560
561 let base_aspect = (self.image.aspect_count << self.access_range.base_aspect == 8) as u8;
562 let prev_access = replace(
563 {
564 let idx = self.image.idx(
565 base_aspect + self.aspect,
566 res.base_array_layer,
567 res.base_mip_level,
568 );
569
570 unsafe { self.image.accesses.get_unchecked_mut(idx) }
571 },
572 self.access,
573 );
574
575 loop {
576 self.mip_level += 1;
577 self.mip_level %= self.access_range.level_count;
578 if self.mip_level == 0 {
579 break;
580 }
581
582 let idx = self.image.idx(
583 base_aspect + self.aspect,
584 self.access_range.base_array_layer + self.array_layer,
585 self.access_range.base_mip_level + self.mip_level,
586 );
587 let access = unsafe { self.image.accesses.get_unchecked_mut(idx) };
588 if *access != prev_access {
589 return Some((prev_access, res));
590 }
591
592 *access = self.access;
593 res.level_count += 1;
594 }
595
596 loop {
597 self.array_layer += 1;
598 self.array_layer %= self.access_range.layer_count;
599 if self.array_layer == 0 {
600 break;
601 }
602
603 if res.base_mip_level != self.access_range.base_mip_level {
604 return Some((prev_access, res));
605 }
606
607 let array_layer = self.access_range.base_array_layer + self.array_layer;
608 let end_mip_level = self.access_range.base_mip_level + self.access_range.level_count;
609
610 for mip_level in self.access_range.base_mip_level..end_mip_level {
611 let idx = self
612 .image
613 .idx(base_aspect + self.aspect, array_layer, mip_level);
614 let access = unsafe { *self.image.accesses.get_unchecked(idx) };
615 if access != prev_access {
616 return Some((prev_access, res));
617 }
618 }
619
620 for mip_level in self.access_range.base_mip_level..end_mip_level {
621 let idx = self
622 .image
623 .idx(base_aspect + self.aspect, array_layer, mip_level);
624 let access = unsafe { self.image.accesses.get_unchecked_mut(idx) };
625 *access = self.access;
626 }
627
628 res.layer_count += 1;
629 }
630
631 loop {
632 self.aspect += 1;
633 if self.aspect == self.access_range.aspect_count {
634 return Some((prev_access, res));
635 }
636
637 let end_array_layer =
638 self.access_range.base_array_layer + self.access_range.layer_count;
639 let end_mip_level = self.access_range.base_mip_level + self.access_range.level_count;
640
641 for array_layer in self.access_range.base_array_layer..end_array_layer {
642 for mip_level in self.access_range.base_mip_level..end_mip_level {
643 let idx = self
644 .image
645 .idx(base_aspect + self.aspect, array_layer, mip_level);
646 let access = unsafe { *self.image.accesses.get_unchecked(idx) };
647 if access != prev_access {
648 return Some((prev_access, res));
649 }
650 }
651 }
652
653 for array_layer in self.access_range.base_array_layer..end_array_layer {
654 for mip_level in self.access_range.base_mip_level..end_mip_level {
655 let idx = self
656 .image
657 .idx(base_aspect + self.aspect, array_layer, mip_level);
658 let access = unsafe { self.image.accesses.get_unchecked_mut(idx) };
659 *access = self.access;
660 }
661 }
662
663 res.aspect_mask |= vk::ImageAspectFlags::from_raw(
664 (1 << (self.access_range.base_aspect + self.aspect)) as _,
665 )
666 }
667 }
668}
669
670#[derive(Copy, Clone)]
671struct ImageAccessRange {
672 aspect_count: u8,
673 base_array_layer: u32,
674 base_aspect: u8,
675 base_mip_level: u32,
676 layer_count: u32,
677 level_count: u32,
678}
679
680#[derive(Builder, Clone, Copy, Debug, Hash, PartialEq, Eq)]
682#[builder(
683 build_fn(private, name = "fallible_build", error = "ImageInfoBuilderError"),
684 derive(Copy, Clone, Debug),
685 pattern = "owned"
686)]
687#[non_exhaustive]
688pub struct ImageInfo {
689 #[builder(default = "1", setter(strip_option))]
691 pub array_layer_count: u32,
692
693 #[builder(setter(strip_option))]
695 pub depth: u32,
696
697 #[builder(default, setter(strip_option))]
699 pub flags: vk::ImageCreateFlags,
700
701 #[builder(setter(strip_option))]
703 pub fmt: vk::Format,
704
705 #[builder(setter(strip_option))]
707 pub height: u32,
708
709 #[builder(default = "1", setter(strip_option))]
711 pub mip_level_count: u32,
712
713 #[builder(default = "SampleCount::Type1", setter(strip_option))]
717 pub sample_count: SampleCount,
718
719 #[builder(default = "vk::ImageTiling::OPTIMAL", setter(strip_option))]
723 pub tiling: vk::ImageTiling,
724
725 #[builder(setter(strip_option))]
729 pub ty: ImageType,
730
731 #[builder(default, setter(strip_option))]
733 pub usage: vk::ImageUsageFlags,
734
735 #[builder(setter(strip_option))]
737 pub width: u32,
738}
739
740impl ImageInfo {
741 #[inline(always)]
743 pub const fn cube(size: u32, fmt: vk::Format, usage: vk::ImageUsageFlags) -> ImageInfo {
744 Self::new(ImageType::Cube, size, size, 1, 1, fmt, usage)
745 }
746
747 #[inline(always)]
749 pub const fn image_1d(size: u32, fmt: vk::Format, usage: vk::ImageUsageFlags) -> ImageInfo {
750 Self::new(ImageType::Texture1D, size, 1, 1, 1, fmt, usage)
751 }
752
753 #[inline(always)]
755 pub const fn image_2d(
756 width: u32,
757 height: u32,
758 fmt: vk::Format,
759 usage: vk::ImageUsageFlags,
760 ) -> ImageInfo {
761 Self::new(ImageType::Texture2D, width, height, 1, 1, fmt, usage)
762 }
763
764 #[inline(always)]
766 pub const fn image_2d_array(
767 width: u32,
768 height: u32,
769 array_elements: u32,
770 fmt: vk::Format,
771 usage: vk::ImageUsageFlags,
772 ) -> ImageInfo {
773 Self::new(
774 ImageType::TextureArray2D,
775 width,
776 height,
777 1,
778 array_elements,
779 fmt,
780 usage,
781 )
782 }
783
784 #[inline(always)]
786 pub const fn image_3d(
787 width: u32,
788 height: u32,
789 depth: u32,
790 fmt: vk::Format,
791 usage: vk::ImageUsageFlags,
792 ) -> ImageInfo {
793 Self::new(ImageType::Texture3D, width, height, depth, 1, fmt, usage)
794 }
795
796 #[inline(always)]
797 const fn new(
798 ty: ImageType,
799 width: u32,
800 height: u32,
801 depth: u32,
802 array_layer_count: u32,
803 fmt: vk::Format,
804 usage: vk::ImageUsageFlags,
805 ) -> Self {
806 Self {
807 ty,
808 width,
809 height,
810 depth,
811 array_layer_count,
812 fmt,
813 usage,
814 flags: vk::ImageCreateFlags::empty(),
815 tiling: vk::ImageTiling::OPTIMAL,
816 mip_level_count: 1,
817 sample_count: SampleCount::Type1,
818 }
819 }
820
821 #[deprecated = "Use ImageInfo::image_1d()"]
823 #[doc(hidden)]
824 pub fn new_1d(fmt: vk::Format, size: u32, usage: vk::ImageUsageFlags) -> ImageInfoBuilder {
825 Self::image_1d(size, fmt, usage).to_builder()
826 }
827
828 #[deprecated = "Use ImageInfo::image_2d()"]
830 #[doc(hidden)]
831 pub fn new_2d(
832 fmt: vk::Format,
833 width: u32,
834 height: u32,
835 usage: vk::ImageUsageFlags,
836 ) -> ImageInfoBuilder {
837 Self::image_2d(width, height, fmt, usage).to_builder()
838 }
839
840 #[deprecated = "Use ImageInfo::image_2d_array()"]
842 #[doc(hidden)]
843 pub fn new_2d_array(
844 fmt: vk::Format,
845 width: u32,
846 height: u32,
847 array_elements: u32,
848 usage: vk::ImageUsageFlags,
849 ) -> ImageInfoBuilder {
850 Self::image_2d_array(width, height, array_elements, fmt, usage).to_builder()
851 }
852
853 #[deprecated = "Use ImageInfo::image_3d()"]
855 #[doc(hidden)]
856 pub fn new_3d(
857 fmt: vk::Format,
858 width: u32,
859 height: u32,
860 depth: u32,
861 usage: vk::ImageUsageFlags,
862 ) -> ImageInfoBuilder {
863 Self::image_3d(width, height, depth, fmt, usage).to_builder()
864 }
865
866 #[deprecated = "Use ImageInfo::cube()"]
868 #[doc(hidden)]
869 pub fn new_cube(fmt: vk::Format, size: u32, usage: vk::ImageUsageFlags) -> ImageInfoBuilder {
870 Self::cube(size, fmt, usage).to_builder()
871 }
872
873 pub fn default_view_info(self) -> ImageViewInfo {
875 self.into()
876 }
877
878 fn image_create_info<'a>(self) -> vk::ImageCreateInfo<'a> {
879 let (ty, extent, array_layer_count) = match self.ty {
880 ImageType::Texture1D => (
881 vk::ImageType::TYPE_1D,
882 vk::Extent3D {
883 width: self.width,
884 height: 1,
885 depth: 1,
886 },
887 1,
888 ),
889 ImageType::TextureArray1D => (
890 vk::ImageType::TYPE_1D,
891 vk::Extent3D {
892 width: self.width,
893 height: 1,
894 depth: 1,
895 },
896 self.array_layer_count,
897 ),
898 ImageType::Texture2D => (
899 vk::ImageType::TYPE_2D,
900 vk::Extent3D {
901 width: self.width,
902 height: self.height,
903 depth: 1,
904 },
905 if self.flags.contains(vk::ImageCreateFlags::CUBE_COMPATIBLE) {
906 self.array_layer_count
907 } else {
908 1
909 },
910 ),
911 ImageType::TextureArray2D => (
912 vk::ImageType::TYPE_2D,
913 vk::Extent3D {
914 width: self.width,
915 height: self.height,
916 depth: 1,
917 },
918 self.array_layer_count,
919 ),
920 ImageType::Texture3D => (
921 vk::ImageType::TYPE_3D,
922 vk::Extent3D {
923 width: self.width,
924 height: self.height,
925 depth: self.depth,
926 },
927 1,
928 ),
929 ImageType::Cube => (
930 vk::ImageType::TYPE_2D,
931 vk::Extent3D {
932 width: self.width,
933 height: self.height,
934 depth: 1,
935 },
936 6,
937 ),
938 ImageType::CubeArray => (
939 vk::ImageType::TYPE_2D,
940 vk::Extent3D {
941 width: self.width,
942 height: self.height,
943 depth: 1,
944 },
945 6 * self.array_layer_count,
946 ),
947 };
948
949 vk::ImageCreateInfo::default()
950 .flags(self.flags)
951 .image_type(ty)
952 .format(self.fmt)
953 .extent(extent)
954 .mip_levels(self.mip_level_count)
955 .array_layers(array_layer_count)
956 .samples(self.sample_count.into())
957 .tiling(self.tiling)
958 .usage(self.usage)
959 .sharing_mode(vk::SharingMode::CONCURRENT)
960 .initial_layout(vk::ImageLayout::UNDEFINED)
961 }
962
963 #[inline(always)]
965 pub fn to_builder(self) -> ImageInfoBuilder {
966 ImageInfoBuilder {
967 array_layer_count: Some(self.array_layer_count),
968 depth: Some(self.depth),
969 flags: Some(self.flags),
970 fmt: Some(self.fmt),
971 height: Some(self.height),
972 mip_level_count: Some(self.mip_level_count),
973 sample_count: Some(self.sample_count),
974 tiling: Some(self.tiling),
975 ty: Some(self.ty),
976 usage: Some(self.usage),
977 width: Some(self.width),
978 }
979 }
980}
981
982impl From<ImageInfoBuilder> for ImageInfo {
983 fn from(info: ImageInfoBuilder) -> Self {
984 info.build()
985 }
986}
987
988impl ImageInfoBuilder {
989 #[inline(always)]
1001 pub fn build(self) -> ImageInfo {
1002 match self.fallible_build() {
1003 Err(ImageInfoBuilderError(err)) => panic!("{err}"),
1004 Ok(info) => info,
1005 }
1006 }
1007}
1008
1009#[derive(Debug)]
1010struct ImageInfoBuilderError(UninitializedFieldError);
1011
1012impl From<UninitializedFieldError> for ImageInfoBuilderError {
1013 fn from(err: UninitializedFieldError) -> Self {
1014 Self(err)
1015 }
1016}
1017
1018impl From<ImageViewInfo> for vk::ImageSubresourceRange {
1019 fn from(info: ImageViewInfo) -> Self {
1020 Self {
1021 aspect_mask: info.aspect_mask,
1022 base_mip_level: info.base_mip_level,
1023 base_array_layer: info.base_array_layer,
1024 layer_count: info.array_layer_count,
1025 level_count: info.mip_level_count,
1026 }
1027 }
1028}
1029
1030#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
1033pub enum ImageType {
1034 Texture1D = 0,
1036 TextureArray1D = 1,
1038 Texture2D = 2,
1040 TextureArray2D = 3,
1042 Texture3D = 4,
1044 Cube = 5,
1046 CubeArray = 6,
1048}
1049
1050impl ImageType {
1051 pub(crate) fn into_vk(self) -> vk::ImageViewType {
1052 match self {
1053 Self::Cube => vk::ImageViewType::CUBE,
1054 Self::CubeArray => vk::ImageViewType::CUBE_ARRAY,
1055 Self::Texture1D => vk::ImageViewType::TYPE_1D,
1056 Self::Texture2D => vk::ImageViewType::TYPE_2D,
1057 Self::Texture3D => vk::ImageViewType::TYPE_3D,
1058 Self::TextureArray1D => vk::ImageViewType::TYPE_1D_ARRAY,
1059 Self::TextureArray2D => vk::ImageViewType::TYPE_2D_ARRAY,
1060 }
1061 }
1062}
1063
1064impl From<ImageType> for vk::ImageType {
1065 fn from(value: ImageType) -> Self {
1066 match value {
1067 ImageType::Texture1D | ImageType::TextureArray1D => vk::ImageType::TYPE_1D,
1068 ImageType::Texture2D
1069 | ImageType::TextureArray2D
1070 | ImageType::Cube
1071 | ImageType::CubeArray => vk::ImageType::TYPE_2D,
1072 ImageType::Texture3D => vk::ImageType::TYPE_3D,
1073 }
1074 }
1075}
1076
1077struct ImageView {
1078 device: Arc<Device>,
1079 image_view: vk::ImageView,
1080}
1081
1082impl ImageView {
1083 #[profiling::function]
1084 fn create(
1085 device: &Arc<Device>,
1086 info: impl Into<ImageViewInfo>,
1087 image: vk::Image,
1088 ) -> Result<Self, DriverError> {
1089 let info = info.into();
1090 let device = Arc::clone(device);
1091 let create_info = vk::ImageViewCreateInfo::default()
1092 .view_type(info.ty.into_vk())
1093 .format(info.fmt)
1094 .components(vk::ComponentMapping {
1095 r: vk::ComponentSwizzle::R,
1096 g: vk::ComponentSwizzle::G,
1097 b: vk::ComponentSwizzle::B,
1098 a: vk::ComponentSwizzle::A,
1099 })
1100 .image(image)
1101 .subresource_range(vk::ImageSubresourceRange {
1102 aspect_mask: info.aspect_mask,
1103 base_array_layer: info.base_array_layer,
1104 base_mip_level: info.base_mip_level,
1105 level_count: info.mip_level_count,
1106 layer_count: info.array_layer_count,
1107 });
1108
1109 let image_view =
1110 unsafe { device.create_image_view(&create_info, None) }.map_err(|err| {
1111 warn!("{err}");
1112
1113 DriverError::Unsupported
1114 })?;
1115
1116 Ok(Self { device, image_view })
1117 }
1118}
1119
1120impl Drop for ImageView {
1121 #[profiling::function]
1122 fn drop(&mut self) {
1123 if panicking() {
1124 return;
1125 }
1126
1127 unsafe {
1128 self.device.destroy_image_view(self.image_view, None);
1129 }
1130 }
1131}
1132
1133#[derive(Builder, Clone, Copy, Debug, Eq, Hash, PartialEq)]
1135#[builder(
1136 build_fn(private, name = "fallible_build", error = "ImageViewInfoBuilderError"),
1137 derive(Clone, Copy, Debug),
1138 pattern = "owned"
1139)]
1140#[non_exhaustive]
1141pub struct ImageViewInfo {
1142 #[builder(default = "vk::REMAINING_ARRAY_LAYERS")]
1146 pub array_layer_count: u32,
1147
1148 pub aspect_mask: vk::ImageAspectFlags,
1150
1151 #[builder(default)]
1153 pub base_array_layer: u32,
1154
1155 #[builder(default)]
1157 pub base_mip_level: u32,
1158
1159 pub fmt: vk::Format,
1161
1162 #[builder(default = "vk::REMAINING_MIP_LEVELS")]
1166 pub mip_level_count: u32,
1167
1168 pub ty: ImageType,
1170}
1171
1172impl ImageViewInfo {
1173 #[inline(always)]
1179 pub const fn new(fmt: vk::Format, ty: ImageType) -> ImageViewInfo {
1180 Self {
1181 array_layer_count: vk::REMAINING_ARRAY_LAYERS,
1182 aspect_mask: format_aspect_mask(fmt),
1183 base_array_layer: 0,
1184 base_mip_level: 0,
1185 fmt,
1186 mip_level_count: vk::REMAINING_MIP_LEVELS,
1187 ty,
1188 }
1189 }
1190
1191 #[inline(always)]
1193 pub fn to_builder(self) -> ImageViewInfoBuilder {
1194 ImageViewInfoBuilder {
1195 array_layer_count: Some(self.array_layer_count),
1196 aspect_mask: Some(self.aspect_mask),
1197 base_array_layer: Some(self.base_array_layer),
1198 base_mip_level: Some(self.base_mip_level),
1199 fmt: Some(self.fmt),
1200 mip_level_count: Some(self.mip_level_count),
1201 ty: Some(self.ty),
1202 }
1203 }
1204
1205 pub fn with_ty(mut self, ty: ImageType) -> Self {
1207 self.ty = ty;
1208 self
1209 }
1210}
1211
1212impl From<ImageInfo> for ImageViewInfo {
1213 fn from(info: ImageInfo) -> Self {
1214 Self {
1215 array_layer_count: info.array_layer_count,
1216 aspect_mask: format_aspect_mask(info.fmt),
1217 base_array_layer: 0,
1218 base_mip_level: 0,
1219 fmt: info.fmt,
1220 mip_level_count: info.mip_level_count,
1221 ty: info.ty,
1222 }
1223 }
1224}
1225
1226impl From<ImageViewInfoBuilder> for ImageViewInfo {
1227 fn from(info: ImageViewInfoBuilder) -> Self {
1228 info.build()
1229 }
1230}
1231
1232impl ImageViewInfoBuilder {
1233 #[deprecated = "Use ImageViewInfo::new()"]
1235 #[doc(hidden)]
1236 pub fn new(fmt: vk::Format, ty: ImageType) -> Self {
1237 Self::default().fmt(fmt).ty(ty)
1238 }
1239
1240 #[inline(always)]
1250 pub fn build(self) -> ImageViewInfo {
1251 match self.fallible_build() {
1252 Err(ImageViewInfoBuilderError(err)) => panic!("{err}"),
1253 Ok(info) => info,
1254 }
1255 }
1256}
1257
1258#[derive(Debug)]
1259struct ImageViewInfoBuilderError(UninitializedFieldError);
1260
1261impl From<UninitializedFieldError> for ImageViewInfoBuilderError {
1262 fn from(err: UninitializedFieldError) -> Self {
1263 Self(err)
1264 }
1265}
1266
1267#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1271pub enum SampleCount {
1272 Type1,
1274
1275 Type2,
1277
1278 Type4,
1280
1281 Type8,
1283
1284 Type16,
1286
1287 Type32,
1289
1290 Type64,
1292}
1293
1294impl SampleCount {
1295 pub fn is_single(self) -> bool {
1297 matches!(self, Self::Type1)
1298 }
1299
1300 pub fn is_multiple(self) -> bool {
1302 matches!(
1303 self,
1304 Self::Type2 | Self::Type4 | Self::Type8 | Self::Type16 | Self::Type32 | Self::Type64
1305 )
1306 }
1307}
1308
1309impl From<SampleCount> for vk::SampleCountFlags {
1310 fn from(sample_count: SampleCount) -> Self {
1311 match sample_count {
1312 SampleCount::Type1 => Self::TYPE_1,
1313 SampleCount::Type2 => Self::TYPE_2,
1314 SampleCount::Type4 => Self::TYPE_4,
1315 SampleCount::Type8 => Self::TYPE_8,
1316 SampleCount::Type16 => Self::TYPE_16,
1317 SampleCount::Type32 => Self::TYPE_32,
1318 SampleCount::Type64 => Self::TYPE_64,
1319 }
1320 }
1321}
1322
1323impl Default for SampleCount {
1324 fn default() -> Self {
1325 Self::Type1
1326 }
1327}
1328
1329#[cfg(test)]
1330mod tests {
1331 use {super::*, std::ops::Range};
1332
1333 fn assert_access_ranges_eq(
1335 lhs: (AccessType, vk::ImageSubresourceRange),
1336 rhs: (AccessType, vk::ImageSubresourceRange),
1337 ) {
1338 assert_eq!(
1339 (
1340 lhs.0,
1341 lhs.1.aspect_mask,
1342 lhs.1.base_array_layer,
1343 lhs.1.layer_count,
1344 lhs.1.base_mip_level,
1345 lhs.1.level_count
1346 ),
1347 (
1348 rhs.0,
1349 rhs.1.aspect_mask,
1350 rhs.1.base_array_layer,
1351 rhs.1.layer_count,
1352 rhs.1.base_mip_level,
1353 rhs.1.level_count
1354 )
1355 );
1356 }
1357
1358 #[test]
1359 pub fn image_access_basic() {
1360 use vk::ImageAspectFlags as A;
1361
1362 let mut image = ImageAccess::new(
1363 image_subresource(vk::Format::R8G8B8A8_UNORM, 1, 1),
1364 AccessType::Nothing,
1365 );
1366
1367 {
1368 let mut accesses = ImageAccessIter::new(
1369 &mut image,
1370 AccessType::AnyShaderWrite,
1371 image_subresource_range(A::COLOR, 0..1, 0..1),
1372 );
1373
1374 assert_access_ranges_eq(
1375 accesses.next().unwrap(),
1376 (
1377 AccessType::Nothing,
1378 image_subresource_range(A::COLOR, 0..1, 0..1),
1379 ),
1380 );
1381 assert!(accesses.next().is_none());
1382 }
1383
1384 {
1385 let mut accesses = ImageAccessIter::new(
1386 &mut image,
1387 AccessType::AnyShaderReadOther,
1388 image_subresource_range(A::COLOR, 0..1, 0..1),
1389 );
1390
1391 assert_access_ranges_eq(
1392 accesses.next().unwrap(),
1393 (
1394 AccessType::AnyShaderWrite,
1395 image_subresource_range(A::COLOR, 0..1, 0..1),
1396 ),
1397 );
1398 assert!(accesses.next().is_none());
1399 }
1400 }
1401
1402 #[test]
1403 pub fn image_access_color() {
1404 use vk::ImageAspectFlags as A;
1405
1406 let mut image = ImageAccess::new(
1407 image_subresource(vk::Format::R8G8B8A8_UNORM, 3, 3),
1408 AccessType::Nothing,
1409 );
1410
1411 {
1412 let mut accesses = ImageAccessIter::new(
1413 &mut image,
1414 AccessType::AnyShaderWrite,
1415 image_subresource_range(A::COLOR, 0..3, 0..3),
1416 );
1417
1418 assert_access_ranges_eq(
1419 accesses.next().unwrap(),
1420 (
1421 AccessType::Nothing,
1422 image_subresource_range(A::COLOR, 0..3, 0..3),
1423 ),
1424 );
1425 assert!(accesses.next().is_none());
1426 }
1427
1428 {
1429 let mut accesses = ImageAccessIter::new(
1430 &mut image,
1431 AccessType::AnyShaderReadOther,
1432 image_subresource_range(A::COLOR, 0..1, 0..1),
1433 );
1434
1435 assert_access_ranges_eq(
1436 accesses.next().unwrap(),
1437 (
1438 AccessType::AnyShaderWrite,
1439 image_subresource_range(A::COLOR, 0..1, 0..1),
1440 ),
1441 );
1442 assert!(accesses.next().is_none());
1443 }
1444
1445 {
1446 let mut accesses = ImageAccessIter::new(
1447 &mut image,
1448 AccessType::ComputeShaderWrite,
1449 image_subresource_range(A::COLOR, 0..3, 0..3),
1450 );
1451
1452 assert_access_ranges_eq(
1453 accesses.next().unwrap(),
1454 (
1455 AccessType::AnyShaderReadOther,
1456 image_subresource_range(A::COLOR, 0..1, 0..1),
1457 ),
1458 );
1459 assert_access_ranges_eq(
1460 accesses.next().unwrap(),
1461 (
1462 AccessType::AnyShaderWrite,
1463 image_subresource_range(A::COLOR, 0..1, 1..3),
1464 ),
1465 );
1466 assert_access_ranges_eq(
1467 accesses.next().unwrap(),
1468 (
1469 AccessType::AnyShaderWrite,
1470 image_subresource_range(A::COLOR, 1..3, 0..3),
1471 ),
1472 );
1473 assert!(accesses.next().is_none());
1474 }
1475
1476 {
1477 let mut accesses = ImageAccessIter::new(
1478 &mut image,
1479 AccessType::HostRead,
1480 image_subresource_range(A::COLOR, 0..3, 0..3),
1481 );
1482
1483 assert_access_ranges_eq(
1484 accesses.next().unwrap(),
1485 (
1486 AccessType::ComputeShaderWrite,
1487 image_subresource_range(A::COLOR, 0..3, 0..3),
1488 ),
1489 );
1490 assert!(accesses.next().is_none());
1491 }
1492
1493 {
1494 let mut accesses = ImageAccessIter::new(
1495 &mut image,
1496 AccessType::HostWrite,
1497 image_subresource_range(A::COLOR, 1..2, 1..2),
1498 );
1499
1500 assert_access_ranges_eq(
1501 accesses.next().unwrap(),
1502 (
1503 AccessType::HostRead,
1504 image_subresource_range(A::COLOR, 1..2, 1..2),
1505 ),
1506 );
1507 assert!(accesses.next().is_none());
1508 }
1509
1510 {
1511 let mut accesses = ImageAccessIter::new(
1512 &mut image,
1513 AccessType::GeometryShaderReadOther,
1514 image_subresource_range(A::COLOR, 0..3, 0..3),
1515 );
1516
1517 assert_access_ranges_eq(
1518 accesses.next().unwrap(),
1519 (
1520 AccessType::HostRead,
1521 image_subresource_range(A::COLOR, 0..1, 0..3),
1522 ),
1523 );
1524 assert_access_ranges_eq(
1525 accesses.next().unwrap(),
1526 (
1527 AccessType::HostRead,
1528 image_subresource_range(A::COLOR, 1..2, 0..1),
1529 ),
1530 );
1531 assert_access_ranges_eq(
1532 accesses.next().unwrap(),
1533 (
1534 AccessType::HostWrite,
1535 image_subresource_range(A::COLOR, 1..2, 1..2),
1536 ),
1537 );
1538 assert_access_ranges_eq(
1539 accesses.next().unwrap(),
1540 (
1541 AccessType::HostRead,
1542 image_subresource_range(A::COLOR, 1..2, 2..3),
1543 ),
1544 );
1545 assert_access_ranges_eq(
1546 accesses.next().unwrap(),
1547 (
1548 AccessType::HostRead,
1549 image_subresource_range(A::COLOR, 2..3, 0..3),
1550 ),
1551 );
1552 assert!(accesses.next().is_none());
1553 }
1554
1555 {
1556 let mut accesses = ImageAccessIter::new(
1557 &mut image,
1558 AccessType::VertexBuffer,
1559 image_subresource_range(A::COLOR, 0..3, 1..2),
1560 );
1561
1562 assert_access_ranges_eq(
1563 accesses.next().unwrap(),
1564 (
1565 AccessType::GeometryShaderReadOther,
1566 image_subresource_range(A::COLOR, 0..3, 1..2),
1567 ),
1568 );
1569 assert!(accesses.next().is_none());
1570 }
1571
1572 {
1573 let mut accesses = ImageAccessIter::new(
1574 &mut image,
1575 AccessType::ColorAttachmentRead,
1576 image_subresource_range(A::COLOR, 0..3, 0..3),
1577 );
1578
1579 assert_access_ranges_eq(
1580 accesses.next().unwrap(),
1581 (
1582 AccessType::GeometryShaderReadOther,
1583 image_subresource_range(A::COLOR, 0..1, 0..1),
1584 ),
1585 );
1586 assert_access_ranges_eq(
1587 accesses.next().unwrap(),
1588 (
1589 AccessType::VertexBuffer,
1590 image_subresource_range(A::COLOR, 0..1, 1..2),
1591 ),
1592 );
1593 assert_access_ranges_eq(
1594 accesses.next().unwrap(),
1595 (
1596 AccessType::GeometryShaderReadOther,
1597 image_subresource_range(A::COLOR, 0..1, 2..3),
1598 ),
1599 );
1600 assert_access_ranges_eq(
1601 accesses.next().unwrap(),
1602 (
1603 AccessType::GeometryShaderReadOther,
1604 image_subresource_range(A::COLOR, 1..2, 0..1),
1605 ),
1606 );
1607 assert_access_ranges_eq(
1608 accesses.next().unwrap(),
1609 (
1610 AccessType::VertexBuffer,
1611 image_subresource_range(A::COLOR, 1..2, 1..2),
1612 ),
1613 );
1614 assert_access_ranges_eq(
1615 accesses.next().unwrap(),
1616 (
1617 AccessType::GeometryShaderReadOther,
1618 image_subresource_range(A::COLOR, 1..2, 2..3),
1619 ),
1620 );
1621 assert_access_ranges_eq(
1622 accesses.next().unwrap(),
1623 (
1624 AccessType::GeometryShaderReadOther,
1625 image_subresource_range(A::COLOR, 2..3, 0..1),
1626 ),
1627 );
1628 assert_access_ranges_eq(
1629 accesses.next().unwrap(),
1630 (
1631 AccessType::VertexBuffer,
1632 image_subresource_range(A::COLOR, 2..3, 1..2),
1633 ),
1634 );
1635 assert_access_ranges_eq(
1636 accesses.next().unwrap(),
1637 (
1638 AccessType::GeometryShaderReadOther,
1639 image_subresource_range(A::COLOR, 2..3, 2..3),
1640 ),
1641 );
1642 assert!(accesses.next().is_none());
1643 }
1644 }
1645
1646 #[test]
1647 pub fn image_access_layers() {
1648 use vk::ImageAspectFlags as A;
1649
1650 let mut image = ImageAccess::new(
1651 image_subresource(vk::Format::R8G8B8A8_UNORM, 3, 1),
1652 AccessType::Nothing,
1653 );
1654
1655 {
1656 let mut accesses = ImageAccessIter::new(
1657 &mut image,
1658 AccessType::AnyShaderWrite,
1659 image_subresource_range(A::COLOR, 0..3, 0..1),
1660 );
1661
1662 assert_access_ranges_eq(
1663 accesses.next().unwrap(),
1664 (
1665 AccessType::Nothing,
1666 image_subresource_range(A::COLOR, 0..3, 0..1),
1667 ),
1668 );
1669 assert!(accesses.next().is_none());
1670 }
1671
1672 {
1673 let mut accesses = ImageAccessIter::new(
1674 &mut image,
1675 AccessType::AnyShaderReadOther,
1676 image_subresource_range(A::COLOR, 2..3, 0..1),
1677 );
1678
1679 assert_access_ranges_eq(
1680 accesses.next().unwrap(),
1681 (
1682 AccessType::AnyShaderWrite,
1683 image_subresource_range(A::COLOR, 2..3, 0..1),
1684 ),
1685 );
1686 assert!(accesses.next().is_none());
1687 }
1688
1689 {
1690 let mut accesses = ImageAccessIter::new(
1691 &mut image,
1692 AccessType::HostRead,
1693 image_subresource_range(A::COLOR, 0..2, 0..1),
1694 );
1695
1696 assert_access_ranges_eq(
1697 accesses.next().unwrap(),
1698 (
1699 AccessType::AnyShaderWrite,
1700 image_subresource_range(A::COLOR, 0..2, 0..1),
1701 ),
1702 );
1703 assert!(accesses.next().is_none());
1704 }
1705
1706 {
1707 let mut accesses = ImageAccessIter::new(
1708 &mut image,
1709 AccessType::AnyShaderReadOther,
1710 image_subresource_range(A::COLOR, 0..1, 0..1),
1711 );
1712
1713 assert_access_ranges_eq(
1714 accesses.next().unwrap(),
1715 (
1716 AccessType::HostRead,
1717 image_subresource_range(A::COLOR, 0..1, 0..1),
1718 ),
1719 );
1720 assert!(accesses.next().is_none());
1721 }
1722
1723 {
1724 let mut accesses = ImageAccessIter::new(
1725 &mut image,
1726 AccessType::AnyShaderReadOther,
1727 image_subresource_range(A::COLOR, 1..2, 0..1),
1728 );
1729
1730 assert_access_ranges_eq(
1731 accesses.next().unwrap(),
1732 (
1733 AccessType::HostRead,
1734 image_subresource_range(A::COLOR, 1..2, 0..1),
1735 ),
1736 );
1737 assert!(accesses.next().is_none());
1738 }
1739
1740 {
1741 let mut accesses = ImageAccessIter::new(
1742 &mut image,
1743 AccessType::HostWrite,
1744 image_subresource_range(A::COLOR, 0..3, 0..1),
1745 );
1746
1747 assert_access_ranges_eq(
1748 accesses.next().unwrap(),
1749 (
1750 AccessType::AnyShaderReadOther,
1751 image_subresource_range(A::COLOR, 0..3, 0..1),
1752 ),
1753 );
1754 assert!(accesses.next().is_none());
1755 }
1756 }
1757
1758 #[test]
1759 pub fn image_access_levels() {
1760 use vk::ImageAspectFlags as A;
1761
1762 let mut image = ImageAccess::new(
1763 image_subresource(vk::Format::R8G8B8A8_UNORM, 1, 3),
1764 AccessType::Nothing,
1765 );
1766
1767 {
1768 let mut accesses = ImageAccessIter::new(
1769 &mut image,
1770 AccessType::AnyShaderWrite,
1771 image_subresource_range(A::COLOR, 0..1, 0..3),
1772 );
1773
1774 assert_access_ranges_eq(
1775 accesses.next().unwrap(),
1776 (
1777 AccessType::Nothing,
1778 image_subresource_range(A::COLOR, 0..1, 0..3),
1779 ),
1780 );
1781 assert!(accesses.next().is_none());
1782 }
1783
1784 {
1785 let mut accesses = ImageAccessIter::new(
1786 &mut image,
1787 AccessType::AnyShaderReadOther,
1788 image_subresource_range(A::COLOR, 0..1, 2..3),
1789 );
1790
1791 assert_access_ranges_eq(
1792 accesses.next().unwrap(),
1793 (
1794 AccessType::AnyShaderWrite,
1795 image_subresource_range(A::COLOR, 0..1, 2..3),
1796 ),
1797 );
1798 assert!(accesses.next().is_none());
1799 }
1800
1801 {
1802 let mut accesses = ImageAccessIter::new(
1803 &mut image,
1804 AccessType::HostRead,
1805 image_subresource_range(A::COLOR, 0..1, 0..2),
1806 );
1807
1808 assert_access_ranges_eq(
1809 accesses.next().unwrap(),
1810 (
1811 AccessType::AnyShaderWrite,
1812 image_subresource_range(A::COLOR, 0..1, 0..2),
1813 ),
1814 );
1815 assert!(accesses.next().is_none());
1816 }
1817
1818 {
1819 let mut accesses = ImageAccessIter::new(
1820 &mut image,
1821 AccessType::AnyShaderReadOther,
1822 image_subresource_range(A::COLOR, 0..1, 0..1),
1823 );
1824
1825 assert_access_ranges_eq(
1826 accesses.next().unwrap(),
1827 (
1828 AccessType::HostRead,
1829 image_subresource_range(A::COLOR, 0..1, 0..1),
1830 ),
1831 );
1832 assert!(accesses.next().is_none());
1833 }
1834
1835 {
1836 let mut accesses = ImageAccessIter::new(
1837 &mut image,
1838 AccessType::AnyShaderReadOther,
1839 image_subresource_range(A::COLOR, 0..1, 1..2),
1840 );
1841
1842 assert_access_ranges_eq(
1843 accesses.next().unwrap(),
1844 (
1845 AccessType::HostRead,
1846 image_subresource_range(A::COLOR, 0..1, 1..2),
1847 ),
1848 );
1849 assert!(accesses.next().is_none());
1850 }
1851
1852 {
1853 let mut accesses = ImageAccessIter::new(
1854 &mut image,
1855 AccessType::HostWrite,
1856 image_subresource_range(A::COLOR, 0..1, 0..3),
1857 );
1858
1859 assert_access_ranges_eq(
1860 accesses.next().unwrap(),
1861 (
1862 AccessType::AnyShaderReadOther,
1863 image_subresource_range(A::COLOR, 0..1, 0..3),
1864 ),
1865 );
1866 assert!(accesses.next().is_none());
1867 }
1868 }
1869
1870 #[test]
1871 pub fn image_access_depth_stencil() {
1872 use vk::ImageAspectFlags as A;
1873
1874 let mut image = ImageAccess::new(
1875 image_subresource(vk::Format::D24_UNORM_S8_UINT, 4, 3),
1876 AccessType::Nothing,
1877 );
1878
1879 {
1880 let mut accesses = ImageAccessIter::new(
1881 &mut image,
1882 AccessType::AnyShaderWrite,
1883 image_subresource_range(A::DEPTH, 0..4, 0..1),
1884 );
1885
1886 assert_access_ranges_eq(
1887 accesses.next().unwrap(),
1888 (
1889 AccessType::Nothing,
1890 image_subresource_range(A::DEPTH, 0..4, 0..1),
1891 ),
1892 );
1893 assert!(accesses.next().is_none());
1894 }
1895
1896 {
1897 let mut accesses = ImageAccessIter::new(
1898 &mut image,
1899 AccessType::AnyShaderWrite,
1900 image_subresource_range(A::STENCIL, 0..4, 1..2),
1901 );
1902
1903 assert_access_ranges_eq(
1904 accesses.next().unwrap(),
1905 (
1906 AccessType::Nothing,
1907 image_subresource_range(A::STENCIL, 0..4, 1..2),
1908 ),
1909 );
1910 assert!(accesses.next().is_none());
1911 }
1912
1913 {
1914 let mut accesses = ImageAccessIter::new(
1915 &mut image,
1916 AccessType::AnyShaderReadOther,
1917 image_subresource_range(A::DEPTH | A::STENCIL, 0..4, 0..2),
1918 );
1919
1920 assert_access_ranges_eq(
1921 accesses.next().unwrap(),
1922 (
1923 AccessType::AnyShaderWrite,
1924 image_subresource_range(A::DEPTH, 0..1, 0..1),
1925 ),
1926 );
1927 assert_access_ranges_eq(
1928 accesses.next().unwrap(),
1929 (
1930 AccessType::Nothing,
1931 image_subresource_range(A::DEPTH, 0..1, 1..2),
1932 ),
1933 );
1934 assert_access_ranges_eq(
1935 accesses.next().unwrap(),
1936 (
1937 AccessType::AnyShaderWrite,
1938 image_subresource_range(A::DEPTH, 1..2, 0..1),
1939 ),
1940 );
1941 assert_access_ranges_eq(
1942 accesses.next().unwrap(),
1943 (
1944 AccessType::Nothing,
1945 image_subresource_range(A::DEPTH, 1..2, 1..2),
1946 ),
1947 );
1948 assert_access_ranges_eq(
1949 accesses.next().unwrap(),
1950 (
1951 AccessType::AnyShaderWrite,
1952 image_subresource_range(A::DEPTH, 2..3, 0..1),
1953 ),
1954 );
1955 assert_access_ranges_eq(
1956 accesses.next().unwrap(),
1957 (
1958 AccessType::Nothing,
1959 image_subresource_range(A::DEPTH, 2..3, 1..2),
1960 ),
1961 );
1962 assert_access_ranges_eq(
1963 accesses.next().unwrap(),
1964 (
1965 AccessType::AnyShaderWrite,
1966 image_subresource_range(A::DEPTH, 3..4, 0..1),
1967 ),
1968 );
1969 assert_access_ranges_eq(
1970 accesses.next().unwrap(),
1971 (
1972 AccessType::Nothing,
1973 image_subresource_range(A::DEPTH, 3..4, 1..2),
1974 ),
1975 );
1976 assert_access_ranges_eq(
1977 accesses.next().unwrap(),
1978 (
1979 AccessType::Nothing,
1980 image_subresource_range(A::STENCIL, 0..1, 0..1),
1981 ),
1982 );
1983 assert_access_ranges_eq(
1984 accesses.next().unwrap(),
1985 (
1986 AccessType::AnyShaderWrite,
1987 image_subresource_range(A::STENCIL, 0..1, 1..2),
1988 ),
1989 );
1990 assert_access_ranges_eq(
1991 accesses.next().unwrap(),
1992 (
1993 AccessType::Nothing,
1994 image_subresource_range(A::STENCIL, 1..2, 0..1),
1995 ),
1996 );
1997 assert_access_ranges_eq(
1998 accesses.next().unwrap(),
1999 (
2000 AccessType::AnyShaderWrite,
2001 image_subresource_range(A::STENCIL, 1..2, 1..2),
2002 ),
2003 );
2004 assert_access_ranges_eq(
2005 accesses.next().unwrap(),
2006 (
2007 AccessType::Nothing,
2008 image_subresource_range(A::STENCIL, 2..3, 0..1),
2009 ),
2010 );
2011 assert_access_ranges_eq(
2012 accesses.next().unwrap(),
2013 (
2014 AccessType::AnyShaderWrite,
2015 image_subresource_range(A::STENCIL, 2..3, 1..2),
2016 ),
2017 );
2018 assert_access_ranges_eq(
2019 accesses.next().unwrap(),
2020 (
2021 AccessType::Nothing,
2022 image_subresource_range(A::STENCIL, 3..4, 0..1),
2023 ),
2024 );
2025 assert_access_ranges_eq(
2026 accesses.next().unwrap(),
2027 (
2028 AccessType::AnyShaderWrite,
2029 image_subresource_range(A::STENCIL, 3..4, 1..2),
2030 ),
2031 );
2032 assert!(accesses.next().is_none());
2033 }
2034
2035 {
2036 let mut accesses = ImageAccessIter::new(
2037 &mut image,
2038 AccessType::AccelerationStructureBuildWrite,
2039 image_subresource_range(A::DEPTH | A::STENCIL, 0..4, 0..2),
2040 );
2041
2042 assert_access_ranges_eq(
2043 accesses.next().unwrap(),
2044 (
2045 AccessType::AnyShaderReadOther,
2046 image_subresource_range(A::DEPTH | A::STENCIL, 0..4, 0..2),
2047 ),
2048 );
2049 assert!(accesses.next().is_none());
2050 }
2051
2052 {
2053 let mut accesses = ImageAccessIter::new(
2054 &mut image,
2055 AccessType::AccelerationStructureBuildRead,
2056 image_subresource_range(A::DEPTH, 1..3, 0..2),
2057 );
2058
2059 assert_access_ranges_eq(
2060 accesses.next().unwrap(),
2061 (
2062 AccessType::AccelerationStructureBuildWrite,
2063 image_subresource_range(A::DEPTH, 1..3, 0..2),
2064 ),
2065 );
2066 assert!(accesses.next().is_none());
2067 }
2068 }
2069
2070 #[test]
2071 pub fn image_access_stencil() {
2072 use vk::ImageAspectFlags as A;
2073
2074 let mut image = ImageAccess::new(
2075 image_subresource(vk::Format::S8_UINT, 2, 2),
2076 AccessType::Nothing,
2077 );
2078
2079 {
2080 let mut accesses = ImageAccessIter::new(
2081 &mut image,
2082 AccessType::AnyShaderWrite,
2083 image_subresource_range(A::STENCIL, 0..2, 0..1),
2084 );
2085
2086 assert_access_ranges_eq(
2087 accesses.next().unwrap(),
2088 (
2089 AccessType::Nothing,
2090 image_subresource_range(A::STENCIL, 0..2, 0..1),
2091 ),
2092 );
2093 assert!(accesses.next().is_none());
2094 }
2095
2096 {
2097 let mut accesses = ImageAccessIter::new(
2098 &mut image,
2099 AccessType::AnyShaderReadOther,
2100 image_subresource_range(A::STENCIL, 0..2, 1..2),
2101 );
2102
2103 assert_access_ranges_eq(
2104 accesses.next().unwrap(),
2105 (
2106 AccessType::Nothing,
2107 image_subresource_range(A::STENCIL, 0..2, 1..2),
2108 ),
2109 );
2110 assert!(accesses.next().is_none());
2111 }
2112
2113 {
2114 let mut accesses = ImageAccessIter::new(
2115 &mut image,
2116 AccessType::HostRead,
2117 image_subresource_range(A::STENCIL, 0..2, 0..2),
2118 );
2119
2120 assert_access_ranges_eq(
2121 accesses.next().unwrap(),
2122 (
2123 AccessType::AnyShaderWrite,
2124 image_subresource_range(A::STENCIL, 0..1, 0..1),
2125 ),
2126 );
2127 assert_access_ranges_eq(
2128 accesses.next().unwrap(),
2129 (
2130 AccessType::AnyShaderReadOther,
2131 image_subresource_range(A::STENCIL, 0..1, 1..2),
2132 ),
2133 );
2134 assert_access_ranges_eq(
2135 accesses.next().unwrap(),
2136 (
2137 AccessType::AnyShaderWrite,
2138 image_subresource_range(A::STENCIL, 1..2, 0..1),
2139 ),
2140 );
2141 assert_access_ranges_eq(
2142 accesses.next().unwrap(),
2143 (
2144 AccessType::AnyShaderReadOther,
2145 image_subresource_range(A::STENCIL, 1..2, 1..2),
2146 ),
2147 );
2148 assert!(accesses.next().is_none());
2149 }
2150 }
2151
2152 #[test]
2153 pub fn image_info_cube() {
2154 let info = ImageInfo::cube(42, vk::Format::R32_SFLOAT, vk::ImageUsageFlags::empty());
2155 let builder = info.to_builder().build();
2156
2157 assert_eq!(info, builder);
2158 }
2159
2160 #[test]
2161 pub fn image_info_cube_builder() {
2162 let info = ImageInfo::cube(42, vk::Format::R32_SFLOAT, vk::ImageUsageFlags::empty());
2163 let builder = ImageInfoBuilder::default()
2164 .ty(ImageType::Cube)
2165 .fmt(vk::Format::R32_SFLOAT)
2166 .width(42)
2167 .height(42)
2168 .depth(1)
2169 .build();
2170
2171 assert_eq!(info, builder);
2172 }
2173
2174 #[test]
2175 pub fn image_info_image_1d() {
2176 let info = ImageInfo::image_1d(42, vk::Format::R32_SFLOAT, vk::ImageUsageFlags::empty());
2177 let builder = info.to_builder().build();
2178
2179 assert_eq!(info, builder);
2180 }
2181
2182 #[test]
2183 pub fn image_info_image_1d_builder() {
2184 let info = ImageInfo::image_1d(42, vk::Format::R32_SFLOAT, vk::ImageUsageFlags::empty());
2185 let builder = ImageInfoBuilder::default()
2186 .ty(ImageType::Texture1D)
2187 .fmt(vk::Format::R32_SFLOAT)
2188 .width(42)
2189 .height(1)
2190 .depth(1)
2191 .build();
2192
2193 assert_eq!(info, builder);
2194 }
2195
2196 #[test]
2197 pub fn image_info_image_2d() {
2198 let info =
2199 ImageInfo::image_2d(42, 84, vk::Format::R32_SFLOAT, vk::ImageUsageFlags::empty());
2200 let builder = info.to_builder().build();
2201
2202 assert_eq!(info, builder);
2203 }
2204
2205 #[test]
2206 pub fn image_info_image_2d_builder() {
2207 let info =
2208 ImageInfo::image_2d(42, 84, vk::Format::R32_SFLOAT, vk::ImageUsageFlags::empty());
2209 let builder = ImageInfoBuilder::default()
2210 .ty(ImageType::Texture2D)
2211 .fmt(vk::Format::R32_SFLOAT)
2212 .width(42)
2213 .height(84)
2214 .depth(1)
2215 .build();
2216
2217 assert_eq!(info, builder);
2218 }
2219
2220 #[test]
2221 pub fn image_info_image_2d_array() {
2222 let info = ImageInfo::image_2d_array(
2223 42,
2224 84,
2225 100,
2226 vk::Format::default(),
2227 vk::ImageUsageFlags::empty(),
2228 );
2229 let builder = info.to_builder().build();
2230
2231 assert_eq!(info, builder);
2232 }
2233
2234 #[test]
2235 pub fn image_info_image_2d_array_builder() {
2236 let info = ImageInfo::image_2d_array(
2237 42,
2238 84,
2239 100,
2240 vk::Format::R32_SFLOAT,
2241 vk::ImageUsageFlags::empty(),
2242 );
2243 let builder = ImageInfoBuilder::default()
2244 .ty(ImageType::TextureArray2D)
2245 .fmt(vk::Format::R32_SFLOAT)
2246 .width(42)
2247 .height(84)
2248 .depth(1)
2249 .array_layer_count(100)
2250 .build();
2251
2252 assert_eq!(info, builder);
2253 }
2254
2255 #[test]
2256 pub fn image_info_image_3d() {
2257 let info = ImageInfo::image_3d(
2258 42,
2259 84,
2260 100,
2261 vk::Format::R32_SFLOAT,
2262 vk::ImageUsageFlags::empty(),
2263 );
2264 let builder = info.to_builder().build();
2265
2266 assert_eq!(info, builder);
2267 }
2268
2269 #[test]
2270 pub fn image_info_image_3d_builder() {
2271 let info = ImageInfo::image_3d(
2272 42,
2273 84,
2274 100,
2275 vk::Format::R32_SFLOAT,
2276 vk::ImageUsageFlags::empty(),
2277 );
2278 let builder = ImageInfoBuilder::default()
2279 .ty(ImageType::Texture3D)
2280 .fmt(vk::Format::R32_SFLOAT)
2281 .width(42)
2282 .height(84)
2283 .depth(100)
2284 .build();
2285
2286 assert_eq!(info, builder);
2287 }
2288
2289 #[test]
2290 #[should_panic(expected = "Field not initialized: depth")]
2291 pub fn image_info_builder_uninit_depth() {
2292 ImageInfoBuilder::default().build();
2293 }
2294
2295 #[test]
2296 #[should_panic(expected = "Field not initialized: fmt")]
2297 pub fn image_info_builder_uninit_fmt() {
2298 ImageInfoBuilder::default().depth(1).build();
2299 }
2300
2301 #[test]
2302 #[should_panic(expected = "Field not initialized: height")]
2303 pub fn image_info_builder_uninit_height() {
2304 ImageInfoBuilder::default()
2305 .depth(1)
2306 .fmt(vk::Format::default())
2307 .build();
2308 }
2309
2310 #[test]
2311 #[should_panic(expected = "Field not initialized: ty")]
2312 pub fn image_info_builder_uninit_ty() {
2313 ImageInfoBuilder::default()
2314 .depth(1)
2315 .fmt(vk::Format::default())
2316 .height(2)
2317 .build();
2318 }
2319
2320 #[test]
2321 #[should_panic(expected = "Field not initialized: width")]
2322 pub fn image_info_builder_uninit_width() {
2323 ImageInfoBuilder::default()
2324 .depth(1)
2325 .fmt(vk::Format::default())
2326 .height(2)
2327 .ty(ImageType::Texture2D)
2328 .build();
2329 }
2330
2331 fn image_subresource(
2332 fmt: vk::Format,
2333 array_layer_count: u32,
2334 mip_level_count: u32,
2335 ) -> ImageInfo {
2336 ImageInfo::image_2d(1, 1, fmt, vk::ImageUsageFlags::empty())
2337 .to_builder()
2338 .array_layer_count(array_layer_count)
2339 .mip_level_count(mip_level_count)
2340 .build()
2341 }
2342
2343 fn image_subresource_range(
2344 aspect_mask: vk::ImageAspectFlags,
2345 array_layers: Range<u32>,
2346 mip_levels: Range<u32>,
2347 ) -> vk::ImageSubresourceRange {
2348 vk::ImageSubresourceRange {
2349 aspect_mask,
2350 base_array_layer: array_layers.start,
2351 base_mip_level: mip_levels.start,
2352 layer_count: array_layers.len() as _,
2353 level_count: mip_levels.len() as _,
2354 }
2355 }
2356
2357 #[test]
2358 pub fn image_subresource_range_contains() {
2359 use {
2360 super::image_subresource_range_contains as f, image_subresource_range as i,
2361 vk::ImageAspectFlags as A,
2362 };
2363
2364 assert!(f(i(A::COLOR, 0..1, 0..1), i(A::COLOR, 0..1, 0..1)));
2365 assert!(f(i(A::COLOR, 0..2, 0..1), i(A::COLOR, 0..1, 0..1)));
2366 assert!(f(i(A::COLOR, 0..1, 0..2), i(A::COLOR, 0..1, 0..1)));
2367 assert!(f(i(A::COLOR, 0..2, 0..2), i(A::COLOR, 0..1, 0..1)));
2368 assert!(!f(i(A::COLOR, 0..1, 1..3), i(A::COLOR, 0..1, 0..1)));
2369 assert!(!f(i(A::COLOR, 1..3, 0..1), i(A::COLOR, 0..1, 0..1)));
2370 assert!(!f(i(A::COLOR, 0..1, 1..3), i(A::COLOR, 0..1, 0..2)));
2371 assert!(!f(i(A::COLOR, 1..3, 0..1), i(A::COLOR, 0..2, 0..1)));
2372 }
2373
2374 #[test]
2375 pub fn image_subresource_range_intersects() {
2376 use {
2377 super::image_subresource_range_intersects as f, image_subresource_range as i,
2378 vk::ImageAspectFlags as A,
2379 };
2380
2381 assert!(f(i(A::COLOR, 0..1, 0..1), i(A::COLOR, 0..1, 0..1)));
2382 assert!(!f(i(A::COLOR, 0..1, 0..1), i(A::DEPTH, 0..1, 0..1)));
2383
2384 assert!(!f(i(A::COLOR, 0..1, 0..1), i(A::COLOR, 1..2, 0..1)));
2385 assert!(!f(i(A::COLOR, 0..1, 0..1), i(A::COLOR, 0..1, 1..2)));
2386 assert!(!f(i(A::COLOR, 0..1, 0..1), i(A::DEPTH, 1..2, 0..1)));
2387 assert!(!f(i(A::COLOR, 0..1, 0..1), i(A::DEPTH, 0..1, 1..2)));
2388 assert!(!f(i(A::COLOR, 1..2, 1..2), i(A::COLOR, 0..1, 0..1)));
2389
2390 assert!(f(
2391 i(A::DEPTH | A::STENCIL, 2..3, 3..5),
2392 i(A::DEPTH, 2..3, 2..4)
2393 ));
2394 assert!(f(
2395 i(A::DEPTH | A::STENCIL, 2..3, 3..5),
2396 i(A::DEPTH, 2..3, 4..6)
2397 ));
2398 assert!(!f(
2399 i(A::DEPTH | A::STENCIL, 2..3, 3..5),
2400 i(A::DEPTH, 2..3, 2..3)
2401 ));
2402 assert!(!f(
2403 i(A::DEPTH | A::STENCIL, 2..3, 3..5),
2404 i(A::DEPTH, 2..3, 5..6)
2405 ));
2406 }
2407
2408 #[test]
2409 pub fn image_view_info() {
2410 let info = ImageViewInfo::new(vk::Format::default(), ImageType::Texture1D);
2411 let builder = info.to_builder().build();
2412
2413 assert_eq!(info, builder);
2414 }
2415
2416 #[test]
2417 pub fn image_view_info_builder() {
2418 let info = ImageViewInfo::new(vk::Format::default(), ImageType::Texture1D);
2419 let builder = ImageViewInfoBuilder::default()
2420 .fmt(vk::Format::default())
2421 .ty(ImageType::Texture1D)
2422 .aspect_mask(vk::ImageAspectFlags::COLOR)
2423 .build();
2424
2425 assert_eq!(info, builder);
2426 }
2427
2428 #[test]
2429 #[should_panic(expected = "Field not initialized: aspect_mask")]
2430 pub fn image_view_info_builder_uninit_aspect_mask() {
2431 ImageViewInfoBuilder::default().build();
2432 }
2433
2434 #[test]
2435 #[should_panic(expected = "Field not initialized: fmt")]
2436 pub fn image_view_info_builder_unint_fmt() {
2437 ImageViewInfoBuilder::default()
2438 .aspect_mask(vk::ImageAspectFlags::empty())
2439 .build();
2440 }
2441
2442 #[test]
2443 #[should_panic(expected = "Field not initialized: ty")]
2444 pub fn image_view_info_builder_unint_ty() {
2445 ImageViewInfoBuilder::default()
2446 .aspect_mask(vk::ImageAspectFlags::empty())
2447 .fmt(vk::Format::default())
2448 .build();
2449 }
2450}