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