• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 //! Image storage (1D, 2D, 3D, arrays, etc.) and image views.
11 //!
12 //! An *image* is a region of memory whose purpose is to store multi-dimensional data. Its
13 //! most common use is to store a 2D array of color pixels (in other words an *image* in
14 //! everyday language), but it can also be used to store arbitrary data.
15 //!
16 //! The advantage of using an image compared to a buffer is that the memory layout is optimized
17 //! for locality. When reading a specific pixel of an image, reading the nearby pixels is really
18 //! fast. Most implementations have hardware dedicated to reading from images if you access them
19 //! through a sampler.
20 //!
21 //! # Properties of an image
22 //!
23 //! # Images and image views
24 //!
25 //! There is a distinction between *images* and *image views*. As its name suggests, an image
26 //! view describes how the GPU must interpret the image.
27 //!
28 //! Transfer and memory operations operate on images themselves, while reading/writing an image
29 //! operates on image views. You can create multiple image views from the same image.
30 //!
31 //! # High-level wrappers
32 //!
33 //! In the vulkano library, an image is any object that implements the [`ImageAccess`] trait. You
34 //! can create a view by wrapping them in an [`ImageView`](crate::image::view::ImageView).
35 //!
36 //! Since the `ImageAccess` trait is low-level, you are encouraged to not implement it yourself but
37 //! instead use one of the provided implementations that are specialized depending on the way you
38 //! are going to use the image:
39 //!
40 //! - An `AttachmentImage` can be used when you want to draw to an image.
41 //! - An `ImmutableImage` stores data which never need be changed after the initial upload,
42 //!   like a texture.
43 //!
44 //! # Low-level information
45 //!
46 //! To be written.
47 //!
48 
49 pub use self::aspect::ImageAspect;
50 pub use self::aspect::ImageAspects;
51 pub use self::attachment::AttachmentImage;
52 pub use self::immutable::ImmutableImage;
53 pub use self::layout::ImageDescriptorLayouts;
54 pub use self::layout::ImageLayout;
55 pub use self::storage::StorageImage;
56 pub use self::swapchain::SwapchainImage;
57 pub use self::sys::ImageCreationError;
58 pub use self::traits::ImageAccess;
59 pub use self::traits::ImageInner;
60 pub use self::usage::ImageUsage;
61 pub use self::view::ImageViewAbstract;
62 use std::cmp;
63 use std::convert::TryFrom;
64 
65 mod aspect;
66 pub mod attachment; // TODO: make private
67 pub mod immutable; // TODO: make private
68 mod layout;
69 mod storage;
70 pub mod swapchain; // TODO: make private
71 pub mod sys;
72 pub mod traits;
73 mod usage;
74 pub mod view;
75 
76 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
77 #[repr(u32)]
78 pub enum SampleCount {
79     Sample1 = ash::vk::SampleCountFlags::TYPE_1.as_raw(),
80     Sample2 = ash::vk::SampleCountFlags::TYPE_2.as_raw(),
81     Sample4 = ash::vk::SampleCountFlags::TYPE_4.as_raw(),
82     Sample8 = ash::vk::SampleCountFlags::TYPE_8.as_raw(),
83     Sample16 = ash::vk::SampleCountFlags::TYPE_16.as_raw(),
84     Sample32 = ash::vk::SampleCountFlags::TYPE_32.as_raw(),
85     Sample64 = ash::vk::SampleCountFlags::TYPE_64.as_raw(),
86 }
87 
88 impl From<SampleCount> for ash::vk::SampleCountFlags {
89     #[inline]
from(val: SampleCount) -> Self90     fn from(val: SampleCount) -> Self {
91         Self::from_raw(val as u32)
92     }
93 }
94 
95 impl TryFrom<ash::vk::SampleCountFlags> for SampleCount {
96     type Error = ();
97 
98     #[inline]
try_from(val: ash::vk::SampleCountFlags) -> Result<Self, Self::Error>99     fn try_from(val: ash::vk::SampleCountFlags) -> Result<Self, Self::Error> {
100         match val {
101             ash::vk::SampleCountFlags::TYPE_1 => Ok(Self::Sample1),
102             ash::vk::SampleCountFlags::TYPE_2 => Ok(Self::Sample2),
103             ash::vk::SampleCountFlags::TYPE_4 => Ok(Self::Sample4),
104             ash::vk::SampleCountFlags::TYPE_8 => Ok(Self::Sample8),
105             ash::vk::SampleCountFlags::TYPE_16 => Ok(Self::Sample16),
106             ash::vk::SampleCountFlags::TYPE_32 => Ok(Self::Sample32),
107             ash::vk::SampleCountFlags::TYPE_64 => Ok(Self::Sample64),
108             _ => Err(()),
109         }
110     }
111 }
112 
113 impl TryFrom<u32> for SampleCount {
114     type Error = ();
115 
116     #[inline]
try_from(val: u32) -> Result<Self, Self::Error>117     fn try_from(val: u32) -> Result<Self, Self::Error> {
118         match val {
119             1 => Ok(Self::Sample1),
120             2 => Ok(Self::Sample2),
121             4 => Ok(Self::Sample4),
122             8 => Ok(Self::Sample8),
123             16 => Ok(Self::Sample16),
124             32 => Ok(Self::Sample32),
125             64 => Ok(Self::Sample64),
126             _ => Err(()),
127         }
128     }
129 }
130 
131 /// Specifies how many sample counts supported for an image used for storage operations.
132 #[derive(Debug, Copy, Clone, Default)]
133 pub struct SampleCounts {
134     // specify an image with one sample per pixel
135     pub sample1: bool,
136     // specify an image with 2 samples per pixel
137     pub sample2: bool,
138     // specify an image with 4 samples per pixel
139     pub sample4: bool,
140     // specify an image with 8 samples per pixel
141     pub sample8: bool,
142     // specify an image with 16 samples per pixel
143     pub sample16: bool,
144     // specify an image with 32 samples per pixel
145     pub sample32: bool,
146     // specify an image with 64 samples per pixel
147     pub sample64: bool,
148 }
149 
150 impl From<ash::vk::SampleCountFlags> for SampleCounts {
from(sample_counts: ash::vk::SampleCountFlags) -> SampleCounts151     fn from(sample_counts: ash::vk::SampleCountFlags) -> SampleCounts {
152         SampleCounts {
153             sample1: !(sample_counts & ash::vk::SampleCountFlags::TYPE_1).is_empty(),
154             sample2: !(sample_counts & ash::vk::SampleCountFlags::TYPE_2).is_empty(),
155             sample4: !(sample_counts & ash::vk::SampleCountFlags::TYPE_4).is_empty(),
156             sample8: !(sample_counts & ash::vk::SampleCountFlags::TYPE_8).is_empty(),
157             sample16: !(sample_counts & ash::vk::SampleCountFlags::TYPE_16).is_empty(),
158             sample32: !(sample_counts & ash::vk::SampleCountFlags::TYPE_32).is_empty(),
159             sample64: !(sample_counts & ash::vk::SampleCountFlags::TYPE_64).is_empty(),
160         }
161     }
162 }
163 
164 impl From<SampleCounts> for ash::vk::SampleCountFlags {
from(val: SampleCounts) -> ash::vk::SampleCountFlags165     fn from(val: SampleCounts) -> ash::vk::SampleCountFlags {
166         let mut sample_counts = ash::vk::SampleCountFlags::default();
167 
168         if val.sample1 {
169             sample_counts |= ash::vk::SampleCountFlags::TYPE_1;
170         }
171         if val.sample2 {
172             sample_counts |= ash::vk::SampleCountFlags::TYPE_2;
173         }
174         if val.sample4 {
175             sample_counts |= ash::vk::SampleCountFlags::TYPE_4;
176         }
177         if val.sample8 {
178             sample_counts |= ash::vk::SampleCountFlags::TYPE_8;
179         }
180         if val.sample16 {
181             sample_counts |= ash::vk::SampleCountFlags::TYPE_16;
182         }
183         if val.sample32 {
184             sample_counts |= ash::vk::SampleCountFlags::TYPE_32;
185         }
186         if val.sample64 {
187             sample_counts |= ash::vk::SampleCountFlags::TYPE_64;
188         }
189 
190         sample_counts
191     }
192 }
193 
194 /// Specifies how many mipmaps must be allocated.
195 ///
196 /// Note that at least one mipmap must be allocated, to store the main level of the image.
197 #[derive(Debug, Copy, Clone)]
198 pub enum MipmapsCount {
199     /// Allocates the number of mipmaps required to store all the mipmaps of the image where each
200     /// mipmap is half the dimensions of the previous level. Guaranteed to be always supported.
201     ///
202     /// Note that this is not necessarily the maximum number of mipmaps, as the Vulkan
203     /// implementation may report that it supports a greater value.
204     Log2,
205 
206     /// Allocate one mipmap (ie. just the main level). Always supported.
207     One,
208 
209     /// Allocate the given number of mipmaps. May result in an error if the value is out of range
210     /// of what the implementation supports.
211     Specific(u32),
212 }
213 
214 impl From<u32> for MipmapsCount {
215     #[inline]
from(num: u32) -> MipmapsCount216     fn from(num: u32) -> MipmapsCount {
217         MipmapsCount::Specific(num)
218     }
219 }
220 
221 /// Helper type for creating extents
222 #[derive(Debug, Copy, Clone)]
223 pub enum Extent {
224     E1D([u32; 1]),
225     E2D([u32; 2]),
226     E3D([u32; 3]),
227 }
228 
229 impl From<ash::vk::Extent2D> for Extent {
from(extent: ash::vk::Extent2D) -> Self230     fn from(extent: ash::vk::Extent2D) -> Self {
231         Extent::E2D([extent.width, extent.height])
232     }
233 }
234 
235 impl From<ash::vk::Extent3D> for Extent {
from(extent: ash::vk::Extent3D) -> Self236     fn from(extent: ash::vk::Extent3D) -> Self {
237         Extent::E3D([extent.width, extent.height, extent.depth])
238     }
239 }
240 impl TryFrom<Extent> for ash::vk::Extent2D {
241     type Error = ();
242 
try_from(extent: Extent) -> Result<Self, Self::Error>243     fn try_from(extent: Extent) -> Result<Self, Self::Error> {
244         match extent {
245             Extent::E2D(a) => Ok(ash::vk::Extent2D {
246                 width: a[0],
247                 height: a[1],
248             }),
249             _ => Err(()),
250         }
251     }
252 }
253 
254 impl TryFrom<Extent> for ash::vk::Extent3D {
255     type Error = ();
256 
try_from(extent: Extent) -> Result<Self, Self::Error>257     fn try_from(extent: Extent) -> Result<Self, Self::Error> {
258         match extent {
259             Extent::E3D(a) => Ok(ash::vk::Extent3D {
260                 width: a[0],
261                 height: a[1],
262                 depth: a[2],
263             }),
264             _ => Err(()),
265         }
266     }
267 }
268 
269 /// Helper type returned from Device's `fn image_format_properties()`
270 pub struct ImageFormatProperties {
271     pub max_extent: Extent,
272     pub max_mip_levels: MipmapsCount,
273     pub max_array_layers: u32,
274     pub sample_counts: SampleCounts,
275     pub max_resource_size: usize,
276 }
277 
278 impl From<ash::vk::ImageFormatProperties> for ImageFormatProperties {
from(props: ash::vk::ImageFormatProperties) -> Self279     fn from(props: ash::vk::ImageFormatProperties) -> Self {
280         Self {
281             max_extent: props.max_extent.into(),
282             max_mip_levels: props.max_mip_levels.into(),
283             max_array_layers: props.max_array_layers,
284             sample_counts: props.sample_counts.into(),
285             max_resource_size: props.max_resource_size as usize,
286         }
287     }
288 }
289 
290 #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
291 pub struct ImageCreateFlags {
292     pub sparse_binding: bool,
293     pub sparse_residency: bool,
294     pub sparse_aliased: bool,
295     pub mutable_format: bool,
296     pub cube_compatible: bool,
297     pub array_2d_compatible: bool,
298 }
299 
300 impl ImageCreateFlags {
all() -> Self301     pub fn all() -> Self {
302         Self {
303             sparse_binding: true,
304             sparse_residency: true,
305             sparse_aliased: true,
306             mutable_format: true,
307             cube_compatible: true,
308             array_2d_compatible: true,
309         }
310     }
311 
none() -> Self312     pub fn none() -> Self {
313         Self::default()
314     }
315 }
316 
317 impl From<ImageCreateFlags> for ash::vk::ImageCreateFlags {
from(flags: ImageCreateFlags) -> Self318     fn from(flags: ImageCreateFlags) -> Self {
319         let mut vk_flags = Self::default();
320         if flags.sparse_binding {
321             vk_flags |= ash::vk::ImageCreateFlags::SPARSE_BINDING
322         };
323         if flags.sparse_residency {
324             vk_flags |= ash::vk::ImageCreateFlags::SPARSE_RESIDENCY
325         };
326         if flags.sparse_aliased {
327             vk_flags |= ash::vk::ImageCreateFlags::SPARSE_ALIASED
328         };
329         if flags.mutable_format {
330             vk_flags |= ash::vk::ImageCreateFlags::MUTABLE_FORMAT
331         };
332         if flags.cube_compatible {
333             vk_flags |= ash::vk::ImageCreateFlags::CUBE_COMPATIBLE
334         };
335         if flags.array_2d_compatible {
336             vk_flags |= ash::vk::ImageCreateFlags::TYPE_2D_ARRAY_COMPATIBLE_KHR
337         };
338         vk_flags
339     }
340 }
341 
342 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
343 #[repr(i32)]
344 pub enum ImageType {
345     Dim1d = ash::vk::ImageType::TYPE_1D.as_raw(),
346     Dim2d = ash::vk::ImageType::TYPE_2D.as_raw(),
347     Dim3d = ash::vk::ImageType::TYPE_3D.as_raw(),
348 }
349 impl From<ImageType> for ash::vk::ImageType {
from(val: ImageType) -> Self350     fn from(val: ImageType) -> Self {
351         ash::vk::ImageType::from_raw(val as i32)
352     }
353 }
354 
355 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
356 #[repr(i32)]
357 pub enum ImageTiling {
358     Optimal = ash::vk::ImageTiling::OPTIMAL.as_raw(),
359     Linear = ash::vk::ImageTiling::LINEAR.as_raw(),
360 }
361 
362 impl From<ImageTiling> for ash::vk::ImageTiling {
from(val: ImageTiling) -> Self363     fn from(val: ImageTiling) -> Self {
364         ash::vk::ImageTiling::from_raw(val as i32)
365     }
366 }
367 
368 /// The dimensions of an image.
369 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
370 pub enum ImageDimensions {
371     Dim1d {
372         width: u32,
373         array_layers: u32,
374     },
375     Dim2d {
376         width: u32,
377         height: u32,
378         array_layers: u32,
379     },
380     Dim3d {
381         width: u32,
382         height: u32,
383         depth: u32,
384     },
385 }
386 
387 impl ImageDimensions {
388     #[inline]
width(&self) -> u32389     pub fn width(&self) -> u32 {
390         match *self {
391             ImageDimensions::Dim1d { width, .. } => width,
392             ImageDimensions::Dim2d { width, .. } => width,
393             ImageDimensions::Dim3d { width, .. } => width,
394         }
395     }
396 
397     #[inline]
height(&self) -> u32398     pub fn height(&self) -> u32 {
399         match *self {
400             ImageDimensions::Dim1d { .. } => 1,
401             ImageDimensions::Dim2d { height, .. } => height,
402             ImageDimensions::Dim3d { height, .. } => height,
403         }
404     }
405 
406     #[inline]
width_height(&self) -> [u32; 2]407     pub fn width_height(&self) -> [u32; 2] {
408         [self.width(), self.height()]
409     }
410 
411     #[inline]
depth(&self) -> u32412     pub fn depth(&self) -> u32 {
413         match *self {
414             ImageDimensions::Dim1d { .. } => 1,
415             ImageDimensions::Dim2d { .. } => 1,
416             ImageDimensions::Dim3d { depth, .. } => depth,
417         }
418     }
419 
420     #[inline]
width_height_depth(&self) -> [u32; 3]421     pub fn width_height_depth(&self) -> [u32; 3] {
422         [self.width(), self.height(), self.depth()]
423     }
424 
425     #[inline]
array_layers(&self) -> u32426     pub fn array_layers(&self) -> u32 {
427         match *self {
428             ImageDimensions::Dim1d { array_layers, .. } => array_layers,
429             ImageDimensions::Dim2d { array_layers, .. } => array_layers,
430             ImageDimensions::Dim3d { .. } => 1,
431         }
432     }
433 
434     /// Returns the total number of texels for an image of these dimensions.
435     #[inline]
num_texels(&self) -> u32436     pub fn num_texels(&self) -> u32 {
437         self.width() * self.height() * self.depth() * self.array_layers()
438     }
439 
440     /// Returns the maximum number of mipmaps for these image dimensions.
441     ///
442     /// The returned value is always at least superior or equal to 1.
443     ///
444     /// # Example
445     ///
446     /// ```
447     /// use vulkano::image::ImageDimensions;
448     ///
449     /// let dims = ImageDimensions::Dim2d {
450     ///     width: 32,
451     ///     height: 50,
452     ///     array_layers: 1,
453     /// };
454     ///
455     /// assert_eq!(dims.max_mipmaps(), 6);
456     /// ```
457     ///
max_mipmaps(&self) -> u32458     pub fn max_mipmaps(&self) -> u32 {
459         32 - (self.width() | self.height() | self.depth()).leading_zeros()
460     }
461 
462     /// Returns the dimensions of the `level`th mipmap level. If `level` is 0, then the dimensions
463     /// are left unchanged.
464     ///
465     /// Returns `None` if `level` is superior or equal to `max_mipmaps()`.
466     ///
467     /// # Example
468     ///
469     /// ```
470     /// use vulkano::image::ImageDimensions;
471     ///
472     /// let dims = ImageDimensions::Dim2d {
473     ///     width: 963,
474     ///     height: 256,
475     ///     array_layers: 1,
476     /// };
477     ///
478     /// assert_eq!(dims.mipmap_dimensions(0), Some(dims));
479     /// assert_eq!(dims.mipmap_dimensions(1), Some(ImageDimensions::Dim2d {
480     ///     width: 481,
481     ///     height: 128,
482     ///     array_layers: 1,
483     /// }));
484     /// assert_eq!(dims.mipmap_dimensions(6), Some(ImageDimensions::Dim2d {
485     ///     width: 15,
486     ///     height: 4,
487     ///     array_layers: 1,
488     /// }));
489     /// assert_eq!(dims.mipmap_dimensions(9), Some(ImageDimensions::Dim2d {
490     ///     width: 1,
491     ///     height: 1,
492     ///     array_layers: 1,
493     /// }));
494     /// assert_eq!(dims.mipmap_dimensions(11), None);
495     /// ```
496     ///
497     /// # Panic
498     ///
499     /// In debug mode, Panics if `width`, `height` or `depth` is equal to 0. In release, returns
500     /// an unspecified value.
501     ///
mipmap_dimensions(&self, level: u32) -> Option<ImageDimensions>502     pub fn mipmap_dimensions(&self, level: u32) -> Option<ImageDimensions> {
503         if level == 0 {
504             return Some(*self);
505         }
506 
507         if level >= self.max_mipmaps() {
508             return None;
509         }
510 
511         Some(match *self {
512             ImageDimensions::Dim1d {
513                 width,
514                 array_layers,
515             } => {
516                 debug_assert_ne!(width, 0);
517                 ImageDimensions::Dim1d {
518                     array_layers,
519                     width: cmp::max(1, width >> level),
520                 }
521             }
522 
523             ImageDimensions::Dim2d {
524                 width,
525                 height,
526                 array_layers,
527             } => {
528                 debug_assert_ne!(width, 0);
529                 debug_assert_ne!(height, 0);
530                 ImageDimensions::Dim2d {
531                     width: cmp::max(1, width >> level),
532                     height: cmp::max(1, height >> level),
533                     array_layers,
534                 }
535             }
536 
537             ImageDimensions::Dim3d {
538                 width,
539                 height,
540                 depth,
541             } => {
542                 debug_assert_ne!(width, 0);
543                 debug_assert_ne!(height, 0);
544                 ImageDimensions::Dim3d {
545                     width: cmp::max(1, width >> level),
546                     height: cmp::max(1, height >> level),
547                     depth: cmp::max(1, depth >> level),
548                 }
549             }
550         })
551     }
552 }
553 
554 #[cfg(test)]
555 mod tests {
556     use crate::format::Format;
557     use crate::image::ImageDimensions;
558     use crate::image::ImmutableImage;
559     use crate::image::MipmapsCount;
560 
561     #[test]
max_mipmaps()562     fn max_mipmaps() {
563         let dims = ImageDimensions::Dim2d {
564             width: 2,
565             height: 1,
566             array_layers: 1,
567         };
568         assert_eq!(dims.max_mipmaps(), 2);
569 
570         let dims = ImageDimensions::Dim2d {
571             width: 2,
572             height: 3,
573             array_layers: 1,
574         };
575         assert_eq!(dims.max_mipmaps(), 2);
576 
577         let dims = ImageDimensions::Dim2d {
578             width: 512,
579             height: 512,
580             array_layers: 1,
581         };
582         assert_eq!(dims.max_mipmaps(), 10);
583     }
584 
585     #[test]
mipmap_dimensions()586     fn mipmap_dimensions() {
587         let dims = ImageDimensions::Dim2d {
588             width: 283,
589             height: 175,
590             array_layers: 1,
591         };
592         assert_eq!(dims.mipmap_dimensions(0), Some(dims));
593         assert_eq!(
594             dims.mipmap_dimensions(1),
595             Some(ImageDimensions::Dim2d {
596                 width: 141,
597                 height: 87,
598                 array_layers: 1,
599             })
600         );
601         assert_eq!(
602             dims.mipmap_dimensions(2),
603             Some(ImageDimensions::Dim2d {
604                 width: 70,
605                 height: 43,
606                 array_layers: 1,
607             })
608         );
609         assert_eq!(
610             dims.mipmap_dimensions(3),
611             Some(ImageDimensions::Dim2d {
612                 width: 35,
613                 height: 21,
614                 array_layers: 1,
615             })
616         );
617 
618         assert_eq!(
619             dims.mipmap_dimensions(4),
620             Some(ImageDimensions::Dim2d {
621                 width: 17,
622                 height: 10,
623                 array_layers: 1,
624             })
625         );
626         assert_eq!(
627             dims.mipmap_dimensions(5),
628             Some(ImageDimensions::Dim2d {
629                 width: 8,
630                 height: 5,
631                 array_layers: 1,
632             })
633         );
634         assert_eq!(
635             dims.mipmap_dimensions(6),
636             Some(ImageDimensions::Dim2d {
637                 width: 4,
638                 height: 2,
639                 array_layers: 1,
640             })
641         );
642         assert_eq!(
643             dims.mipmap_dimensions(7),
644             Some(ImageDimensions::Dim2d {
645                 width: 2,
646                 height: 1,
647                 array_layers: 1,
648             })
649         );
650         assert_eq!(
651             dims.mipmap_dimensions(8),
652             Some(ImageDimensions::Dim2d {
653                 width: 1,
654                 height: 1,
655                 array_layers: 1,
656             })
657         );
658         assert_eq!(dims.mipmap_dimensions(9), None);
659     }
660 
661     #[test]
mipmap_working_immutable_image()662     fn mipmap_working_immutable_image() {
663         let (device, queue) = gfx_dev_and_queue!();
664 
665         let dimensions = ImageDimensions::Dim2d {
666             width: 512,
667             height: 512,
668             array_layers: 1,
669         };
670         {
671             let mut vec = Vec::new();
672 
673             vec.resize(512 * 512, 0u8);
674 
675             let (image, _) = ImmutableImage::from_iter(
676                 vec.into_iter(),
677                 dimensions,
678                 MipmapsCount::One,
679                 Format::R8Unorm,
680                 queue.clone(),
681             )
682             .unwrap();
683             assert_eq!(image.mipmap_levels(), 1);
684         }
685         {
686             let mut vec = Vec::new();
687 
688             vec.resize(512 * 512, 0u8);
689 
690             let (image, _) = ImmutableImage::from_iter(
691                 vec.into_iter(),
692                 dimensions,
693                 MipmapsCount::Log2,
694                 Format::R8Unorm,
695                 queue.clone(),
696             )
697             .unwrap();
698             assert_eq!(image.mipmap_levels(), 10);
699         }
700     }
701 }
702