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