screen_13/driver/
image.rs

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