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 //! Low-level implementation of images.
11 //!
12 //! This module contains low-level wrappers around the Vulkan image types. All
13 //! other image types of this library, and all custom image types
14 //! that you create must wrap around the types in this module.
15 
16 use super::{
17     ImageAspect, ImageAspects, ImageCreateFlags, ImageDimensions, ImageLayout,
18     ImageSubresourceLayers, ImageSubresourceRange, ImageTiling, ImageUsage, SampleCount,
19     SampleCounts, SparseImageMemoryRequirements,
20 };
21 use crate::{
22     buffer::subbuffer::{ReadLockError, WriteLockError},
23     cache::OnceCache,
24     device::{Device, DeviceOwned},
25     format::{ChromaSampling, Format, FormatFeatures, NumericType},
26     image::{
27         view::ImageViewCreationError, ImageFormatInfo, ImageFormatProperties, ImageType,
28         SparseImageFormatProperties,
29     },
30     macros::impl_id_counter,
31     memory::{
32         allocator::{AllocationCreationError, AllocationType, DeviceLayout, MemoryAlloc},
33         is_aligned, DedicatedTo, DeviceAlignment, ExternalMemoryHandleType,
34         ExternalMemoryHandleTypes, MemoryPropertyFlags, MemoryRequirements,
35     },
36     range_map::RangeMap,
37     swapchain::Swapchain,
38     sync::{future::AccessError, CurrentAccess, Sharing},
39     DeviceSize, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
40 };
41 use ash::vk::ImageDrmFormatModifierExplicitCreateInfoEXT;
42 use parking_lot::{Mutex, MutexGuard};
43 use smallvec::{smallvec, SmallVec};
44 use std::{
45     error::Error,
46     fmt::{Display, Error as FmtError, Formatter},
47     hash::{Hash, Hasher},
48     iter::{FusedIterator, Peekable},
49     mem::{size_of_val, MaybeUninit},
50     num::NonZeroU64,
51     ops::Range,
52     ptr,
53     sync::Arc,
54 };
55 
56 /// A raw image, with no memory backing it.
57 ///
58 /// This is the basic image type, a direct translation of a `VkImage` object, but it is mostly
59 /// useless in this form. After creating a raw image, you must call `bind_memory` to make a
60 /// complete image object.
61 #[derive(Debug)]
62 pub struct RawImage {
63     handle: ash::vk::Image,
64     device: Arc<Device>,
65     id: NonZeroU64,
66 
67     flags: ImageCreateFlags,
68     dimensions: ImageDimensions,
69     format: Option<Format>,
70     format_features: FormatFeatures,
71     initial_layout: ImageLayout,
72     mip_levels: u32,
73     samples: SampleCount,
74     tiling: ImageTiling,
75     usage: ImageUsage,
76     sharing: Sharing<SmallVec<[u32; 4]>>,
77     stencil_usage: ImageUsage,
78     external_memory_handle_types: ExternalMemoryHandleTypes,
79 
80     memory_requirements: SmallVec<[MemoryRequirements; 3]>,
81     needs_destruction: bool, // `vkDestroyImage` is called only if true.
82     subresource_layout: OnceCache<(ImageAspect, u32, u32), SubresourceLayout>,
83 }
84 
85 impl RawImage {
86     /// Creates a new `RawImage`.
87     ///
88     /// # Panics
89     ///
90     /// - Panics if one of the values in `create_info.dimensions` is zero.
91     /// - Panics if `create_info.format` is `None`.
92     /// - Panics if `create_info.block_texel_view_compatible` is set but not
93     ///   `create_info.mutable_format`.
94     /// - Panics if `create_info.mip_levels` is `0`.
95     /// - Panics if `create_info.sharing` is [`Sharing::Concurrent`] with less than 2 items.
96     /// - Panics if `create_info.initial_layout` is something other than
97     ///   [`ImageLayout::Undefined`] or [`ImageLayout::Preinitialized`].
98     /// - Panics if `create_info.usage` is empty.
99     /// - Panics if `create_info.usage` contains `transient_attachment`, but does not also contain
100     ///   at least one of `color_attachment`, `depth_stencil_attachment`, `input_attachment`, or
101     ///   if it contains values other than these.
102     #[inline]
new( device: Arc<Device>, mut create_info: ImageCreateInfo, ) -> Result<RawImage, ImageError>103     pub fn new(
104         device: Arc<Device>,
105         mut create_info: ImageCreateInfo,
106     ) -> Result<RawImage, ImageError> {
107         match &mut create_info.sharing {
108             Sharing::Exclusive => (),
109             Sharing::Concurrent(queue_family_indices) => {
110                 // VUID-VkImageCreateInfo-sharingMode-01420
111                 queue_family_indices.sort_unstable();
112                 queue_family_indices.dedup();
113             }
114         }
115 
116         Self::validate_new(&device, &create_info)?;
117 
118         unsafe { Ok(RawImage::new_unchecked(device, create_info)?) }
119     }
120 
validate_new( device: &Device, create_info: &ImageCreateInfo, ) -> Result<FormatFeatures, ImageError>121     fn validate_new(
122         device: &Device,
123         create_info: &ImageCreateInfo,
124     ) -> Result<FormatFeatures, ImageError> {
125         let &ImageCreateInfo {
126             flags,
127             dimensions,
128             format,
129             mip_levels,
130             samples,
131             tiling,
132             usage,
133             mut stencil_usage,
134             ref sharing,
135             initial_layout,
136             external_memory_handle_types,
137             _ne: _,
138             image_drm_format_modifier_create_info,
139         } = create_info;
140 
141         let physical_device = device.physical_device();
142         let device_properties = physical_device.properties();
143 
144         let format = format.unwrap(); // Can be None for "external formats" but Vulkano doesn't support that yet
145         let aspects = format.aspects();
146 
147         let has_separate_stencil_usage = if stencil_usage.is_empty()
148             || !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
149         {
150             stencil_usage = usage;
151             false
152         } else {
153             stencil_usage == usage
154         };
155 
156         // VUID-VkImageCreateInfo-flags-parameter
157         flags.validate_device(device)?;
158 
159         // VUID-VkImageCreateInfo-format-parameter
160         format.validate_device(device)?;
161 
162         // VUID-VkImageCreateInfo-samples-parameter
163         samples.validate_device(device)?;
164 
165         // VUID-VkImageCreateInfo-tiling-parameter
166         tiling.validate_device(device)?;
167 
168         // VUID-VkImageCreateInfo-usage-parameter
169         usage.validate_device(device)?;
170 
171         // VUID-VkImageCreateInfo-usage-requiredbitmask
172         assert!(!usage.is_empty());
173 
174         if has_separate_stencil_usage {
175             if !(device.api_version() >= Version::V1_2
176                 || device.enabled_extensions().ext_separate_stencil_usage)
177             {
178                 return Err(ImageError::RequirementNotMet {
179                     required_for: "`create_info.stencil_usage` is `Some` and `create_info.format` \
180                         has both a depth and a stencil aspect",
181                     requires_one_of: RequiresOneOf {
182                         api_version: Some(Version::V1_2),
183                         device_extensions: &["ext_separate_stencil_usage"],
184                         ..Default::default()
185                     },
186                 });
187             }
188 
189             // VUID-VkImageStencilUsageCreateInfo-stencilUsage-parameter
190             stencil_usage.validate_device(device)?;
191 
192             // VUID-VkImageStencilUsageCreateInfo-usage-requiredbitmask
193             assert!(!stencil_usage.is_empty());
194         }
195 
196         // VUID-VkImageCreateInfo-initialLayout-parameter
197         initial_layout.validate_device(device)?;
198 
199         // VUID-VkImageCreateInfo-initialLayout-00993
200         assert!(matches!(
201             initial_layout,
202             ImageLayout::Undefined | ImageLayout::Preinitialized
203         ));
204 
205         // VUID-VkImageCreateInfo-flags-01573
206         assert!(
207             !flags.intersects(ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE)
208                 || flags.intersects(ImageCreateFlags::MUTABLE_FORMAT)
209         );
210 
211         // VUID-VkImageCreateInfo-tiling-02261
212         // VUID-VkImageCreateInfo-pNext-02262
213         if (tiling == ImageTiling::DrmFormatModifier)
214             != image_drm_format_modifier_create_info.is_some()
215         {
216             return Err(ImageError::DrmFormatModifierRequiresCreateInfo);
217         }
218 
219         // Get format features
220         let format_features = {
221             // Use unchecked, because all validation has been done above.
222             let format_properties = unsafe { physical_device.format_properties_unchecked(format) };
223             match tiling {
224                 ImageTiling::Linear => format_properties.linear_tiling_features,
225                 ImageTiling::Optimal => format_properties.optimal_tiling_features,
226                 ImageTiling::DrmFormatModifier => format_properties.linear_tiling_features, // TODO: Improve
227             }
228         };
229 
230         // TODO: VUID-VkImageCreateInfo-tiling-02353
231         // Vulkano currently has no high-level way to add or check for VkImageFormatListCreateInfo.
232 
233         // Format isn't supported at all?
234         if format_features.is_empty() {
235             return Err(ImageError::FormatNotSupported);
236         }
237 
238         // Decode the dimensions
239         let (image_type, extent, array_layers) = match dimensions {
240             ImageDimensions::Dim1d {
241                 width,
242                 array_layers,
243             } => (ImageType::Dim1d, [width, 1, 1], array_layers),
244             ImageDimensions::Dim2d {
245                 width,
246                 height,
247                 array_layers,
248             } => (ImageType::Dim2d, [width, height, 1], array_layers),
249             ImageDimensions::Dim3d {
250                 width,
251                 height,
252                 depth,
253             } => (ImageType::Dim3d, [width, height, depth], 1),
254         };
255 
256         // VUID-VkImageCreateInfo-extent-00944
257         assert!(extent[0] != 0);
258 
259         // VUID-VkImageCreateInfo-extent-00945
260         assert!(extent[1] != 0);
261 
262         // VUID-VkImageCreateInfo-extent-00946
263         assert!(extent[2] != 0);
264 
265         // VUID-VkImageCreateInfo-arrayLayers-00948
266         assert!(array_layers != 0);
267 
268         // VUID-VkImageCreateInfo-mipLevels-00947
269         assert!(mip_levels != 0);
270 
271         // Check mip levels
272 
273         let max_mip_levels = dimensions.max_mip_levels();
274         debug_assert!(max_mip_levels >= 1);
275 
276         // VUID-VkImageCreateInfo-mipLevels-00958
277         if mip_levels > max_mip_levels {
278             return Err(ImageError::MaxMipLevelsExceeded {
279                 mip_levels,
280                 max: max_mip_levels,
281             });
282         }
283 
284         // VUID-VkImageCreateInfo-samples-02257
285         if samples != SampleCount::Sample1 {
286             if image_type != ImageType::Dim2d {
287                 return Err(ImageError::MultisampleNot2d);
288             }
289 
290             if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) {
291                 return Err(ImageError::MultisampleCubeCompatible);
292             }
293 
294             if mip_levels != 1 {
295                 return Err(ImageError::MultisampleMultipleMipLevels);
296             }
297 
298             if tiling == ImageTiling::Linear {
299                 return Err(ImageError::MultisampleLinearTiling);
300             }
301 
302             // VUID-VkImageCreateInfo-multisampleArrayImage-04460
303             if device.enabled_extensions().khr_portability_subset
304                 && !device.enabled_features().multisample_array_image
305                 && array_layers != 1
306             {
307                 return Err(ImageError::RequirementNotMet {
308                     required_for: "this device is a portability subset device, \
309                         `create_info.samples` is not `SampleCount::Sample1` and \
310                         `create_info.dimensions.array_layers()` is greater than `1`",
311                     requires_one_of: RequiresOneOf {
312                         features: &["multisample_array_image"],
313                         ..Default::default()
314                     },
315                 });
316             }
317         }
318 
319         // Check limits for YCbCr formats
320         if let Some(chroma_sampling) = format.ycbcr_chroma_sampling() {
321             // VUID-VkImageCreateInfo-format-06410
322             if mip_levels != 1 {
323                 return Err(ImageError::YcbcrFormatMultipleMipLevels);
324             }
325 
326             // VUID-VkImageCreateInfo-format-06411
327             if samples != SampleCount::Sample1 {
328                 return Err(ImageError::YcbcrFormatMultisampling);
329             }
330 
331             // VUID-VkImageCreateInfo-format-06412
332             if image_type != ImageType::Dim2d {
333                 return Err(ImageError::YcbcrFormatNot2d);
334             }
335 
336             // VUID-VkImageCreateInfo-format-06413
337             if array_layers > 1 && !device.enabled_features().ycbcr_image_arrays {
338                 return Err(ImageError::RequirementNotMet {
339                     required_for: "`create_info.format.ycbcr_chroma_sampling()` is `Some` and \
340                         `create_info.dimensions.array_layers()` is greater than `1`",
341                     requires_one_of: RequiresOneOf {
342                         features: &["ycbcr_image_arrays"],
343                         ..Default::default()
344                     },
345                 });
346             }
347 
348             match chroma_sampling {
349                 ChromaSampling::Mode444 => (),
350                 ChromaSampling::Mode422 => {
351                     // VUID-VkImageCreateInfo-format-04712
352                     if extent[0] % 2 != 0 {
353                         return Err(ImageError::YcbcrFormatInvalidDimensions);
354                     }
355                 }
356                 ChromaSampling::Mode420 => {
357                     // VUID-VkImageCreateInfo-format-04712
358                     // VUID-VkImageCreateInfo-format-04713
359                     if !(extent[0] % 2 == 0 && extent[1] % 2 == 0) {
360                         return Err(ImageError::YcbcrFormatInvalidDimensions);
361                     }
362                 }
363             }
364         }
365 
366         /* Check usage requirements */
367 
368         let combined_usage = usage | stencil_usage;
369 
370         if combined_usage.intersects(ImageUsage::SAMPLED)
371             && !format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
372         {
373             return Err(ImageError::FormatUsageNotSupported { usage: "sampled" });
374         }
375 
376         if combined_usage.intersects(ImageUsage::COLOR_ATTACHMENT)
377             && !format_features.intersects(FormatFeatures::COLOR_ATTACHMENT)
378         {
379             return Err(ImageError::FormatUsageNotSupported {
380                 usage: "color_attachment",
381             });
382         }
383 
384         if combined_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
385             && !format_features.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
386         {
387             return Err(ImageError::FormatUsageNotSupported {
388                 usage: "depth_stencil_attachment",
389             });
390         }
391 
392         if combined_usage.intersects(ImageUsage::INPUT_ATTACHMENT)
393             && !format_features.intersects(
394                 FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT,
395             )
396         {
397             return Err(ImageError::FormatUsageNotSupported {
398                 usage: "input_attachment",
399             });
400         }
401 
402         if combined_usage.intersects(
403             ImageUsage::COLOR_ATTACHMENT
404                 | ImageUsage::DEPTH_STENCIL_ATTACHMENT
405                 | ImageUsage::INPUT_ATTACHMENT
406                 | ImageUsage::TRANSIENT_ATTACHMENT,
407         ) {
408             // VUID-VkImageCreateInfo-usage-00964
409             // VUID-VkImageCreateInfo-usage-00965
410             // VUID-VkImageCreateInfo-Format-02536
411             // VUID-VkImageCreateInfo-format-02537
412             if extent[0] > device_properties.max_framebuffer_width
413                 || extent[1] > device_properties.max_framebuffer_height
414             {
415                 return Err(ImageError::MaxFramebufferDimensionsExceeded {
416                     extent: [extent[0], extent[1]],
417                     max: [
418                         device_properties.max_framebuffer_width,
419                         device_properties.max_framebuffer_height,
420                     ],
421                 });
422             }
423         }
424 
425         if combined_usage.intersects(ImageUsage::STORAGE) {
426             if !format_features.intersects(FormatFeatures::STORAGE_IMAGE) {
427                 return Err(ImageError::FormatUsageNotSupported { usage: "storage" });
428             }
429 
430             // VUID-VkImageCreateInfo-usage-00968
431             // VUID-VkImageCreateInfo-format-02538
432             if !device.enabled_features().shader_storage_image_multisample
433                 && samples != SampleCount::Sample1
434             {
435                 return Err(ImageError::RequirementNotMet {
436                     required_for: "`create_info.usage` or `create_info.stencil_usage` contains \
437                         `ImageUsage::STORAGE`, and `create_info.samples` is not \
438                         `SampleCount::Sample1`",
439                     requires_one_of: RequiresOneOf {
440                         features: &["shader_storage_image_multisample"],
441                         ..Default::default()
442                     },
443                 });
444             }
445         }
446 
447         // These flags only exist in later versions, ignore them otherwise
448         if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 {
449             if combined_usage.intersects(ImageUsage::TRANSFER_SRC)
450                 && !format_features.intersects(FormatFeatures::TRANSFER_SRC)
451             {
452                 return Err(ImageError::FormatUsageNotSupported {
453                     usage: "transfer_src",
454                 });
455             }
456 
457             if combined_usage.intersects(ImageUsage::TRANSFER_DST)
458                 && !format_features.intersects(FormatFeatures::TRANSFER_DST)
459             {
460                 return Err(ImageError::FormatUsageNotSupported {
461                     usage: "transfer_dst",
462                 });
463             }
464         }
465 
466         if usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT) {
467             // VUID-VkImageCreateInfo-usage-00966
468             assert!(usage.intersects(
469                 ImageUsage::COLOR_ATTACHMENT
470                     | ImageUsage::DEPTH_STENCIL_ATTACHMENT
471                     | ImageUsage::INPUT_ATTACHMENT
472             ));
473 
474             // VUID-VkImageCreateInfo-usage-00963
475             assert!((usage
476                 - (ImageUsage::TRANSIENT_ATTACHMENT
477                     | ImageUsage::COLOR_ATTACHMENT
478                     | ImageUsage::DEPTH_STENCIL_ATTACHMENT
479                     | ImageUsage::INPUT_ATTACHMENT))
480                 .is_empty())
481         }
482 
483         if has_separate_stencil_usage {
484             // VUID-VkImageCreateInfo-format-02795
485             // VUID-VkImageCreateInfo-format-02796
486             if usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
487                 != stencil_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
488             {
489                 return Err(ImageError::StencilUsageMismatch {
490                     usage,
491                     stencil_usage,
492                 });
493             }
494 
495             // VUID-VkImageCreateInfo-format-02797
496             // VUID-VkImageCreateInfo-format-02798
497             if usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
498                 != stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT)
499             {
500                 return Err(ImageError::StencilUsageMismatch {
501                     usage,
502                     stencil_usage,
503                 });
504             }
505 
506             if stencil_usage.intersects(ImageUsage::TRANSIENT_ATTACHMENT) {
507                 // VUID-VkImageStencilUsageCreateInfo-stencilUsage-02539
508                 assert!((stencil_usage
509                     - (ImageUsage::TRANSIENT_ATTACHMENT
510                         | ImageUsage::DEPTH_STENCIL_ATTACHMENT
511                         | ImageUsage::INPUT_ATTACHMENT))
512                     .is_empty())
513             }
514         }
515 
516         /* Check flags requirements */
517 
518         if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) {
519             // VUID-VkImageCreateInfo-flags-00949
520             if image_type != ImageType::Dim2d {
521                 return Err(ImageError::CubeCompatibleNot2d);
522             }
523 
524             // VUID-VkImageCreateInfo-imageType-00954
525             if extent[0] != extent[1] {
526                 return Err(ImageError::CubeCompatibleNotSquare);
527             }
528 
529             // VUID-VkImageCreateInfo-imageType-00954
530             if array_layers < 6 {
531                 return Err(ImageError::CubeCompatibleNotEnoughArrayLayers);
532             }
533         }
534 
535         if flags.intersects(ImageCreateFlags::ARRAY_2D_COMPATIBLE) {
536             // VUID-VkImageCreateInfo-flags-00950
537             if image_type != ImageType::Dim3d {
538                 return Err(ImageError::Array2dCompatibleNot3d);
539             }
540 
541             // VUID-VkImageCreateInfo-imageView2DOn3DImage-04459
542             if device.enabled_extensions().khr_portability_subset
543                 && !device.enabled_features().image_view2_d_on3_d_image
544             {
545                 return Err(ImageError::RequirementNotMet {
546                     required_for: "this device is a portability subset device, and \
547                         `create_info.flags` contains `ImageCreateFlags::ARRAY_2D_COMPATIBLE`",
548                     requires_one_of: RequiresOneOf {
549                         features: &["image_view2_d_on3_d_image"],
550                         ..Default::default()
551                     },
552                 });
553             }
554         }
555 
556         if flags.intersects(ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE) {
557             // VUID-VkImageCreateInfo-flags-01572
558             if format.compression().is_none() {
559                 return Err(ImageError::BlockTexelViewCompatibleNotCompressed);
560             }
561         }
562 
563         if flags.intersects(ImageCreateFlags::DISJOINT) {
564             // VUID-VkImageCreateInfo-format-01577
565             if format.planes().len() < 2 {
566                 return Err(ImageError::DisjointFormatNotSupported);
567             }
568 
569             // VUID-VkImageCreateInfo-imageCreateFormatFeatures-02260
570             if !format_features.intersects(FormatFeatures::DISJOINT) {
571                 return Err(ImageError::DisjointFormatNotSupported);
572             }
573         }
574 
575         /* Check sharing mode and queue families */
576 
577         match sharing {
578             Sharing::Exclusive => (),
579             Sharing::Concurrent(queue_family_indices) => {
580                 // VUID-VkImageCreateInfo-sharingMode-00942
581                 assert!(queue_family_indices.len() >= 2);
582 
583                 for &queue_family_index in queue_family_indices {
584                     // VUID-VkImageCreateInfo-sharingMode-01420
585                     if queue_family_index
586                         >= device.physical_device().queue_family_properties().len() as u32
587                     {
588                         return Err(ImageError::SharingQueueFamilyIndexOutOfRange {
589                             queue_family_index,
590                             queue_family_count: device
591                                 .physical_device()
592                                 .queue_family_properties()
593                                 .len() as u32,
594                         });
595                     }
596                 }
597             }
598         }
599 
600         /* External memory handles */
601 
602         if !external_memory_handle_types.is_empty() {
603             if !(device.api_version() >= Version::V1_1
604                 || device.enabled_extensions().khr_external_memory)
605             {
606                 return Err(ImageError::RequirementNotMet {
607                     required_for: "`create_info.external_memory_handle_types` is not empty",
608                     requires_one_of: RequiresOneOf {
609                         api_version: Some(Version::V1_1),
610                         device_extensions: &["khr_external_memory"],
611                         ..Default::default()
612                     },
613                 });
614             }
615 
616             // VUID-VkExternalMemoryImageCreateInfo-handleTypes-parameter
617             external_memory_handle_types.validate_device(device)?;
618 
619             // VUID-VkImageCreateInfo-pNext-01443
620             if initial_layout != ImageLayout::Undefined {
621                 return Err(ImageError::ExternalMemoryInvalidInitialLayout);
622             }
623         }
624 
625         /*
626             Some device limits can be exceeded, but only for particular image configurations, which
627             must be queried with `image_format_properties`. See:
628             https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap44.html#capabilities-image
629             First, we check if this is the case, then query the device if so.
630         */
631 
632         // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap44.html#features-extentperimagetype
633         let extent_must_query = || match image_type {
634             ImageType::Dim1d => {
635                 let limit = device.physical_device().properties().max_image_dimension1_d;
636                 extent[0] > limit
637             }
638             ImageType::Dim2d if flags.intersects(ImageCreateFlags::CUBE_COMPATIBLE) => {
639                 let limit = device
640                     .physical_device()
641                     .properties()
642                     .max_image_dimension_cube;
643                 extent[0] > limit
644             }
645             ImageType::Dim2d => {
646                 let limit = device.physical_device().properties().max_image_dimension2_d;
647                 extent[0] > limit || extent[1] > limit
648             }
649             ImageType::Dim3d => {
650                 let limit = device.physical_device().properties().max_image_dimension3_d;
651                 extent[0] > limit || extent[1] > limit || extent[2] > limit
652             }
653         };
654         // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkImageFormatProperties.html
655         let mip_levels_must_query = || {
656             if mip_levels > 1 {
657                 // TODO: for external memory, the spec says:
658                 // "handle type included in the handleTypes member for which mipmap image support is
659                 // not required". But which handle types are those?
660                 !external_memory_handle_types.is_empty()
661             } else {
662                 false
663             }
664         };
665         // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkImageFormatProperties.html
666         let array_layers_must_query = || {
667             if array_layers > device.physical_device().properties().max_image_array_layers {
668                 true
669             } else if array_layers > 1 {
670                 image_type == ImageType::Dim3d
671             } else {
672                 false
673             }
674         };
675         // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap44.html#features-supported-sample-counts
676         let samples_must_query = || {
677             if samples == SampleCount::Sample1 {
678                 return false;
679             }
680 
681             if combined_usage.intersects(ImageUsage::COLOR_ATTACHMENT)
682                 && !device_properties
683                     .framebuffer_color_sample_counts
684                     .contains_enum(samples)
685             {
686                 // TODO: how to handle framebuffer_integer_color_sample_counts limit, which only
687                 // exists >= Vulkan 1.2
688                 return true;
689             }
690 
691             if combined_usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) {
692                 if aspects.intersects(ImageAspects::DEPTH)
693                     && !device_properties
694                         .framebuffer_depth_sample_counts
695                         .contains_enum(samples)
696                 {
697                     return true;
698                 }
699 
700                 if aspects.intersects(ImageAspects::STENCIL)
701                     && !device_properties
702                         .framebuffer_stencil_sample_counts
703                         .contains_enum(samples)
704                 {
705                     return true;
706                 }
707             }
708 
709             if combined_usage.intersects(ImageUsage::SAMPLED) {
710                 if let Some(numeric_type) = format.type_color() {
711                     match numeric_type {
712                         NumericType::UINT | NumericType::SINT => {
713                             if !device_properties
714                                 .sampled_image_integer_sample_counts
715                                 .contains_enum(samples)
716                             {
717                                 return true;
718                             }
719                         }
720                         NumericType::SFLOAT
721                         | NumericType::UFLOAT
722                         | NumericType::SNORM
723                         | NumericType::UNORM
724                         | NumericType::SSCALED
725                         | NumericType::USCALED
726                         | NumericType::SRGB => {
727                             if !device_properties
728                                 .sampled_image_color_sample_counts
729                                 .contains_enum(samples)
730                             {
731                                 return true;
732                             }
733                         }
734                     }
735                 } else {
736                     if aspects.intersects(ImageAspects::DEPTH)
737                         && !device_properties
738                             .sampled_image_depth_sample_counts
739                             .contains_enum(samples)
740                     {
741                         return true;
742                     }
743 
744                     if aspects.intersects(ImageAspects::STENCIL)
745                         && device_properties
746                             .sampled_image_stencil_sample_counts
747                             .contains_enum(samples)
748                     {
749                         return true;
750                     }
751                 }
752             }
753 
754             if combined_usage.intersects(ImageUsage::STORAGE)
755                 && !device_properties
756                     .storage_image_sample_counts
757                     .contains_enum(samples)
758             {
759                 return true;
760             }
761 
762             false
763         };
764         // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkImageCreateInfo.html#_description
765         let linear_must_query = || {
766             if tiling == ImageTiling::Linear {
767                 !(image_type == ImageType::Dim2d
768                     && format.type_color().is_some()
769                     && mip_levels == 1
770                     && array_layers == 1
771                     // VUID-VkImageCreateInfo-samples-02257 already states that multisampling+linear
772                     // is invalid so no need to check for that here.
773                     && (usage - (ImageUsage::TRANSFER_SRC | ImageUsage::TRANSFER_DST)).is_empty())
774             } else {
775                 false
776             }
777         };
778 
779         let must_query_device = extent_must_query()
780             || mip_levels_must_query()
781             || array_layers_must_query()
782             || samples_must_query()
783             || linear_must_query();
784 
785         // We determined that we must query the device in order to be sure that the image
786         // configuration is supported.
787         if must_query_device {
788             let external_memory_handle_types: SmallVec<[Option<ExternalMemoryHandleType>; 4]> =
789                 if !external_memory_handle_types.is_empty() {
790                     // If external memory handles are used, the properties need to be queried
791                     // individually for each handle type.
792                     external_memory_handle_types.into_iter().map(Some).collect()
793                 } else {
794                     smallvec![None]
795                 };
796 
797             for external_memory_handle_type in external_memory_handle_types {
798                 // Use unchecked, because all validation has been done above.
799                 let image_format_properties = unsafe {
800                     device
801                         .physical_device()
802                         .image_format_properties_unchecked(ImageFormatInfo {
803                             flags,
804                             format: Some(format),
805                             image_type,
806                             tiling,
807                             usage,
808                             external_memory_handle_type,
809                             ..Default::default()
810                         })?
811                 };
812 
813                 let ImageFormatProperties {
814                     max_extent,
815                     max_mip_levels,
816                     max_array_layers,
817                     sample_counts,
818                     max_resource_size: _,
819                     ..
820                 } = match image_format_properties {
821                     Some(x) => x,
822                     None => return Err(ImageError::ImageFormatPropertiesNotSupported),
823                 };
824 
825                 // VUID-VkImageCreateInfo-extent-02252
826                 // VUID-VkImageCreateInfo-extent-02253
827                 // VUID-VkImageCreateInfo-extent-02254
828                 if extent[0] > max_extent[0]
829                     || extent[1] > max_extent[1]
830                     || extent[2] > max_extent[2]
831                 {
832                     return Err(ImageError::MaxDimensionsExceeded {
833                         extent,
834                         max: max_extent,
835                     });
836                 }
837 
838                 // VUID-VkImageCreateInfo-mipLevels-02255
839                 if mip_levels > max_mip_levels {
840                     return Err(ImageError::MaxMipLevelsExceeded {
841                         mip_levels,
842                         max: max_mip_levels,
843                     });
844                 }
845 
846                 // VUID-VkImageCreateInfo-arrayLayers-02256
847                 if array_layers > max_array_layers {
848                     return Err(ImageError::MaxArrayLayersExceeded {
849                         array_layers,
850                         max: max_array_layers,
851                     });
852                 }
853 
854                 // VUID-VkImageCreateInfo-samples-02258
855                 if !sample_counts.contains_enum(samples) {
856                     return Err(ImageError::SampleCountNotSupported {
857                         samples,
858                         supported: sample_counts,
859                     });
860                 }
861 
862                 // TODO: check resource size?
863             }
864         }
865 
866         Ok(format_features)
867     }
868 
869     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
870     #[inline]
new_unchecked( device: Arc<Device>, create_info: ImageCreateInfo, ) -> Result<Self, VulkanError>871     pub unsafe fn new_unchecked(
872         device: Arc<Device>,
873         create_info: ImageCreateInfo,
874     ) -> Result<Self, VulkanError> {
875         let &ImageCreateInfo {
876             flags,
877             dimensions,
878             format,
879             mip_levels,
880             samples,
881             tiling,
882             usage,
883             mut stencil_usage,
884             ref sharing,
885             initial_layout,
886             external_memory_handle_types,
887             _ne: _,
888             mut image_drm_format_modifier_create_info,
889         } = &create_info;
890 
891         let aspects = format.map_or_else(Default::default, |format| format.aspects());
892 
893         let has_separate_stencil_usage = if stencil_usage.is_empty()
894             || !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
895         {
896             stencil_usage = usage;
897             false
898         } else {
899             stencil_usage == usage
900         };
901 
902         let (image_type, extent, array_layers) = match dimensions {
903             ImageDimensions::Dim1d {
904                 width,
905                 array_layers,
906             } => (ImageType::Dim1d, [width, 1, 1], array_layers),
907             ImageDimensions::Dim2d {
908                 width,
909                 height,
910                 array_layers,
911             } => (ImageType::Dim2d, [width, height, 1], array_layers),
912             ImageDimensions::Dim3d {
913                 width,
914                 height,
915                 depth,
916             } => (ImageType::Dim3d, [width, height, depth], 1),
917         };
918 
919         let (sharing_mode, queue_family_index_count, p_queue_family_indices) = match sharing {
920             Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, 0, &[] as _),
921             Sharing::Concurrent(queue_family_indices) => (
922                 ash::vk::SharingMode::CONCURRENT,
923                 queue_family_indices.len() as u32,
924                 queue_family_indices.as_ptr(),
925             ),
926         };
927 
928         let mut info_vk = ash::vk::ImageCreateInfo {
929             flags: flags.into(),
930             image_type: image_type.into(),
931             format: format.map(Into::into).unwrap_or_default(),
932             extent: ash::vk::Extent3D {
933                 width: extent[0],
934                 height: extent[1],
935                 depth: extent[2],
936             },
937             mip_levels,
938             array_layers,
939             samples: samples.into(),
940             tiling: tiling.into(),
941             usage: usage.into(),
942             sharing_mode,
943             queue_family_index_count,
944             p_queue_family_indices,
945             initial_layout: initial_layout.into(),
946             ..Default::default()
947         };
948         let mut external_memory_info_vk = None;
949         let mut stencil_usage_info_vk = None;
950 
951         if !external_memory_handle_types.is_empty() {
952             let next = external_memory_info_vk.insert(ash::vk::ExternalMemoryImageCreateInfo {
953                 handle_types: external_memory_handle_types.into(),
954                 ..Default::default()
955             });
956 
957             next.p_next = info_vk.p_next;
958             info_vk.p_next = next as *const _ as *const _;
959         }
960 
961         if has_separate_stencil_usage {
962             let next = stencil_usage_info_vk.insert(ash::vk::ImageStencilUsageCreateInfo {
963                 stencil_usage: stencil_usage.into(),
964                 ..Default::default()
965             });
966 
967             next.p_next = info_vk.p_next;
968             info_vk.p_next = next as *const _ as *const _;
969         }
970 
971         if external_memory_handle_types.intersects(ExternalMemoryHandleTypes::DMA_BUF) {
972             let next = image_drm_format_modifier_create_info.as_mut().unwrap();
973 
974             next.p_next = info_vk.p_next;
975             info_vk.p_next = next as *const _ as *const _;
976         }
977 
978         let handle = {
979             let fns = device.fns();
980             let mut output = MaybeUninit::uninit();
981             (fns.v1_0.create_image)(device.handle(), &info_vk, ptr::null(), output.as_mut_ptr())
982                 .result()
983                 .map_err(VulkanError::from)?;
984             output.assume_init()
985         };
986 
987         Ok(Self::from_handle(device, handle, create_info))
988     }
989 
990     /// Creates a new `RawImage` from a raw object handle.
991     ///
992     /// # Safety
993     ///
994     /// - `handle` must be a valid Vulkan object handle created from `device`.
995     /// - `handle` must refer to an image that has not yet had memory bound to it.
996     /// - `create_info` must match the info used to create the object.
997     #[inline]
from_handle( device: Arc<Device>, handle: ash::vk::Image, create_info: ImageCreateInfo, ) -> Self998     pub unsafe fn from_handle(
999         device: Arc<Device>,
1000         handle: ash::vk::Image,
1001         create_info: ImageCreateInfo,
1002     ) -> Self {
1003         Self::from_handle_with_destruction(device, handle, create_info, true)
1004     }
1005 
from_handle_with_destruction( device: Arc<Device>, handle: ash::vk::Image, create_info: ImageCreateInfo, needs_destruction: bool, ) -> Self1006     unsafe fn from_handle_with_destruction(
1007         device: Arc<Device>,
1008         handle: ash::vk::Image,
1009         create_info: ImageCreateInfo,
1010         needs_destruction: bool,
1011     ) -> Self {
1012         let ImageCreateInfo {
1013             flags,
1014             dimensions,
1015             format,
1016             mip_levels,
1017             samples,
1018             tiling,
1019             usage,
1020             mut stencil_usage,
1021             sharing,
1022             initial_layout,
1023             external_memory_handle_types,
1024             _ne: _,
1025             image_drm_format_modifier_create_info: _,
1026         } = create_info;
1027 
1028         let aspects = format.map_or_else(Default::default, |format| format.aspects());
1029 
1030         if stencil_usage.is_empty()
1031             || !aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
1032         {
1033             stencil_usage = usage;
1034         }
1035 
1036         // Get format features
1037         let format_features = {
1038             // Use unchecked, because `create_info` is assumed to match the info of the handle, and
1039             // therefore already valid.
1040             let format_properties = device
1041                 .physical_device()
1042                 .format_properties_unchecked(format.unwrap());
1043             match tiling {
1044                 ImageTiling::Linear => format_properties.linear_tiling_features,
1045                 ImageTiling::Optimal => format_properties.optimal_tiling_features,
1046                 ImageTiling::DrmFormatModifier => format_properties.linear_tiling_features, // TODO: improve
1047             }
1048         };
1049 
1050         let memory_requirements = if needs_destruction {
1051             if flags.intersects(ImageCreateFlags::DISJOINT) {
1052                 (0..format.unwrap().planes().len())
1053                     .map(|plane| Self::get_memory_requirements(&device, handle, Some(plane)))
1054                     .collect()
1055             } else {
1056                 smallvec![Self::get_memory_requirements(&device, handle, None)]
1057             }
1058         } else {
1059             smallvec![]
1060         };
1061 
1062         RawImage {
1063             handle,
1064             device,
1065             id: Self::next_id(),
1066             flags,
1067             dimensions,
1068             format,
1069             format_features,
1070             mip_levels,
1071             initial_layout,
1072             samples,
1073             tiling,
1074             usage,
1075             stencil_usage,
1076             sharing,
1077             external_memory_handle_types,
1078             memory_requirements,
1079             needs_destruction,
1080             subresource_layout: OnceCache::new(),
1081         }
1082     }
1083 
get_memory_requirements( device: &Device, handle: ash::vk::Image, plane: Option<usize>, ) -> MemoryRequirements1084     fn get_memory_requirements(
1085         device: &Device,
1086         handle: ash::vk::Image,
1087         plane: Option<usize>,
1088     ) -> MemoryRequirements {
1089         let mut info_vk = ash::vk::ImageMemoryRequirementsInfo2 {
1090             image: handle,
1091             ..Default::default()
1092         };
1093         let mut plane_info_vk = None;
1094 
1095         if let Some(plane) = plane {
1096             debug_assert!(
1097                 device.api_version() >= Version::V1_1
1098                     || device.enabled_extensions().khr_get_memory_requirements2
1099                         && device.enabled_extensions().khr_sampler_ycbcr_conversion
1100             );
1101 
1102             let next = plane_info_vk.insert(ash::vk::ImagePlaneMemoryRequirementsInfo {
1103                 plane_aspect: match plane {
1104                     0 => ash::vk::ImageAspectFlags::PLANE_0,
1105                     1 => ash::vk::ImageAspectFlags::PLANE_1,
1106                     2 => ash::vk::ImageAspectFlags::PLANE_2,
1107                     _ => unreachable!(),
1108                 },
1109                 ..Default::default()
1110             });
1111 
1112             next.p_next = info_vk.p_next;
1113             info_vk.p_next = next as *mut _ as *mut _;
1114         }
1115 
1116         let mut memory_requirements2_vk = ash::vk::MemoryRequirements2::default();
1117         let mut memory_dedicated_requirements_vk = None;
1118 
1119         if device.api_version() >= Version::V1_1
1120             || device.enabled_extensions().khr_dedicated_allocation
1121         {
1122             debug_assert!(
1123                 device.api_version() >= Version::V1_1
1124                     || device.enabled_extensions().khr_get_memory_requirements2
1125             );
1126 
1127             let next = memory_dedicated_requirements_vk
1128                 .insert(ash::vk::MemoryDedicatedRequirements::default());
1129 
1130             next.p_next = memory_requirements2_vk.p_next;
1131             memory_requirements2_vk.p_next = next as *mut _ as *mut _;
1132         }
1133 
1134         unsafe {
1135             let fns = device.fns();
1136 
1137             if device.api_version() >= Version::V1_1
1138                 || device.enabled_extensions().khr_get_memory_requirements2
1139             {
1140                 if device.api_version() >= Version::V1_1 {
1141                     (fns.v1_1.get_image_memory_requirements2)(
1142                         device.handle(),
1143                         &info_vk,
1144                         &mut memory_requirements2_vk,
1145                     );
1146                 } else {
1147                     (fns.khr_get_memory_requirements2
1148                         .get_image_memory_requirements2_khr)(
1149                         device.handle(),
1150                         &info_vk,
1151                         &mut memory_requirements2_vk,
1152                     );
1153                 }
1154             } else {
1155                 (fns.v1_0.get_image_memory_requirements)(
1156                     device.handle(),
1157                     handle,
1158                     &mut memory_requirements2_vk.memory_requirements,
1159                 );
1160             }
1161         }
1162 
1163         MemoryRequirements {
1164             layout: DeviceLayout::from_size_alignment(
1165                 memory_requirements2_vk.memory_requirements.size,
1166                 memory_requirements2_vk.memory_requirements.alignment,
1167             )
1168             .unwrap(),
1169             memory_type_bits: memory_requirements2_vk.memory_requirements.memory_type_bits,
1170             prefers_dedicated_allocation: memory_dedicated_requirements_vk
1171                 .map_or(false, |dreqs| dreqs.prefers_dedicated_allocation != 0),
1172             requires_dedicated_allocation: memory_dedicated_requirements_vk
1173                 .map_or(false, |dreqs| dreqs.requires_dedicated_allocation != 0),
1174         }
1175     }
1176 
1177     #[inline]
1178     #[allow(dead_code)] // Remove when sparse memory is implemented
get_sparse_memory_requirements(&self) -> Vec<SparseImageMemoryRequirements>1179     fn get_sparse_memory_requirements(&self) -> Vec<SparseImageMemoryRequirements> {
1180         let device = &self.device;
1181 
1182         unsafe {
1183             let fns = self.device.fns();
1184 
1185             if device.api_version() >= Version::V1_1
1186                 || device.enabled_extensions().khr_get_memory_requirements2
1187             {
1188                 let info2 = ash::vk::ImageSparseMemoryRequirementsInfo2 {
1189                     image: self.handle,
1190                     ..Default::default()
1191                 };
1192 
1193                 let mut count = 0;
1194 
1195                 if device.api_version() >= Version::V1_1 {
1196                     (fns.v1_1.get_image_sparse_memory_requirements2)(
1197                         device.handle(),
1198                         &info2,
1199                         &mut count,
1200                         ptr::null_mut(),
1201                     );
1202                 } else {
1203                     (fns.khr_get_memory_requirements2
1204                         .get_image_sparse_memory_requirements2_khr)(
1205                         device.handle(),
1206                         &info2,
1207                         &mut count,
1208                         ptr::null_mut(),
1209                     );
1210                 }
1211 
1212                 let mut sparse_image_memory_requirements2 =
1213                     vec![ash::vk::SparseImageMemoryRequirements2::default(); count as usize];
1214 
1215                 if device.api_version() >= Version::V1_1 {
1216                     (fns.v1_1.get_image_sparse_memory_requirements2)(
1217                         self.device.handle(),
1218                         &info2,
1219                         &mut count,
1220                         sparse_image_memory_requirements2.as_mut_ptr(),
1221                     );
1222                 } else {
1223                     (fns.khr_get_memory_requirements2
1224                         .get_image_sparse_memory_requirements2_khr)(
1225                         self.device.handle(),
1226                         &info2,
1227                         &mut count,
1228                         sparse_image_memory_requirements2.as_mut_ptr(),
1229                     );
1230                 }
1231 
1232                 sparse_image_memory_requirements2.set_len(count as usize);
1233 
1234                 sparse_image_memory_requirements2
1235                     .into_iter()
1236                     .map(
1237                         |sparse_image_memory_requirements2| SparseImageMemoryRequirements {
1238                             format_properties: SparseImageFormatProperties {
1239                                 aspects: sparse_image_memory_requirements2
1240                                     .memory_requirements
1241                                     .format_properties
1242                                     .aspect_mask
1243                                     .into(),
1244                                 image_granularity: [
1245                                     sparse_image_memory_requirements2
1246                                         .memory_requirements
1247                                         .format_properties
1248                                         .image_granularity
1249                                         .width,
1250                                     sparse_image_memory_requirements2
1251                                         .memory_requirements
1252                                         .format_properties
1253                                         .image_granularity
1254                                         .height,
1255                                     sparse_image_memory_requirements2
1256                                         .memory_requirements
1257                                         .format_properties
1258                                         .image_granularity
1259                                         .depth,
1260                                 ],
1261                                 flags: sparse_image_memory_requirements2
1262                                     .memory_requirements
1263                                     .format_properties
1264                                     .flags
1265                                     .into(),
1266                             },
1267                             image_mip_tail_first_lod: sparse_image_memory_requirements2
1268                                 .memory_requirements
1269                                 .image_mip_tail_first_lod,
1270                             image_mip_tail_size: sparse_image_memory_requirements2
1271                                 .memory_requirements
1272                                 .image_mip_tail_size,
1273                             image_mip_tail_offset: sparse_image_memory_requirements2
1274                                 .memory_requirements
1275                                 .image_mip_tail_offset,
1276                             image_mip_tail_stride: (!sparse_image_memory_requirements2
1277                                 .memory_requirements
1278                                 .format_properties
1279                                 .flags
1280                                 .intersects(ash::vk::SparseImageFormatFlags::SINGLE_MIPTAIL))
1281                             .then_some(
1282                                 sparse_image_memory_requirements2
1283                                     .memory_requirements
1284                                     .image_mip_tail_stride,
1285                             ),
1286                         },
1287                     )
1288                     .collect()
1289             } else {
1290                 let mut count = 0;
1291 
1292                 (fns.v1_0.get_image_sparse_memory_requirements)(
1293                     device.handle(),
1294                     self.handle,
1295                     &mut count,
1296                     ptr::null_mut(),
1297                 );
1298 
1299                 let mut sparse_image_memory_requirements =
1300                     vec![ash::vk::SparseImageMemoryRequirements::default(); count as usize];
1301 
1302                 (fns.v1_0.get_image_sparse_memory_requirements)(
1303                     device.handle(),
1304                     self.handle,
1305                     &mut count,
1306                     sparse_image_memory_requirements.as_mut_ptr(),
1307                 );
1308 
1309                 sparse_image_memory_requirements.set_len(count as usize);
1310 
1311                 sparse_image_memory_requirements
1312                     .into_iter()
1313                     .map(
1314                         |sparse_image_memory_requirements| SparseImageMemoryRequirements {
1315                             format_properties: SparseImageFormatProperties {
1316                                 aspects: sparse_image_memory_requirements
1317                                     .format_properties
1318                                     .aspect_mask
1319                                     .into(),
1320                                 image_granularity: [
1321                                     sparse_image_memory_requirements
1322                                         .format_properties
1323                                         .image_granularity
1324                                         .width,
1325                                     sparse_image_memory_requirements
1326                                         .format_properties
1327                                         .image_granularity
1328                                         .height,
1329                                     sparse_image_memory_requirements
1330                                         .format_properties
1331                                         .image_granularity
1332                                         .depth,
1333                                 ],
1334                                 flags: sparse_image_memory_requirements
1335                                     .format_properties
1336                                     .flags
1337                                     .into(),
1338                             },
1339                             image_mip_tail_first_lod: sparse_image_memory_requirements
1340                                 .image_mip_tail_first_lod,
1341                             image_mip_tail_size: sparse_image_memory_requirements
1342                                 .image_mip_tail_size,
1343                             image_mip_tail_offset: sparse_image_memory_requirements
1344                                 .image_mip_tail_offset,
1345                             image_mip_tail_stride: (!sparse_image_memory_requirements
1346                                 .format_properties
1347                                 .flags
1348                                 .intersects(ash::vk::SparseImageFormatFlags::SINGLE_MIPTAIL))
1349                             .then_some(sparse_image_memory_requirements.image_mip_tail_stride),
1350                         },
1351                     )
1352                     .collect()
1353             }
1354         }
1355     }
1356 
id(&self) -> NonZeroU641357     pub(crate) fn id(&self) -> NonZeroU64 {
1358         self.id
1359     }
1360 
1361     /// Binds device memory to this image.
1362     ///
1363     /// - If `self.flags().disjoint` is not set, then `allocations` must contain exactly one
1364     ///   element. This element may be a dedicated allocation.
1365     /// - If `self.flags().disjoint` is set, then `allocations` must contain exactly
1366     ///   `self.format().unwrap().planes().len()` elements. These elements must not be dedicated
1367     ///   allocations.
bind_memory( self, allocations: impl IntoIterator<Item = MemoryAlloc>, ) -> Result< Image, ( ImageError, RawImage, impl ExactSizeIterator<Item = MemoryAlloc>, ), >1368     pub fn bind_memory(
1369         self,
1370         allocations: impl IntoIterator<Item = MemoryAlloc>,
1371     ) -> Result<
1372         Image,
1373         (
1374             ImageError,
1375             RawImage,
1376             impl ExactSizeIterator<Item = MemoryAlloc>,
1377         ),
1378     > {
1379         let allocations: SmallVec<[_; 3]> = allocations.into_iter().collect();
1380 
1381         if let Err(err) = self.validate_bind_memory(&allocations) {
1382             return Err((err, self, allocations.into_iter()));
1383         }
1384 
1385         unsafe { self.bind_memory_unchecked(allocations) }.map_err(|(err, image, allocations)| {
1386             (
1387                 err.into(),
1388                 image,
1389                 allocations
1390                     .into_iter()
1391                     .collect::<SmallVec<[_; 3]>>()
1392                     .into_iter(),
1393             )
1394         })
1395     }
1396 
validate_bind_memory(&self, allocations: &[MemoryAlloc]) -> Result<(), ImageError>1397     fn validate_bind_memory(&self, allocations: &[MemoryAlloc]) -> Result<(), ImageError> {
1398         if self.flags.intersects(ImageCreateFlags::DISJOINT) {
1399             if allocations.len() != self.format.unwrap().planes().len() {
1400                 return Err(ImageError::AllocationsWrongNumberOfElements {
1401                     provided: allocations.len(),
1402                     required: self.format.unwrap().planes().len(),
1403                 });
1404             }
1405         } else {
1406             if allocations.len() != 1 {
1407                 return Err(ImageError::AllocationsWrongNumberOfElements {
1408                     provided: allocations.len(),
1409                     required: 1,
1410                 });
1411             }
1412         }
1413 
1414         for (allocations_index, (allocation, memory_requirements)) in (allocations.iter())
1415             .zip(self.memory_requirements.iter())
1416             .enumerate()
1417         {
1418             assert_ne!(allocation.allocation_type(), AllocationType::Linear);
1419 
1420             let memory = allocation.device_memory();
1421             let memory_offset = allocation.offset();
1422             let memory_type = &self
1423                 .device
1424                 .physical_device()
1425                 .memory_properties()
1426                 .memory_types[memory.memory_type_index() as usize];
1427 
1428             // VUID-VkBindImageMemoryInfo-commonparent
1429             assert_eq!(self.device(), memory.device());
1430 
1431             // VUID-VkBindImageMemoryInfo-image-07460
1432             // Ensured by taking ownership of `RawImage`.
1433 
1434             // VUID-VkBindImageMemoryInfo-image-01045
1435             // Currently ensured by not having sparse binding flags, but this needs to be checked
1436             // once those are enabled.
1437 
1438             // VUID-VkBindImageMemoryInfo-memoryOffset-01046
1439             // Assume that `allocation` was created correctly.
1440 
1441             if let Some(dedicated_to) = memory.dedicated_to() {
1442                 // VUID-VkBindImageMemoryInfo-memory-02628
1443                 match dedicated_to {
1444                     DedicatedTo::Image(id) if id == self.id => {}
1445                     _ => return Err(ImageError::DedicatedAllocationMismatch),
1446                 }
1447                 debug_assert!(memory_offset == 0); // This should be ensured by the allocator
1448             } else {
1449                 // VUID-VkBindImageMemoryInfo-image-01445
1450                 if memory_requirements.requires_dedicated_allocation {
1451                     return Err(ImageError::DedicatedAllocationRequired);
1452                 }
1453             }
1454 
1455             // VUID-VkBindImageMemoryInfo-None-01901
1456             if memory_type
1457                 .property_flags
1458                 .intersects(MemoryPropertyFlags::PROTECTED)
1459             {
1460                 return Err(ImageError::MemoryProtectedMismatch {
1461                     allocations_index,
1462                     image_protected: false,
1463                     memory_protected: true,
1464                 });
1465             }
1466 
1467             // VUID-VkBindImageMemoryInfo-memory-02728
1468             if !memory.export_handle_types().is_empty()
1469                 && !memory
1470                     .export_handle_types()
1471                     .intersects(self.external_memory_handle_types)
1472             {
1473                 return Err(ImageError::MemoryExternalHandleTypesDisjoint {
1474                     allocations_index,
1475                     image_handle_types: self.external_memory_handle_types,
1476                     memory_export_handle_types: memory.export_handle_types(),
1477                 });
1478             }
1479 
1480             if let Some(handle_type) = memory.imported_handle_type() {
1481                 // VUID-VkBindImageMemoryInfo-memory-02989
1482                 if !ExternalMemoryHandleTypes::from(handle_type)
1483                     .intersects(self.external_memory_handle_types)
1484                 {
1485                     return Err(ImageError::MemoryImportedHandleTypeNotEnabled {
1486                         allocations_index,
1487                         image_handle_types: self.external_memory_handle_types,
1488                         memory_imported_handle_type: handle_type,
1489                     });
1490                 }
1491             }
1492 
1493             // VUID-VkBindImageMemoryInfo-pNext-01615
1494             // VUID-VkBindImageMemoryInfo-pNext-01619
1495             if memory_requirements.memory_type_bits & (1 << memory.memory_type_index()) == 0 {
1496                 return Err(ImageError::MemoryTypeNotAllowed {
1497                     allocations_index,
1498                     provided_memory_type_index: memory.memory_type_index(),
1499                     allowed_memory_type_bits: memory_requirements.memory_type_bits,
1500                 });
1501             }
1502 
1503             // VUID-VkBindImageMemoryInfo-pNext-01616
1504             // VUID-VkBindImageMemoryInfo-pNext-01620
1505             if !is_aligned(memory_offset, memory_requirements.layout.alignment()) {
1506                 return Err(ImageError::MemoryAllocationNotAligned {
1507                     allocations_index,
1508                     allocation_offset: memory_offset,
1509                     required_alignment: memory_requirements.layout.alignment(),
1510                 });
1511             }
1512 
1513             // VUID-VkBindImageMemoryInfo-pNext-01617
1514             // VUID-VkBindImageMemoryInfo-pNext-01621
1515             if allocation.size() < memory_requirements.layout.size() {
1516                 return Err(ImageError::MemoryAllocationTooSmall {
1517                     allocations_index,
1518                     allocation_size: allocation.size(),
1519                     required_size: memory_requirements.layout.size(),
1520                 });
1521             }
1522         }
1523 
1524         Ok(())
1525     }
1526 
1527     /// # Safety
1528     ///
1529     /// - If `self.flags().disjoint` is not set, then `allocations` must contain exactly one
1530     ///   element.
1531     /// - If `self.flags().disjoint` is set, then `allocations` must contain exactly
1532     ///   `self.format().unwrap().planes().len()` elements.
1533     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
bind_memory_unchecked( self, allocations: impl IntoIterator<Item = MemoryAlloc>, ) -> Result< Image, ( VulkanError, RawImage, impl ExactSizeIterator<Item = MemoryAlloc>, ), >1534     pub unsafe fn bind_memory_unchecked(
1535         self,
1536         allocations: impl IntoIterator<Item = MemoryAlloc>,
1537     ) -> Result<
1538         Image,
1539         (
1540             VulkanError,
1541             RawImage,
1542             impl ExactSizeIterator<Item = MemoryAlloc>,
1543         ),
1544     > {
1545         let allocations: SmallVec<[_; 3]> = allocations.into_iter().collect();
1546         let fns = self.device.fns();
1547 
1548         let result = if self.device.api_version() >= Version::V1_1
1549             || self.device.enabled_extensions().khr_bind_memory2
1550         {
1551             let mut infos_vk: SmallVec<[_; 3]> = SmallVec::with_capacity(3);
1552             let mut plane_infos_vk: SmallVec<[_; 3]> = SmallVec::with_capacity(3);
1553 
1554             if self.flags.intersects(ImageCreateFlags::DISJOINT) {
1555                 debug_assert_eq!(allocations.len(), self.format.unwrap().planes().len());
1556 
1557                 for (plane, allocation) in allocations.iter().enumerate() {
1558                     let memory = allocation.device_memory();
1559                     let memory_offset = allocation.offset();
1560 
1561                     infos_vk.push(ash::vk::BindImageMemoryInfo {
1562                         image: self.handle,
1563                         memory: memory.handle(),
1564                         memory_offset,
1565                         ..Default::default()
1566                     });
1567                     // VUID-VkBindImageMemoryInfo-pNext-01618
1568                     plane_infos_vk.push(ash::vk::BindImagePlaneMemoryInfo {
1569                         plane_aspect: match plane {
1570                             0 => ash::vk::ImageAspectFlags::PLANE_0,
1571                             1 => ash::vk::ImageAspectFlags::PLANE_1,
1572                             2 => ash::vk::ImageAspectFlags::PLANE_2,
1573                             _ => unreachable!(),
1574                         },
1575                         ..Default::default()
1576                     });
1577                 }
1578             } else {
1579                 debug_assert_eq!(allocations.len(), 1);
1580 
1581                 let allocation = &allocations[0];
1582                 let memory = allocation.device_memory();
1583                 let memory_offset = allocation.offset();
1584 
1585                 infos_vk.push(ash::vk::BindImageMemoryInfo {
1586                     image: self.handle,
1587                     memory: memory.handle(),
1588                     memory_offset,
1589                     ..Default::default()
1590                 });
1591             };
1592 
1593             for (info_vk, plane_info_vk) in (infos_vk.iter_mut()).zip(plane_infos_vk.iter_mut()) {
1594                 info_vk.p_next = plane_info_vk as *mut _ as *mut _;
1595             }
1596 
1597             if self.device.api_version() >= Version::V1_1 {
1598                 (fns.v1_1.bind_image_memory2)(
1599                     self.device.handle(),
1600                     infos_vk.len() as u32,
1601                     infos_vk.as_ptr(),
1602                 )
1603             } else {
1604                 (fns.khr_bind_memory2.bind_image_memory2_khr)(
1605                     self.device.handle(),
1606                     infos_vk.len() as u32,
1607                     infos_vk.as_ptr(),
1608                 )
1609             }
1610         } else {
1611             debug_assert_eq!(allocations.len(), 1);
1612 
1613             let allocation = &allocations[0];
1614             let memory = allocation.device_memory();
1615             let memory_offset = allocation.offset();
1616 
1617             (fns.v1_0.bind_image_memory)(
1618                 self.device.handle(),
1619                 self.handle,
1620                 memory.handle(),
1621                 memory_offset,
1622             )
1623         }
1624         .result();
1625 
1626         if let Err(err) = result {
1627             return Err((VulkanError::from(err), self, allocations.into_iter()));
1628         }
1629 
1630         Ok(Image::from_raw(self, ImageMemory::Normal(allocations)))
1631     }
1632 
1633     /// Returns the memory requirements for this image.
1634     ///
1635     /// - If the image is a swapchain image, this returns a slice with a length of 0.
1636     /// - If `self.flags().disjoint` is not set, this returns a slice with a length of 1.
1637     /// - If `self.flags().disjoint` is set, this returns a slice with a length equal to
1638     ///   `self.format().unwrap().planes().len()`.
1639     #[inline]
memory_requirements(&self) -> &[MemoryRequirements]1640     pub fn memory_requirements(&self) -> &[MemoryRequirements] {
1641         &self.memory_requirements
1642     }
1643 
1644     /// Returns the flags the image was created with.
1645     #[inline]
flags(&self) -> ImageCreateFlags1646     pub fn flags(&self) -> ImageCreateFlags {
1647         self.flags
1648     }
1649 
1650     /// Returns the dimensions of the image.
1651     #[inline]
dimensions(&self) -> ImageDimensions1652     pub fn dimensions(&self) -> ImageDimensions {
1653         self.dimensions
1654     }
1655 
1656     /// Returns the image's format.
1657     #[inline]
format(&self) -> Option<Format>1658     pub fn format(&self) -> Option<Format> {
1659         self.format
1660     }
1661 
1662     /// Returns the features supported by the image's format.
1663     #[inline]
format_features(&self) -> FormatFeatures1664     pub fn format_features(&self) -> FormatFeatures {
1665         self.format_features
1666     }
1667 
1668     /// Returns the number of mipmap levels in the image.
1669     #[inline]
mip_levels(&self) -> u321670     pub fn mip_levels(&self) -> u32 {
1671         self.mip_levels
1672     }
1673 
1674     /// Returns the initial layout of the image.
1675     #[inline]
initial_layout(&self) -> ImageLayout1676     pub fn initial_layout(&self) -> ImageLayout {
1677         self.initial_layout
1678     }
1679 
1680     /// Returns the number of samples for the image.
1681     #[inline]
samples(&self) -> SampleCount1682     pub fn samples(&self) -> SampleCount {
1683         self.samples
1684     }
1685 
1686     /// Returns the tiling of the image.
1687     #[inline]
tiling(&self) -> ImageTiling1688     pub fn tiling(&self) -> ImageTiling {
1689         self.tiling
1690     }
1691 
1692     /// Returns the usage the image was created with.
1693     #[inline]
usage(&self) -> ImageUsage1694     pub fn usage(&self) -> ImageUsage {
1695         self.usage
1696     }
1697 
1698     /// Returns the stencil usage the image was created with.
1699     #[inline]
stencil_usage(&self) -> ImageUsage1700     pub fn stencil_usage(&self) -> ImageUsage {
1701         self.stencil_usage
1702     }
1703 
1704     /// Returns the sharing the image was created with.
1705     #[inline]
sharing(&self) -> &Sharing<SmallVec<[u32; 4]>>1706     pub fn sharing(&self) -> &Sharing<SmallVec<[u32; 4]>> {
1707         &self.sharing
1708     }
1709 
1710     /// Returns the external memory handle types that are supported with this image.
1711     #[inline]
external_memory_handle_types(&self) -> ExternalMemoryHandleTypes1712     pub fn external_memory_handle_types(&self) -> ExternalMemoryHandleTypes {
1713         self.external_memory_handle_types
1714     }
1715 
1716     /// Returns an `ImageSubresourceLayers` covering the first mip level of the image. All aspects
1717     /// of the image are selected, or `plane0` if the image is multi-planar.
1718     #[inline]
subresource_layers(&self) -> ImageSubresourceLayers1719     pub fn subresource_layers(&self) -> ImageSubresourceLayers {
1720         ImageSubresourceLayers {
1721             aspects: {
1722                 let aspects = self.format.unwrap().aspects();
1723 
1724                 if aspects.intersects(ImageAspects::PLANE_0) {
1725                     ImageAspects::PLANE_0
1726                 } else {
1727                     aspects
1728                 }
1729             },
1730             mip_level: 0,
1731             array_layers: 0..self.dimensions.array_layers(),
1732         }
1733     }
1734 
1735     /// Returns an `ImageSubresourceRange` covering the whole image. If the image is multi-planar,
1736     /// only the `color` aspect is selected.
1737     #[inline]
subresource_range(&self) -> ImageSubresourceRange1738     pub fn subresource_range(&self) -> ImageSubresourceRange {
1739         ImageSubresourceRange {
1740             aspects: self.format.unwrap().aspects()
1741                 - (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2),
1742             mip_levels: 0..self.mip_levels,
1743             array_layers: 0..self.dimensions.array_layers(),
1744         }
1745     }
1746 
1747     /// Queries the memory layout of a single subresource of the image.
1748     ///
1749     /// Only images with linear tiling are supported, if they do not have a format with both a
1750     /// depth and a stencil format. Images with optimal tiling have an opaque image layout that is
1751     /// not suitable for direct memory accesses, and likewise for combined depth/stencil formats.
1752     /// Multi-planar formats are supported, but you must specify one of the planes as the `aspect`,
1753     /// not [`ImageAspect::Color`].
1754     ///
1755     /// The results of this function are cached, so that future calls with the same arguments
1756     /// do not need to make a call to the Vulkan API again.
subresource_layout( &self, aspect: ImageAspect, mip_level: u32, array_layer: u32, ) -> Result<SubresourceLayout, ImageError>1757     pub fn subresource_layout(
1758         &self,
1759         aspect: ImageAspect,
1760         mip_level: u32,
1761         array_layer: u32,
1762     ) -> Result<SubresourceLayout, ImageError> {
1763         self.validate_subresource_layout(aspect, mip_level, array_layer)?;
1764 
1765         unsafe { Ok(self.subresource_layout_unchecked(aspect, mip_level, array_layer)) }
1766     }
1767 
validate_subresource_layout( &self, aspect: ImageAspect, mip_level: u32, array_layer: u32, ) -> Result<(), ImageError>1768     fn validate_subresource_layout(
1769         &self,
1770         aspect: ImageAspect,
1771         mip_level: u32,
1772         array_layer: u32,
1773     ) -> Result<(), ImageError> {
1774         // VUID-VkImageSubresource-aspectMask-parameter
1775         aspect.validate_device(&self.device)?;
1776 
1777         // VUID-VkImageSubresource-aspectMask-requiredbitmask
1778         // VUID-vkGetImageSubresourceLayout-aspectMask-00997
1779         // Ensured by use of enum `ImageAspect`.
1780 
1781         // VUID-vkGetImageSubresourceLayout-image-02270
1782         if !matches!(
1783             self.tiling,
1784             ImageTiling::DrmFormatModifier | ImageTiling::Linear
1785         ) {
1786             return Err(ImageError::OptimalTilingNotSupported);
1787         }
1788 
1789         // VUID-vkGetImageSubresourceLayout-mipLevel-01716
1790         if mip_level >= self.mip_levels {
1791             return Err(ImageError::MipLevelOutOfRange {
1792                 provided_mip_level: mip_level,
1793                 image_mip_levels: self.mip_levels,
1794             });
1795         }
1796 
1797         // VUID-vkGetImageSubresourceLayout-arrayLayer-01717
1798         if array_layer >= self.dimensions.array_layers() {
1799             return Err(ImageError::ArrayLayerOutOfRange {
1800                 provided_array_layer: array_layer,
1801                 image_array_layers: self.dimensions.array_layers(),
1802             });
1803         }
1804 
1805         let mut allowed_aspects = self.format.unwrap().aspects();
1806 
1807         // Follows from the combination of these three VUIDs. See:
1808         // https://github.com/KhronosGroup/Vulkan-Docs/issues/1942
1809         // VUID-vkGetImageSubresourceLayout-aspectMask-00997
1810         // VUID-vkGetImageSubresourceLayout-format-04462
1811         // VUID-vkGetImageSubresourceLayout-format-04463
1812         if allowed_aspects.contains(ImageAspects::DEPTH | ImageAspects::STENCIL) {
1813             return Err(ImageError::DepthStencilFormatsNotSupported);
1814         }
1815 
1816         if allowed_aspects
1817             .intersects(ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2)
1818         {
1819             allowed_aspects -= ImageAspects::COLOR;
1820         }
1821 
1822         // TODO:  VUID-vkGetImageSubresourceLayout-tiling-02271
1823         //if self.tiling == ImageTiling::DrmFormatModifier {
1824         // Only one-plane image importing is possible for now.
1825         //}
1826 
1827         // VUID-vkGetImageSubresourceLayout-format-04461
1828         // VUID-vkGetImageSubresourceLayout-format-04462
1829         // VUID-vkGetImageSubresourceLayout-format-04463
1830         // VUID-vkGetImageSubresourceLayout-format-04464
1831         // VUID-vkGetImageSubresourceLayout-format-01581
1832         // VUID-vkGetImageSubresourceLayout-format-01582
1833         if !allowed_aspects.contains(aspect.into()) {
1834             return Err(ImageError::AspectNotAllowed {
1835                 provided_aspect: aspect,
1836                 allowed_aspects,
1837             });
1838         }
1839 
1840         Ok(())
1841     }
1842 
1843     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
subresource_layout_unchecked( &self, aspect: ImageAspect, mip_level: u32, array_layer: u32, ) -> SubresourceLayout1844     pub unsafe fn subresource_layout_unchecked(
1845         &self,
1846         aspect: ImageAspect,
1847         mip_level: u32,
1848         array_layer: u32,
1849     ) -> SubresourceLayout {
1850         self.subresource_layout.get_or_insert(
1851             (aspect, mip_level, array_layer),
1852             |&(aspect, mip_level, array_layer)| {
1853                 let fns = self.device.fns();
1854 
1855                 let subresource = ash::vk::ImageSubresource {
1856                     aspect_mask: aspect.into(),
1857                     mip_level,
1858                     array_layer,
1859                 };
1860 
1861                 let mut output = MaybeUninit::uninit();
1862                 (fns.v1_0.get_image_subresource_layout)(
1863                     self.device.handle(),
1864                     self.handle,
1865                     &subresource,
1866                     output.as_mut_ptr(),
1867                 );
1868                 let output = output.assume_init();
1869 
1870                 SubresourceLayout {
1871                     offset: output.offset,
1872                     size: output.size,
1873                     row_pitch: output.row_pitch,
1874                     array_pitch: (self.dimensions.array_layers() > 1).then_some(output.array_pitch),
1875                     depth_pitch: matches!(self.dimensions, ImageDimensions::Dim3d { .. })
1876                         .then_some(output.depth_pitch),
1877                 }
1878             },
1879         )
1880     }
1881 }
1882 
1883 impl Drop for RawImage {
1884     #[inline]
drop(&mut self)1885     fn drop(&mut self) {
1886         if !self.needs_destruction {
1887             return;
1888         }
1889 
1890         unsafe {
1891             let fns = self.device.fns();
1892             (fns.v1_0.destroy_image)(self.device.handle(), self.handle, ptr::null());
1893         }
1894     }
1895 }
1896 
1897 unsafe impl VulkanObject for RawImage {
1898     type Handle = ash::vk::Image;
1899 
1900     #[inline]
handle(&self) -> Self::Handle1901     fn handle(&self) -> Self::Handle {
1902         self.handle
1903     }
1904 }
1905 
1906 unsafe impl DeviceOwned for RawImage {
1907     #[inline]
device(&self) -> &Arc<Device>1908     fn device(&self) -> &Arc<Device> {
1909         &self.device
1910     }
1911 }
1912 
1913 impl_id_counter!(RawImage);
1914 
1915 /// Parameters to create a new `Image`.
1916 #[derive(Clone, Debug)]
1917 pub struct ImageCreateInfo {
1918     /// Flags to enable.
1919     ///
1920     /// The default value is [`ImageCreateFlags::empty()`].
1921     pub flags: ImageCreateFlags,
1922 
1923     /// The type, extent and number of array layers to create the image with.
1924     ///
1925     /// On [portability subset](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag)
1926     /// devices, if `samples` is not [`SampleCount::Sample1`] and `dimensions.array_layers()` is
1927     /// not 1, the [`multisample_array_image`](crate::device::Features::multisample_array_image)
1928     /// feature must be enabled on the device.
1929     ///
1930     /// The default value is `ImageDimensions::Dim2d { width: 0, height: 0, array_layers: 1 }`,
1931     /// which must be overridden.
1932     pub dimensions: ImageDimensions,
1933 
1934     /// The format used to store the image data.
1935     ///
1936     /// The default value is `None`, which must be overridden.
1937     pub format: Option<Format>,
1938 
1939     /// The number of mip levels to create the image with.
1940     ///
1941     /// The default value is `1`.
1942     pub mip_levels: u32,
1943 
1944     /// The number of samples per texel that the image should use.
1945     ///
1946     /// On [portability subset](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag)
1947     /// devices, if `samples` is not [`SampleCount::Sample1`] and `dimensions.array_layers()` is
1948     /// not 1, the [`multisample_array_image`](crate::device::Features::multisample_array_image)
1949     /// feature must be enabled on the device.
1950     ///
1951     /// The default value is [`SampleCount::Sample1`].
1952     pub samples: SampleCount,
1953 
1954     /// The memory arrangement of the texel blocks.
1955     ///
1956     /// The default value is [`ImageTiling::Optimal`].
1957     pub tiling: ImageTiling,
1958 
1959     /// How the image is going to be used.
1960     ///
1961     /// The default value is [`ImageUsage::empty()`], which must be overridden.
1962     pub usage: ImageUsage,
1963 
1964     /// How the stencil aspect of the image is going to be used, if any.
1965     ///
1966     /// If `stencil_usage` is empty or if `format` does not have both a depth and a stencil aspect,
1967     /// then it is automatically set to equal `usage`.
1968     ///
1969     /// If after this, `stencil_usage` does not equal `usage`,
1970     /// then the device API version must be at least 1.2, or the
1971     /// [`ext_separate_stencil_usage`](crate::device::DeviceExtensions::ext_separate_stencil_usage)
1972     /// extension must be enabled on the device.
1973     ///
1974     /// The default value is [`ImageUsage::empty()`].
1975     pub stencil_usage: ImageUsage,
1976 
1977     /// Whether the image can be shared across multiple queues, or is limited to a single queue.
1978     ///
1979     /// The default value is [`Sharing::Exclusive`].
1980     pub sharing: Sharing<SmallVec<[u32; 4]>>,
1981 
1982     /// The image layout that the image will have when it is created.
1983     ///
1984     /// The default value is [`ImageLayout::Undefined`].
1985     pub initial_layout: ImageLayout,
1986 
1987     /// The external memory handle types that are going to be used with the image.
1988     ///
1989     /// If any of the fields in this value are set, the device must either support API version 1.1
1990     /// or the [`khr_external_memory`](crate::device::DeviceExtensions::khr_external_memory)
1991     /// extension must be enabled, and `initial_layout` must be set to
1992     /// [`ImageLayout::Undefined`].
1993     ///
1994     /// The default value is [`ExternalMemoryHandleTypes::empty()`].
1995     pub external_memory_handle_types: ExternalMemoryHandleTypes,
1996 
1997     /// Specify that an image be created with the provided DRM format modifier and explicit memory layout
1998     pub image_drm_format_modifier_create_info: Option<ImageDrmFormatModifierExplicitCreateInfoEXT>,
1999 
2000     pub _ne: crate::NonExhaustive,
2001 }
2002 
2003 impl Default for ImageCreateInfo {
2004     #[inline]
default() -> Self2005     fn default() -> Self {
2006         Self {
2007             flags: ImageCreateFlags::empty(),
2008             dimensions: ImageDimensions::Dim2d {
2009                 width: 0,
2010                 height: 0,
2011                 array_layers: 1,
2012             },
2013             format: None,
2014             mip_levels: 1,
2015             samples: SampleCount::Sample1,
2016             tiling: ImageTiling::Optimal,
2017             usage: ImageUsage::empty(),
2018             stencil_usage: ImageUsage::empty(),
2019             sharing: Sharing::Exclusive,
2020             initial_layout: ImageLayout::Undefined,
2021             external_memory_handle_types: ExternalMemoryHandleTypes::empty(),
2022             image_drm_format_modifier_create_info: None,
2023             _ne: crate::NonExhaustive(()),
2024         }
2025     }
2026 }
2027 
2028 /// A multi-dimensioned storage for texel data.
2029 ///
2030 /// Unlike [`RawImage`], an `Image` has memory backing it, and can be used normally.
2031 #[derive(Debug)]
2032 pub struct Image {
2033     inner: RawImage,
2034     memory: ImageMemory,
2035 
2036     aspect_list: SmallVec<[ImageAspect; 4]>,
2037     aspect_size: DeviceSize,
2038     mip_level_size: DeviceSize,
2039     range_size: DeviceSize,
2040     state: Mutex<ImageState>,
2041 }
2042 
2043 /// The type of backing memory that an image can have.
2044 #[derive(Debug)]
2045 pub enum ImageMemory {
2046     /// The image is backed by normal memory, bound with [`bind_memory`].
2047     ///
2048     /// [`bind_memory`]: RawImage::bind_memory
2049     Normal(SmallVec<[MemoryAlloc; 3]>),
2050 
2051     /// The image is backed by sparse memory, bound with [`bind_sparse`].
2052     ///
2053     /// [`bind_sparse`]: crate::device::QueueGuard::bind_sparse
2054     Sparse(Vec<SparseImageMemoryRequirements>),
2055 
2056     /// The image is backed by memory owned by a [`Swapchain`].
2057     Swapchain {
2058         swapchain: Arc<Swapchain>,
2059         image_index: u32,
2060     },
2061 }
2062 
2063 impl Image {
from_raw(inner: RawImage, memory: ImageMemory) -> Self2064     fn from_raw(inner: RawImage, memory: ImageMemory) -> Self {
2065         let aspects = inner.format.unwrap().aspects();
2066         let aspect_list: SmallVec<[ImageAspect; 4]> = aspects.into_iter().collect();
2067         let mip_level_size = inner.dimensions.array_layers() as DeviceSize;
2068         let aspect_size = mip_level_size * inner.mip_levels as DeviceSize;
2069         let range_size = aspect_list.len() as DeviceSize * aspect_size;
2070         let state = Mutex::new(ImageState::new(range_size, inner.initial_layout));
2071 
2072         Image {
2073             inner,
2074             memory,
2075 
2076             aspect_list,
2077             aspect_size,
2078             mip_level_size,
2079             range_size,
2080             state,
2081         }
2082     }
2083 
from_swapchain( handle: ash::vk::Image, swapchain: Arc<Swapchain>, image_index: u32, ) -> Self2084     pub(crate) unsafe fn from_swapchain(
2085         handle: ash::vk::Image,
2086         swapchain: Arc<Swapchain>,
2087         image_index: u32,
2088     ) -> Self {
2089         let create_info = ImageCreateInfo {
2090             flags: ImageCreateFlags::empty(),
2091             dimensions: ImageDimensions::Dim2d {
2092                 width: swapchain.image_extent()[0],
2093                 height: swapchain.image_extent()[1],
2094                 array_layers: swapchain.image_array_layers(),
2095             },
2096             format: Some(swapchain.image_format()),
2097             initial_layout: ImageLayout::Undefined,
2098             mip_levels: 1,
2099             samples: SampleCount::Sample1,
2100             tiling: ImageTiling::Optimal,
2101             usage: swapchain.image_usage(),
2102             stencil_usage: swapchain.image_usage(),
2103             sharing: swapchain.image_sharing().clone(),
2104             ..Default::default()
2105         };
2106 
2107         Self::from_raw(
2108             RawImage::from_handle_with_destruction(
2109                 swapchain.device().clone(),
2110                 handle,
2111                 create_info,
2112                 false,
2113             ),
2114             ImageMemory::Swapchain {
2115                 swapchain,
2116                 image_index,
2117             },
2118         )
2119     }
2120 
2121     /// Returns the type of memory that is backing this image.
2122     #[inline]
memory(&self) -> &ImageMemory2123     pub fn memory(&self) -> &ImageMemory {
2124         &self.memory
2125     }
2126 
2127     /// Returns the memory requirements for this image.
2128     ///
2129     /// - If the image is a swapchain image, this returns a slice with a length of 0.
2130     /// - If `self.flags().disjoint` is not set, this returns a slice with a length of 1.
2131     /// - If `self.flags().disjoint` is set, this returns a slice with a length equal to
2132     ///   `self.format().unwrap().planes().len()`.
2133     #[inline]
memory_requirements(&self) -> &[MemoryRequirements]2134     pub fn memory_requirements(&self) -> &[MemoryRequirements] {
2135         &self.inner.memory_requirements
2136     }
2137 
2138     /// Returns the flags the image was created with.
2139     #[inline]
flags(&self) -> ImageCreateFlags2140     pub fn flags(&self) -> ImageCreateFlags {
2141         self.inner.flags
2142     }
2143 
2144     /// Returns the dimensions of the image.
2145     #[inline]
dimensions(&self) -> ImageDimensions2146     pub fn dimensions(&self) -> ImageDimensions {
2147         self.inner.dimensions
2148     }
2149 
2150     /// Returns the image's format.
2151     #[inline]
format(&self) -> Option<Format>2152     pub fn format(&self) -> Option<Format> {
2153         self.inner.format
2154     }
2155 
2156     /// Returns the features supported by the image's format.
2157     #[inline]
format_features(&self) -> FormatFeatures2158     pub fn format_features(&self) -> FormatFeatures {
2159         self.inner.format_features
2160     }
2161 
2162     /// Returns the number of mipmap levels in the image.
2163     #[inline]
mip_levels(&self) -> u322164     pub fn mip_levels(&self) -> u32 {
2165         self.inner.mip_levels
2166     }
2167 
2168     /// Returns the initial layout of the image.
2169     #[inline]
initial_layout(&self) -> ImageLayout2170     pub fn initial_layout(&self) -> ImageLayout {
2171         self.inner.initial_layout
2172     }
2173 
2174     /// Returns the number of samples for the image.
2175     #[inline]
samples(&self) -> SampleCount2176     pub fn samples(&self) -> SampleCount {
2177         self.inner.samples
2178     }
2179 
2180     /// Returns the tiling of the image.
2181     #[inline]
tiling(&self) -> ImageTiling2182     pub fn tiling(&self) -> ImageTiling {
2183         self.inner.tiling
2184     }
2185 
2186     /// Returns the usage the image was created with.
2187     #[inline]
usage(&self) -> ImageUsage2188     pub fn usage(&self) -> ImageUsage {
2189         self.inner.usage
2190     }
2191 
2192     /// Returns the stencil usage the image was created with.
2193     #[inline]
stencil_usage(&self) -> ImageUsage2194     pub fn stencil_usage(&self) -> ImageUsage {
2195         self.inner.stencil_usage
2196     }
2197 
2198     /// Returns the sharing the image was created with.
2199     #[inline]
sharing(&self) -> &Sharing<SmallVec<[u32; 4]>>2200     pub fn sharing(&self) -> &Sharing<SmallVec<[u32; 4]>> {
2201         &self.inner.sharing
2202     }
2203 
2204     /// Returns the external memory handle types that are supported with this image.
2205     #[inline]
external_memory_handle_types(&self) -> ExternalMemoryHandleTypes2206     pub fn external_memory_handle_types(&self) -> ExternalMemoryHandleTypes {
2207         self.inner.external_memory_handle_types
2208     }
2209 
2210     /// Returns an `ImageSubresourceLayers` covering the first mip level of the image. All aspects
2211     /// of the image are selected, or `plane0` if the image is multi-planar.
2212     #[inline]
subresource_layers(&self) -> ImageSubresourceLayers2213     pub fn subresource_layers(&self) -> ImageSubresourceLayers {
2214         self.inner.subresource_layers()
2215     }
2216 
2217     /// Returns an `ImageSubresourceRange` covering the whole image. If the image is multi-planar,
2218     /// only the `color` aspect is selected.
2219     #[inline]
subresource_range(&self) -> ImageSubresourceRange2220     pub fn subresource_range(&self) -> ImageSubresourceRange {
2221         self.inner.subresource_range()
2222     }
2223 
2224     /// Queries the memory layout of a single subresource of the image.
2225     ///
2226     /// Only images with linear tiling are supported, if they do not have a format with both a
2227     /// depth and a stencil format. Images with optimal tiling have an opaque image layout that is
2228     /// not suitable for direct memory accesses, and likewise for combined depth/stencil formats.
2229     /// Multi-planar formats are supported, but you must specify one of the planes as the `aspect`,
2230     /// not [`ImageAspect::Color`].
2231     ///
2232     /// The layout is invariant for each image. However it is not cached, as this would waste
2233     /// memory in the case of non-linear-tiling images. You are encouraged to store the layout
2234     /// somewhere in order to avoid calling this semi-expensive function at every single memory
2235     /// access.
2236     #[inline]
subresource_layout( &self, aspect: ImageAspect, mip_level: u32, array_layer: u32, ) -> Result<SubresourceLayout, ImageError>2237     pub fn subresource_layout(
2238         &self,
2239         aspect: ImageAspect,
2240         mip_level: u32,
2241         array_layer: u32,
2242     ) -> Result<SubresourceLayout, ImageError> {
2243         self.inner
2244             .subresource_layout(aspect, mip_level, array_layer)
2245     }
2246 
2247     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
2248     #[inline]
subresource_layout_unchecked( &self, aspect: ImageAspect, mip_level: u32, array_layer: u32, ) -> SubresourceLayout2249     pub unsafe fn subresource_layout_unchecked(
2250         &self,
2251         aspect: ImageAspect,
2252         mip_level: u32,
2253         array_layer: u32,
2254     ) -> SubresourceLayout {
2255         self.inner
2256             .subresource_layout_unchecked(aspect, mip_level, array_layer)
2257     }
2258 
range_size(&self) -> DeviceSize2259     pub(crate) fn range_size(&self) -> DeviceSize {
2260         self.range_size
2261     }
2262 
2263     /// Returns an iterator over subresource ranges.
2264     ///
2265     /// In ranges, the subresources are "flattened" to `DeviceSize`, where each index in the range
2266     /// is a single array layer. The layers are arranged hierarchically: aspects at the top level,
2267     /// with the mip levels in that aspect, and the array layers in that mip level.
iter_ranges( &self, subresource_range: ImageSubresourceRange, ) -> SubresourceRangeIterator2268     pub(crate) fn iter_ranges(
2269         &self,
2270         subresource_range: ImageSubresourceRange,
2271     ) -> SubresourceRangeIterator {
2272         assert!(self
2273             .format()
2274             .unwrap()
2275             .aspects()
2276             .contains(subresource_range.aspects));
2277         assert!(subresource_range.mip_levels.end <= self.inner.mip_levels);
2278         assert!(subresource_range.array_layers.end <= self.inner.dimensions.array_layers());
2279 
2280         SubresourceRangeIterator::new(
2281             subresource_range,
2282             &self.aspect_list,
2283             self.aspect_size,
2284             self.inner.mip_levels,
2285             self.mip_level_size,
2286             self.inner.dimensions.array_layers(),
2287         )
2288     }
2289 
range_to_subresources( &self, mut range: Range<DeviceSize>, ) -> ImageSubresourceRange2290     pub(crate) fn range_to_subresources(
2291         &self,
2292         mut range: Range<DeviceSize>,
2293     ) -> ImageSubresourceRange {
2294         debug_assert!(!range.is_empty());
2295         debug_assert!(range.end <= self.range_size);
2296 
2297         if range.end - range.start > self.aspect_size {
2298             debug_assert!(range.start % self.aspect_size == 0);
2299             debug_assert!(range.end % self.aspect_size == 0);
2300 
2301             let start_aspect_num = (range.start / self.aspect_size) as usize;
2302             let end_aspect_num = (range.end / self.aspect_size) as usize;
2303 
2304             ImageSubresourceRange {
2305                 aspects: self.aspect_list[start_aspect_num..end_aspect_num]
2306                     .iter()
2307                     .copied()
2308                     .collect(),
2309                 mip_levels: 0..self.inner.mip_levels,
2310                 array_layers: 0..self.inner.dimensions.array_layers(),
2311             }
2312         } else {
2313             let aspect_num = (range.start / self.aspect_size) as usize;
2314             range.start %= self.aspect_size;
2315             range.end %= self.aspect_size;
2316 
2317             // Wraparound
2318             if range.end == 0 {
2319                 range.end = self.aspect_size;
2320             }
2321 
2322             if range.end - range.start > self.mip_level_size {
2323                 debug_assert!(range.start % self.mip_level_size == 0);
2324                 debug_assert!(range.end % self.mip_level_size == 0);
2325 
2326                 let start_mip_level = (range.start / self.mip_level_size) as u32;
2327                 let end_mip_level = (range.end / self.mip_level_size) as u32;
2328 
2329                 ImageSubresourceRange {
2330                     aspects: self.aspect_list[aspect_num].into(),
2331                     mip_levels: start_mip_level..end_mip_level,
2332                     array_layers: 0..self.inner.dimensions.array_layers(),
2333                 }
2334             } else {
2335                 let mip_level = (range.start / self.mip_level_size) as u32;
2336                 range.start %= self.mip_level_size;
2337                 range.end %= self.mip_level_size;
2338 
2339                 // Wraparound
2340                 if range.end == 0 {
2341                     range.end = self.mip_level_size;
2342                 }
2343 
2344                 let start_array_layer = range.start as u32;
2345                 let end_array_layer = range.end as u32;
2346 
2347                 ImageSubresourceRange {
2348                     aspects: self.aspect_list[aspect_num].into(),
2349                     mip_levels: mip_level..mip_level + 1,
2350                     array_layers: start_array_layer..end_array_layer,
2351                 }
2352             }
2353         }
2354     }
2355 
state(&self) -> MutexGuard<'_, ImageState>2356     pub(crate) fn state(&self) -> MutexGuard<'_, ImageState> {
2357         self.state.lock()
2358     }
2359 }
2360 
2361 unsafe impl VulkanObject for Image {
2362     type Handle = ash::vk::Image;
2363 
2364     #[inline]
handle(&self) -> Self::Handle2365     fn handle(&self) -> Self::Handle {
2366         self.inner.handle
2367     }
2368 }
2369 
2370 unsafe impl DeviceOwned for Image {
2371     #[inline]
device(&self) -> &Arc<Device>2372     fn device(&self) -> &Arc<Device> {
2373         &self.inner.device
2374     }
2375 }
2376 
2377 impl PartialEq for Image {
2378     #[inline]
eq(&self, other: &Self) -> bool2379     fn eq(&self, other: &Self) -> bool {
2380         self.inner == other.inner
2381     }
2382 }
2383 
2384 impl Eq for Image {}
2385 
2386 impl Hash for Image {
hash<H: Hasher>(&self, state: &mut H)2387     fn hash<H: Hasher>(&self, state: &mut H) {
2388         self.inner.hash(state);
2389     }
2390 }
2391 
2392 /// The current state of an image.
2393 #[derive(Debug)]
2394 pub(crate) struct ImageState {
2395     ranges: RangeMap<DeviceSize, ImageRangeState>,
2396 }
2397 
2398 impl ImageState {
new(size: DeviceSize, initial_layout: ImageLayout) -> Self2399     fn new(size: DeviceSize, initial_layout: ImageLayout) -> Self {
2400         ImageState {
2401             ranges: [(
2402                 0..size,
2403                 ImageRangeState {
2404                     current_access: CurrentAccess::Shared {
2405                         cpu_reads: 0,
2406                         gpu_reads: 0,
2407                     },
2408                     layout: initial_layout,
2409                 },
2410             )]
2411             .into_iter()
2412             .collect(),
2413         }
2414     }
2415 
2416     #[allow(dead_code)]
check_cpu_read(&self, range: Range<DeviceSize>) -> Result<(), ReadLockError>2417     pub(crate) fn check_cpu_read(&self, range: Range<DeviceSize>) -> Result<(), ReadLockError> {
2418         for (_range, state) in self.ranges.range(&range) {
2419             match &state.current_access {
2420                 CurrentAccess::CpuExclusive { .. } => return Err(ReadLockError::CpuWriteLocked),
2421                 CurrentAccess::GpuExclusive { .. } => return Err(ReadLockError::GpuWriteLocked),
2422                 CurrentAccess::Shared { .. } => (),
2423             }
2424         }
2425 
2426         Ok(())
2427     }
2428 
2429     #[allow(dead_code)]
cpu_read_lock(&mut self, range: Range<DeviceSize>)2430     pub(crate) unsafe fn cpu_read_lock(&mut self, range: Range<DeviceSize>) {
2431         self.ranges.split_at(&range.start);
2432         self.ranges.split_at(&range.end);
2433 
2434         for (_range, state) in self.ranges.range_mut(&range) {
2435             match &mut state.current_access {
2436                 CurrentAccess::Shared { cpu_reads, .. } => {
2437                     *cpu_reads += 1;
2438                 }
2439                 _ => unreachable!("Image is being written by the CPU or GPU"),
2440             }
2441         }
2442     }
2443 
2444     #[allow(dead_code)]
cpu_read_unlock(&mut self, range: Range<DeviceSize>)2445     pub(crate) unsafe fn cpu_read_unlock(&mut self, range: Range<DeviceSize>) {
2446         self.ranges.split_at(&range.start);
2447         self.ranges.split_at(&range.end);
2448 
2449         for (_range, state) in self.ranges.range_mut(&range) {
2450             match &mut state.current_access {
2451                 CurrentAccess::Shared { cpu_reads, .. } => *cpu_reads -= 1,
2452                 _ => unreachable!("Image was not locked for CPU read"),
2453             }
2454         }
2455     }
2456 
2457     #[allow(dead_code)]
check_cpu_write(&self, range: Range<DeviceSize>) -> Result<(), WriteLockError>2458     pub(crate) fn check_cpu_write(&self, range: Range<DeviceSize>) -> Result<(), WriteLockError> {
2459         for (_range, state) in self.ranges.range(&range) {
2460             match &state.current_access {
2461                 CurrentAccess::CpuExclusive => return Err(WriteLockError::CpuLocked),
2462                 CurrentAccess::GpuExclusive { .. } => return Err(WriteLockError::GpuLocked),
2463                 CurrentAccess::Shared {
2464                     cpu_reads: 0,
2465                     gpu_reads: 0,
2466                 } => (),
2467                 CurrentAccess::Shared { cpu_reads, .. } if *cpu_reads > 0 => {
2468                     return Err(WriteLockError::CpuLocked)
2469                 }
2470                 CurrentAccess::Shared { .. } => return Err(WriteLockError::GpuLocked),
2471             }
2472         }
2473 
2474         Ok(())
2475     }
2476 
2477     #[allow(dead_code)]
cpu_write_lock(&mut self, range: Range<DeviceSize>)2478     pub(crate) unsafe fn cpu_write_lock(&mut self, range: Range<DeviceSize>) {
2479         self.ranges.split_at(&range.start);
2480         self.ranges.split_at(&range.end);
2481 
2482         for (_range, state) in self.ranges.range_mut(&range) {
2483             state.current_access = CurrentAccess::CpuExclusive;
2484         }
2485     }
2486 
2487     #[allow(dead_code)]
cpu_write_unlock(&mut self, range: Range<DeviceSize>)2488     pub(crate) unsafe fn cpu_write_unlock(&mut self, range: Range<DeviceSize>) {
2489         self.ranges.split_at(&range.start);
2490         self.ranges.split_at(&range.end);
2491 
2492         for (_range, state) in self.ranges.range_mut(&range) {
2493             match &mut state.current_access {
2494                 CurrentAccess::CpuExclusive => {
2495                     state.current_access = CurrentAccess::Shared {
2496                         cpu_reads: 0,
2497                         gpu_reads: 0,
2498                     }
2499                 }
2500                 _ => unreachable!("Image was not locked for CPU write"),
2501             }
2502         }
2503     }
2504 
check_gpu_read( &self, range: Range<DeviceSize>, expected_layout: ImageLayout, ) -> Result<(), AccessError>2505     pub(crate) fn check_gpu_read(
2506         &self,
2507         range: Range<DeviceSize>,
2508         expected_layout: ImageLayout,
2509     ) -> Result<(), AccessError> {
2510         for (_range, state) in self.ranges.range(&range) {
2511             match &state.current_access {
2512                 CurrentAccess::Shared { .. } => (),
2513                 _ => return Err(AccessError::AlreadyInUse),
2514             }
2515 
2516             if expected_layout != ImageLayout::Undefined && state.layout != expected_layout {
2517                 return Err(AccessError::UnexpectedImageLayout {
2518                     allowed: state.layout,
2519                     requested: expected_layout,
2520                 });
2521             }
2522         }
2523 
2524         Ok(())
2525     }
2526 
gpu_read_lock(&mut self, range: Range<DeviceSize>)2527     pub(crate) unsafe fn gpu_read_lock(&mut self, range: Range<DeviceSize>) {
2528         self.ranges.split_at(&range.start);
2529         self.ranges.split_at(&range.end);
2530 
2531         for (_range, state) in self.ranges.range_mut(&range) {
2532             match &mut state.current_access {
2533                 CurrentAccess::GpuExclusive { gpu_reads, .. }
2534                 | CurrentAccess::Shared { gpu_reads, .. } => *gpu_reads += 1,
2535                 _ => unreachable!("Image is being written by the CPU"),
2536             }
2537         }
2538     }
2539 
gpu_read_unlock(&mut self, range: Range<DeviceSize>)2540     pub(crate) unsafe fn gpu_read_unlock(&mut self, range: Range<DeviceSize>) {
2541         self.ranges.split_at(&range.start);
2542         self.ranges.split_at(&range.end);
2543 
2544         for (_range, state) in self.ranges.range_mut(&range) {
2545             match &mut state.current_access {
2546                 CurrentAccess::GpuExclusive { gpu_reads, .. } => *gpu_reads -= 1,
2547                 CurrentAccess::Shared { gpu_reads, .. } => *gpu_reads -= 1,
2548                 _ => unreachable!("Buffer was not locked for GPU read"),
2549             }
2550         }
2551     }
2552 
check_gpu_write( &self, range: Range<DeviceSize>, expected_layout: ImageLayout, ) -> Result<(), AccessError>2553     pub(crate) fn check_gpu_write(
2554         &self,
2555         range: Range<DeviceSize>,
2556         expected_layout: ImageLayout,
2557     ) -> Result<(), AccessError> {
2558         for (_range, state) in self.ranges.range(&range) {
2559             match &state.current_access {
2560                 CurrentAccess::Shared {
2561                     cpu_reads: 0,
2562                     gpu_reads: 0,
2563                 } => (),
2564                 _ => return Err(AccessError::AlreadyInUse),
2565             }
2566 
2567             if expected_layout != ImageLayout::Undefined && state.layout != expected_layout {
2568                 return Err(AccessError::UnexpectedImageLayout {
2569                     allowed: state.layout,
2570                     requested: expected_layout,
2571                 });
2572             }
2573         }
2574 
2575         Ok(())
2576     }
2577 
gpu_write_lock( &mut self, range: Range<DeviceSize>, destination_layout: ImageLayout, )2578     pub(crate) unsafe fn gpu_write_lock(
2579         &mut self,
2580         range: Range<DeviceSize>,
2581         destination_layout: ImageLayout,
2582     ) {
2583         debug_assert!(!matches!(
2584             destination_layout,
2585             ImageLayout::Undefined | ImageLayout::Preinitialized
2586         ));
2587 
2588         self.ranges.split_at(&range.start);
2589         self.ranges.split_at(&range.end);
2590 
2591         for (_range, state) in self.ranges.range_mut(&range) {
2592             match &mut state.current_access {
2593                 CurrentAccess::GpuExclusive { gpu_writes, .. } => *gpu_writes += 1,
2594                 &mut CurrentAccess::Shared {
2595                     cpu_reads: 0,
2596                     gpu_reads,
2597                 } => {
2598                     state.current_access = CurrentAccess::GpuExclusive {
2599                         gpu_reads,
2600                         gpu_writes: 1,
2601                     }
2602                 }
2603                 _ => unreachable!("Image is being accessed by the CPU"),
2604             }
2605 
2606             state.layout = destination_layout;
2607         }
2608     }
2609 
gpu_write_unlock(&mut self, range: Range<DeviceSize>)2610     pub(crate) unsafe fn gpu_write_unlock(&mut self, range: Range<DeviceSize>) {
2611         self.ranges.split_at(&range.start);
2612         self.ranges.split_at(&range.end);
2613 
2614         for (_range, state) in self.ranges.range_mut(&range) {
2615             match &mut state.current_access {
2616                 &mut CurrentAccess::GpuExclusive {
2617                     gpu_reads,
2618                     gpu_writes: 1,
2619                 } => {
2620                     state.current_access = CurrentAccess::Shared {
2621                         cpu_reads: 0,
2622                         gpu_reads,
2623                     }
2624                 }
2625                 CurrentAccess::GpuExclusive { gpu_writes, .. } => *gpu_writes -= 1,
2626                 _ => unreachable!("Image was not locked for GPU write"),
2627             }
2628         }
2629     }
2630 }
2631 
2632 /// The current state of a specific subresource range in an image.
2633 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
2634 struct ImageRangeState {
2635     current_access: CurrentAccess,
2636     layout: ImageLayout,
2637 }
2638 
2639 #[derive(Clone)]
2640 pub(crate) struct SubresourceRangeIterator {
2641     next_fn: fn(&mut Self) -> Option<Range<DeviceSize>>,
2642     image_aspect_size: DeviceSize,
2643     image_mip_level_size: DeviceSize,
2644     mip_levels: Range<u32>,
2645     array_layers: Range<u32>,
2646 
2647     aspect_nums: Peekable<smallvec::IntoIter<[usize; 4]>>,
2648     current_aspect_num: Option<usize>,
2649     current_mip_level: u32,
2650 }
2651 
2652 impl SubresourceRangeIterator {
new( subresource_range: ImageSubresourceRange, image_aspect_list: &[ImageAspect], image_aspect_size: DeviceSize, image_mip_levels: u32, image_mip_level_size: DeviceSize, image_array_layers: u32, ) -> Self2653     fn new(
2654         subresource_range: ImageSubresourceRange,
2655         image_aspect_list: &[ImageAspect],
2656         image_aspect_size: DeviceSize,
2657         image_mip_levels: u32,
2658         image_mip_level_size: DeviceSize,
2659         image_array_layers: u32,
2660     ) -> Self {
2661         assert!(!subresource_range.mip_levels.is_empty());
2662         assert!(!subresource_range.array_layers.is_empty());
2663 
2664         let next_fn = if subresource_range.array_layers.start != 0
2665             || subresource_range.array_layers.end != image_array_layers
2666         {
2667             Self::next_some_layers
2668         } else if subresource_range.mip_levels.start != 0
2669             || subresource_range.mip_levels.end != image_mip_levels
2670         {
2671             Self::next_some_levels_all_layers
2672         } else {
2673             Self::next_all_levels_all_layers
2674         };
2675 
2676         let mut aspect_nums = subresource_range
2677             .aspects
2678             .into_iter()
2679             .map(|aspect| image_aspect_list.iter().position(|&a| a == aspect).unwrap())
2680             .collect::<SmallVec<[usize; 4]>>()
2681             .into_iter()
2682             .peekable();
2683         assert!(aspect_nums.len() != 0);
2684         let current_aspect_num = aspect_nums.next();
2685         let current_mip_level = subresource_range.mip_levels.start;
2686 
2687         Self {
2688             next_fn,
2689             image_aspect_size,
2690             image_mip_level_size,
2691             mip_levels: subresource_range.mip_levels,
2692             array_layers: subresource_range.array_layers,
2693 
2694             aspect_nums,
2695             current_aspect_num,
2696             current_mip_level,
2697         }
2698     }
2699 
2700     /// Used when the requested range contains only a subset of the array layers in the image.
2701     /// The iterator returns one range for each mip level and aspect, each covering the range of
2702     /// array layers of that mip level and aspect.
next_some_layers(&mut self) -> Option<Range<DeviceSize>>2703     fn next_some_layers(&mut self) -> Option<Range<DeviceSize>> {
2704         self.current_aspect_num.map(|aspect_num| {
2705             let mip_level_offset = aspect_num as DeviceSize * self.image_aspect_size
2706                 + self.current_mip_level as DeviceSize * self.image_mip_level_size;
2707             self.current_mip_level += 1;
2708 
2709             if self.current_mip_level >= self.mip_levels.end {
2710                 self.current_mip_level = self.mip_levels.start;
2711                 self.current_aspect_num = self.aspect_nums.next();
2712             }
2713 
2714             let start = mip_level_offset + self.array_layers.start as DeviceSize;
2715             let end = mip_level_offset + self.array_layers.end as DeviceSize;
2716             start..end
2717         })
2718     }
2719 
2720     /// Used when the requested range contains all array layers in the image, but not all mip
2721     /// levels. The iterator returns one range for each aspect, each covering all layers of the
2722     /// range of mip levels of that aspect.
next_some_levels_all_layers(&mut self) -> Option<Range<DeviceSize>>2723     fn next_some_levels_all_layers(&mut self) -> Option<Range<DeviceSize>> {
2724         self.current_aspect_num.map(|aspect_num| {
2725             let aspect_offset = aspect_num as DeviceSize * self.image_aspect_size;
2726             self.current_aspect_num = self.aspect_nums.next();
2727 
2728             let start =
2729                 aspect_offset + self.mip_levels.start as DeviceSize * self.image_mip_level_size;
2730             let end = aspect_offset + self.mip_levels.end as DeviceSize * self.image_mip_level_size;
2731             start..end
2732         })
2733     }
2734 
2735     /// Used when the requested range contains all array layers and mip levels in the image.
2736     /// The iterator returns one range for each series of adjacent aspect numbers, each covering
2737     /// all mip levels and all layers of those aspects. If the range contains the whole image, then
2738     /// exactly one range is returned since all aspect numbers will be adjacent.
next_all_levels_all_layers(&mut self) -> Option<Range<DeviceSize>>2739     fn next_all_levels_all_layers(&mut self) -> Option<Range<DeviceSize>> {
2740         self.current_aspect_num.map(|aspect_num_start| {
2741             self.current_aspect_num = self.aspect_nums.next();
2742             let mut aspect_num_end = aspect_num_start + 1;
2743 
2744             while self.current_aspect_num == Some(aspect_num_end) {
2745                 self.current_aspect_num = self.aspect_nums.next();
2746                 aspect_num_end += 1;
2747             }
2748 
2749             let start = aspect_num_start as DeviceSize * self.image_aspect_size;
2750             let end = aspect_num_end as DeviceSize * self.image_aspect_size;
2751             start..end
2752         })
2753     }
2754 }
2755 
2756 impl Iterator for SubresourceRangeIterator {
2757     type Item = Range<DeviceSize>;
2758 
next(&mut self) -> Option<Self::Item>2759     fn next(&mut self) -> Option<Self::Item> {
2760         (self.next_fn)(self)
2761     }
2762 }
2763 
2764 impl FusedIterator for SubresourceRangeIterator {}
2765 
2766 /// Describes the memory layout of a single subresource of an image.
2767 ///
2768 /// The address of a texel at `(x, y, z, layer)` is `layer * array_pitch + z * depth_pitch +
2769 /// y * row_pitch + x * size_of_each_texel + offset`. `size_of_each_texel` must be determined
2770 /// depending on the format. The same formula applies for compressed formats, except that the
2771 /// coordinates must be in number of blocks.
2772 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
2773 pub struct SubresourceLayout {
2774     /// The number of bytes from the start of the memory to the start of the queried subresource.
2775     pub offset: DeviceSize,
2776 
2777     /// The total number of bytes for the queried subresource.
2778     pub size: DeviceSize,
2779 
2780     /// The number of bytes between two texels or two blocks in adjacent rows.
2781     pub row_pitch: DeviceSize,
2782 
2783     /// For images with more than one array layer, the number of bytes between two texels or two
2784     /// blocks in adjacent array layers.
2785     pub array_pitch: Option<DeviceSize>,
2786 
2787     /// For 3D images, the number of bytes between two texels or two blocks in adjacent depth
2788     /// layers.
2789     pub depth_pitch: Option<DeviceSize>,
2790 }
2791 
2792 /// Error that can happen in image functions.
2793 #[derive(Clone, Debug, PartialEq, Eq)]
2794 pub enum ImageError {
2795     VulkanError(VulkanError),
2796 
2797     /// Allocating memory failed.
2798     AllocError(AllocationCreationError),
2799 
2800     RequirementNotMet {
2801         required_for: &'static str,
2802         requires_one_of: RequiresOneOf,
2803     },
2804 
2805     /// The provided number of elements in `allocations` is not what is required for `image`.
2806     AllocationsWrongNumberOfElements {
2807         provided: usize,
2808         required: usize,
2809     },
2810 
2811     /// The `array_2d_compatible` flag was enabled, but the image type was not 3D.
2812     Array2dCompatibleNot3d,
2813 
2814     /// The provided array layer is not less than the number of array layers in the image.
2815     ArrayLayerOutOfRange {
2816         provided_array_layer: u32,
2817         image_array_layers: u32,
2818     },
2819 
2820     /// The provided aspect is not present in the image, or is not allowed.
2821     AspectNotAllowed {
2822         provided_aspect: ImageAspect,
2823         allowed_aspects: ImageAspects,
2824     },
2825 
2826     /// The `block_texel_view_compatible` flag was enabled, but the given format was not compressed.
2827     BlockTexelViewCompatibleNotCompressed,
2828 
2829     /// The `cube_compatible` flag was enabled, but the image type was not 2D.
2830     CubeCompatibleNot2d,
2831 
2832     /// The `cube_compatible` flag was enabled, but the number of array layers was less than 6.
2833     CubeCompatibleNotEnoughArrayLayers,
2834 
2835     /// The `cube_compatible` flag was enabled, but the image dimensions were not square.
2836     CubeCompatibleNotSquare,
2837 
2838     /// The `cube_compatible` flag was enabled together with multisampling.
2839     CubeCompatibleMultisampling,
2840 
2841     /// The memory was created dedicated to a resource, but not to this image.
2842     DedicatedAllocationMismatch,
2843 
2844     /// A dedicated allocation is required for this image, but one was not provided.
2845     DedicatedAllocationRequired,
2846 
2847     /// The image has a format with both a depth and a stencil aspect, which is not supported for
2848     /// this operation.
2849     DepthStencilFormatsNotSupported,
2850 
2851     /// The `disjoint` flag was enabled, but the given format is either not multi-planar, or does
2852     /// not support disjoint images.
2853     DisjointFormatNotSupported,
2854 
2855     /// One or more external memory handle types were provided, but the initial layout was not
2856     /// `Undefined`.
2857     ExternalMemoryInvalidInitialLayout,
2858 
2859     /// The given format was not supported by the device.
2860     FormatNotSupported,
2861 
2862     /// A requested usage flag was not supported by the given format.
2863     FormatUsageNotSupported {
2864         usage: &'static str,
2865     },
2866 
2867     /// The image configuration as queried through the `image_format_properties` function was not
2868     /// supported by the device.
2869     ImageFormatPropertiesNotSupported,
2870 
2871     /// The number of array layers exceeds the maximum supported by the device for this image
2872     /// configuration.
2873     MaxArrayLayersExceeded {
2874         array_layers: u32,
2875         max: u32,
2876     },
2877 
2878     /// The specified dimensions exceed the maximum supported by the device for this image
2879     /// configuration.
2880     MaxDimensionsExceeded {
2881         extent: [u32; 3],
2882         max: [u32; 3],
2883     },
2884 
2885     /// The usage included one of the attachment types, and the specified width and height exceeded
2886     /// the `max_framebuffer_width` or `max_framebuffer_height` limits.
2887     MaxFramebufferDimensionsExceeded {
2888         extent: [u32; 2],
2889         max: [u32; 2],
2890     },
2891 
2892     /// The maximum number of mip levels for the given dimensions has been exceeded.
2893     MaxMipLevelsExceeded {
2894         mip_levels: u32,
2895         max: u32,
2896     },
2897 
2898     /// In an `allocations` element, the offset of the allocation does not have the required
2899     /// alignment.
2900     MemoryAllocationNotAligned {
2901         allocations_index: usize,
2902         allocation_offset: DeviceSize,
2903         required_alignment: DeviceAlignment,
2904     },
2905 
2906     /// In an `allocations` element, the size of the allocation is smaller than what is required.
2907     MemoryAllocationTooSmall {
2908         allocations_index: usize,
2909         allocation_size: DeviceSize,
2910         required_size: DeviceSize,
2911     },
2912 
2913     /// In an `allocations` element, the memory was created with export handle types, but none of
2914     /// these handle types were enabled on the image.
2915     MemoryExternalHandleTypesDisjoint {
2916         allocations_index: usize,
2917         image_handle_types: ExternalMemoryHandleTypes,
2918         memory_export_handle_types: ExternalMemoryHandleTypes,
2919     },
2920 
2921     /// In an `allocations` element, the memory was created with an import, but the import's handle
2922     /// type was not enabled on the image.
2923     MemoryImportedHandleTypeNotEnabled {
2924         allocations_index: usize,
2925         image_handle_types: ExternalMemoryHandleTypes,
2926         memory_imported_handle_type: ExternalMemoryHandleType,
2927     },
2928 
2929     /// In an `allocations` element, the protection of image and memory are not equal.
2930     MemoryProtectedMismatch {
2931         allocations_index: usize,
2932         image_protected: bool,
2933         memory_protected: bool,
2934     },
2935 
2936     /// In an `allocations` element, the provided memory type is not one of the allowed memory
2937     /// types that can be bound to this image or image plane.
2938     MemoryTypeNotAllowed {
2939         allocations_index: usize,
2940         provided_memory_type_index: u32,
2941         allowed_memory_type_bits: u32,
2942     },
2943 
2944     /// The provided mip level is not less than the number of mip levels in the image.
2945     MipLevelOutOfRange {
2946         provided_mip_level: u32,
2947         image_mip_levels: u32,
2948     },
2949 
2950     /// Multisampling was enabled, and the `cube_compatible` flag was set.
2951     MultisampleCubeCompatible,
2952 
2953     /// Multisampling was enabled, and tiling was `Linear`.
2954     MultisampleLinearTiling,
2955 
2956     /// Multisampling was enabled, and multiple mip levels were specified.
2957     MultisampleMultipleMipLevels,
2958 
2959     /// Multisampling was enabled, but the image type was not 2D.
2960     MultisampleNot2d,
2961 
2962     /// The image has optimal tiling, which is not supported for this operation.
2963     OptimalTilingNotSupported,
2964 
2965     /// The sample count is not supported by the device for this image configuration.
2966     SampleCountNotSupported {
2967         samples: SampleCount,
2968         supported: SampleCounts,
2969     },
2970 
2971     /// The sharing mode was set to `Concurrent`, but one of the specified queue family indices was
2972     /// out of range.
2973     SharingQueueFamilyIndexOutOfRange {
2974         queue_family_index: u32,
2975         queue_family_count: u32,
2976     },
2977 
2978     /// The provided `usage` and `stencil_usage` have different values for
2979     /// `depth_stencil_attachment` or `transient_attachment`.
2980     StencilUsageMismatch {
2981         usage: ImageUsage,
2982         stencil_usage: ImageUsage,
2983     },
2984 
2985     /// A YCbCr format was given, but the specified width and/or height was not a multiple of 2
2986     /// as required by the format's chroma subsampling.
2987     YcbcrFormatInvalidDimensions,
2988 
2989     /// A YCbCr format was given, and multiple mip levels were specified.
2990     YcbcrFormatMultipleMipLevels,
2991 
2992     /// A YCbCr format was given, and multisampling was enabled.
2993     YcbcrFormatMultisampling,
2994 
2995     /// A YCbCr format was given, but the image type was not 2D.
2996     YcbcrFormatNot2d,
2997 
2998     DirectImageViewCreationFailed(ImageViewCreationError),
2999 
3000     /// If and only if tiling is `DRMFormatModifier`, then `image_drm_format_modifier_create_info` must not be `None`.
3001     DrmFormatModifierRequiresCreateInfo,
3002 }
3003 
3004 impl Error for ImageError {
source(&self) -> Option<&(dyn Error + 'static)>3005     fn source(&self) -> Option<&(dyn Error + 'static)> {
3006         match self {
3007             ImageError::AllocError(err) => Some(err),
3008             _ => None,
3009         }
3010     }
3011 }
3012 
3013 impl Display for ImageError {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>3014     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
3015         match self {
3016             Self::VulkanError(_) => write!(f, "a runtime error occurred"),
3017             Self::AllocError(_) => write!(f, "allocating memory failed"),
3018             Self::RequirementNotMet {
3019                 required_for,
3020                 requires_one_of,
3021             } => write!(
3022                 f,
3023                 "a requirement was not met for: {}; requires one of: {}",
3024                 required_for, requires_one_of,
3025             ),
3026             Self::AllocationsWrongNumberOfElements { provided, required } => write!(
3027                 f,
3028                 "the provided number of elements in `allocations` ({}) is not what is required for \
3029                 `image` ({})",
3030                 provided, required,
3031             ),
3032             Self::Array2dCompatibleNot3d => write!(
3033                 f,
3034                 "the `array_2d_compatible` flag was enabled, but the image type was not 3D",
3035             ),
3036             Self::ArrayLayerOutOfRange {
3037                 provided_array_layer,
3038                 image_array_layers,
3039             } => write!(
3040                 f,
3041                 "the provided array layer ({}) is not less than the number of array layers in the image ({})",
3042                 provided_array_layer, image_array_layers,
3043             ),
3044             Self::AspectNotAllowed {
3045                 provided_aspect,
3046                 allowed_aspects,
3047             } => write!(
3048                 f,
3049                 "the provided aspect ({:?}) is not present in the image, or is not allowed ({:?})",
3050                 provided_aspect, allowed_aspects,
3051             ),
3052             Self::BlockTexelViewCompatibleNotCompressed => write!(
3053                 f,
3054                 "the `block_texel_view_compatible` flag was enabled, but the given format was not \
3055                 compressed",
3056             ),
3057             Self::CubeCompatibleNot2d => write!(
3058                 f,
3059                 "the `cube_compatible` flag was enabled, but the image type was not 2D",
3060             ),
3061             Self::CubeCompatibleNotEnoughArrayLayers => write!(
3062                 f,
3063                 "the `cube_compatible` flag was enabled, but the number of array layers was less \
3064                 than 6",
3065             ),
3066             Self::CubeCompatibleNotSquare => write!(
3067                 f,
3068                 "the `cube_compatible` flag was enabled, but the image dimensions were not square",
3069             ),
3070             Self::CubeCompatibleMultisampling => write!(
3071                 f,
3072                 "the `cube_compatible` flag was enabled together with multisampling",
3073             ),
3074             Self::DedicatedAllocationMismatch => write!(
3075                 f,
3076                 "the memory was created dedicated to a resource, but not to this image",
3077             ),
3078             Self::DedicatedAllocationRequired => write!(
3079                 f,
3080                 "a dedicated allocation is required for this image, but one was not provided"
3081             ),
3082             Self::DepthStencilFormatsNotSupported => write!(
3083                 f,
3084                 "the image has a format with both a depth and a stencil aspect, which is not \
3085                 supported for this operation",
3086             ),
3087             Self::DisjointFormatNotSupported => write!(
3088                 f,
3089                 "the `disjoint` flag was enabled, but the given format is either not multi-planar, \
3090                 or does not support disjoint images",
3091             ),
3092             Self::ExternalMemoryInvalidInitialLayout => write!(
3093                 f,
3094                 "one or more external memory handle types were provided, but the initial layout \
3095                 was not `Undefined`",
3096             ),
3097             Self::FormatNotSupported => {
3098                 write!(f, "the given format was not supported by the device")
3099             }
3100             Self::FormatUsageNotSupported { .. } => write!(
3101                 f,
3102                 "a requested usage flag was not supported by the given format",
3103             ),
3104             Self::ImageFormatPropertiesNotSupported => write!(
3105                 f,
3106                 "the image configuration as queried through the `image_format_properties` function \
3107                 was not supported by the device",
3108             ),
3109             Self::MaxArrayLayersExceeded { .. } => write!(
3110                 f,
3111                 "the number of array layers exceeds the maximum supported by the device for this \
3112                 image configuration",
3113             ),
3114             Self::MaxDimensionsExceeded { .. } => write!(
3115                 f,
3116                 "the specified dimensions exceed the maximum supported by the device for this \
3117                 image configuration",
3118             ),
3119             Self::MaxFramebufferDimensionsExceeded { .. } => write!(
3120                 f,
3121                 "the usage included one of the attachment types, and the specified width and \
3122                 height exceeded the `max_framebuffer_width` or `max_framebuffer_height` limits",
3123             ),
3124             Self::MaxMipLevelsExceeded { .. } => write!(
3125                 f,
3126                 "the maximum number of mip levels for the given dimensions has been exceeded",
3127             ),
3128             Self::MemoryAllocationNotAligned {
3129                 allocations_index,
3130                 allocation_offset,
3131                 required_alignment,
3132             } => write!(
3133                 f,
3134                 "in `allocations` element {}, the offset of the allocation ({}) does not have the \
3135                 required alignment ({:?})",
3136                 allocations_index, allocation_offset, required_alignment,
3137             ),
3138             Self::MemoryAllocationTooSmall {
3139                 allocations_index,
3140                 allocation_size,
3141                 required_size,
3142             } => write!(
3143                 f,
3144                 "in `allocations` element {}, the size of the allocation ({}) is smaller than what \
3145                 is required ({})",
3146                 allocations_index, allocation_size, required_size,
3147             ),
3148             Self::MemoryExternalHandleTypesDisjoint {
3149                 allocations_index, ..
3150             } => write!(
3151                 f,
3152                 "in `allocations` element {}, the memory was created with export handle types, but \
3153                 none of these handle types were enabled on the image",
3154                 allocations_index,
3155             ),
3156             Self::MemoryImportedHandleTypeNotEnabled {
3157                 allocations_index, ..
3158             } => write!(
3159                 f,
3160                 "in `allocations` element {}, the memory was created with an import, but the \
3161                 import's handle type was not enabled on the image",
3162                 allocations_index,
3163             ),
3164             Self::MemoryProtectedMismatch {
3165                 allocations_index,
3166                 image_protected,
3167                 memory_protected,
3168             } => write!(
3169                 f,
3170                 "in `allocations` element {}, the protection of image ({}) and memory ({}) are not \
3171                 equal",
3172                 allocations_index, image_protected, memory_protected,
3173             ),
3174             Self::MemoryTypeNotAllowed {
3175                 allocations_index,
3176                 provided_memory_type_index,
3177                 allowed_memory_type_bits,
3178             } => write!(
3179                 f,
3180                 "in `allocations` element {}, the provided memory type ({}) is not one of the \
3181                 allowed memory types (",
3182                 allocations_index, provided_memory_type_index,
3183             )
3184             .and_then(|_| {
3185                 let mut first = true;
3186 
3187                 for i in (0..size_of_val(allowed_memory_type_bits))
3188                     .filter(|i| allowed_memory_type_bits & (1 << i) != 0)
3189                 {
3190                     if first {
3191                         write!(f, "{}", i)?;
3192                         first = false;
3193                     } else {
3194                         write!(f, ", {}", i)?;
3195                     }
3196                 }
3197 
3198                 Ok(())
3199             })
3200             .and_then(|_| write!(f, ") that can be bound to this buffer")),
3201             Self::MipLevelOutOfRange {
3202                 provided_mip_level,
3203                 image_mip_levels,
3204             } => write!(
3205                 f,
3206                 "the provided mip level ({}) is not less than the number of mip levels in the image ({})",
3207                 provided_mip_level, image_mip_levels,
3208             ),
3209             Self::MultisampleCubeCompatible => write!(
3210                 f,
3211                 "multisampling was enabled, and the `cube_compatible` flag was set",
3212             ),
3213             Self::MultisampleLinearTiling => {
3214                 write!(f, "multisampling was enabled, and tiling was `Linear`")
3215             }
3216             Self::MultisampleMultipleMipLevels => write!(
3217                 f,
3218                 "multisampling was enabled, and multiple mip levels were specified",
3219             ),
3220             Self::MultisampleNot2d => write!(
3221                 f,
3222                 "multisampling was enabled, but the image type was not 2D",
3223             ),
3224             Self::OptimalTilingNotSupported => write!(
3225                 f,
3226                 "the image has optimal tiling, which is not supported for this operation",
3227             ),
3228             Self::SampleCountNotSupported { .. } => write!(
3229                 f,
3230                 "the sample count is not supported by the device for this image configuration",
3231             ),
3232             Self::SharingQueueFamilyIndexOutOfRange { .. } => write!(
3233                 f,
3234                 "the sharing mode was set to `Concurrent`, but one of the specified queue family \
3235                 indices was out of range",
3236             ),
3237             Self::StencilUsageMismatch {
3238                 usage: _,
3239                 stencil_usage: _,
3240             } => write!(
3241                 f,
3242                 "the provided `usage` and `stencil_usage` have different values for \
3243                 `depth_stencil_attachment` or `transient_attachment`",
3244             ),
3245             Self::YcbcrFormatInvalidDimensions => write!(
3246                 f,
3247                 "a YCbCr format was given, but the specified width and/or height was not a \
3248                 multiple of 2 as required by the format's chroma subsampling",
3249             ),
3250             Self::YcbcrFormatMultipleMipLevels => write!(
3251                 f,
3252                 "a YCbCr format was given, and multiple mip levels were specified",
3253             ),
3254             Self::YcbcrFormatMultisampling => {
3255                 write!(f, "a YCbCr format was given, and multisampling was enabled")
3256             }
3257             Self::YcbcrFormatNot2d => {
3258                 write!(f, "a YCbCr format was given, but the image type was not 2D")
3259             }
3260             Self::DirectImageViewCreationFailed(e) => write!(f, "Image view creation failed {}", e),
3261 	    Self::DrmFormatModifierRequiresCreateInfo => write!(f, "If and only if tiling is `DRMFormatModifier`, then `image_drm_format_modifier_create_info` must be `Some`"),
3262         }
3263     }
3264 }
3265 
3266 impl From<VulkanError> for ImageError {
from(err: VulkanError) -> Self3267     fn from(err: VulkanError) -> Self {
3268         Self::VulkanError(err)
3269     }
3270 }
3271 
3272 impl From<AllocationCreationError> for ImageError {
from(err: AllocationCreationError) -> Self3273     fn from(err: AllocationCreationError) -> Self {
3274         Self::AllocError(err)
3275     }
3276 }
3277 
3278 impl From<RequirementNotMet> for ImageError {
from(err: RequirementNotMet) -> Self3279     fn from(err: RequirementNotMet) -> Self {
3280         Self::RequirementNotMet {
3281             required_for: err.required_for,
3282             requires_one_of: err.requires_one_of,
3283         }
3284     }
3285 }
3286 
3287 #[cfg(test)]
3288 mod tests {
3289     use super::{ImageCreateInfo, ImageError, ImageUsage, RawImage};
3290     use crate::{
3291         format::Format,
3292         image::{
3293             sys::SubresourceRangeIterator, ImageAspect, ImageAspects, ImageCreateFlags,
3294             ImageDimensions, ImageSubresourceRange, SampleCount,
3295         },
3296         DeviceSize, RequiresOneOf,
3297     };
3298     use smallvec::SmallVec;
3299 
3300     #[test]
create_sampled()3301     fn create_sampled() {
3302         let (device, _) = gfx_dev_and_queue!();
3303 
3304         let _ = RawImage::new(
3305             device,
3306             ImageCreateInfo {
3307                 dimensions: ImageDimensions::Dim2d {
3308                     width: 32,
3309                     height: 32,
3310                     array_layers: 1,
3311                 },
3312                 format: Some(Format::R8G8B8A8_UNORM),
3313                 usage: ImageUsage::SAMPLED,
3314                 ..Default::default()
3315             },
3316         )
3317         .unwrap();
3318     }
3319 
3320     #[test]
create_transient()3321     fn create_transient() {
3322         let (device, _) = gfx_dev_and_queue!();
3323 
3324         let _ = RawImage::new(
3325             device,
3326             ImageCreateInfo {
3327                 dimensions: ImageDimensions::Dim2d {
3328                     width: 32,
3329                     height: 32,
3330                     array_layers: 1,
3331                 },
3332                 format: Some(Format::R8G8B8A8_UNORM),
3333                 usage: ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::COLOR_ATTACHMENT,
3334                 ..Default::default()
3335             },
3336         )
3337         .unwrap();
3338     }
3339 
3340     #[test]
zero_mipmap()3341     fn zero_mipmap() {
3342         let (device, _) = gfx_dev_and_queue!();
3343 
3344         assert_should_panic!({
3345             let _ = RawImage::new(
3346                 device,
3347                 ImageCreateInfo {
3348                     dimensions: ImageDimensions::Dim2d {
3349                         width: 32,
3350                         height: 32,
3351                         array_layers: 1,
3352                     },
3353                     format: Some(Format::R8G8B8A8_UNORM),
3354                     mip_levels: 0,
3355                     usage: ImageUsage::SAMPLED,
3356                     ..Default::default()
3357                 },
3358             );
3359         });
3360     }
3361 
3362     #[test]
mipmaps_too_high()3363     fn mipmaps_too_high() {
3364         let (device, _) = gfx_dev_and_queue!();
3365 
3366         let res = RawImage::new(
3367             device,
3368             ImageCreateInfo {
3369                 dimensions: ImageDimensions::Dim2d {
3370                     width: 32,
3371                     height: 32,
3372                     array_layers: 1,
3373                 },
3374                 format: Some(Format::R8G8B8A8_UNORM),
3375                 mip_levels: u32::MAX,
3376                 usage: ImageUsage::SAMPLED,
3377                 ..Default::default()
3378             },
3379         );
3380 
3381         match res {
3382             Err(ImageError::MaxMipLevelsExceeded { .. }) => (),
3383             _ => panic!(),
3384         };
3385     }
3386 
3387     #[test]
shader_storage_image_multisample()3388     fn shader_storage_image_multisample() {
3389         let (device, _) = gfx_dev_and_queue!();
3390 
3391         let res = RawImage::new(
3392             device,
3393             ImageCreateInfo {
3394                 dimensions: ImageDimensions::Dim2d {
3395                     width: 32,
3396                     height: 32,
3397                     array_layers: 1,
3398                 },
3399                 format: Some(Format::R8G8B8A8_UNORM),
3400                 samples: SampleCount::Sample2,
3401                 usage: ImageUsage::STORAGE,
3402                 ..Default::default()
3403             },
3404         );
3405 
3406         match res {
3407             Err(ImageError::RequirementNotMet {
3408                 requires_one_of: RequiresOneOf { features, .. },
3409                 ..
3410             }) if features.contains(&"shader_storage_image_multisample") => (),
3411             Err(ImageError::SampleCountNotSupported { .. }) => (), // unlikely but possible
3412             _ => panic!(),
3413         };
3414     }
3415 
3416     #[test]
compressed_not_color_attachment()3417     fn compressed_not_color_attachment() {
3418         let (device, _) = gfx_dev_and_queue!();
3419 
3420         let res = RawImage::new(
3421             device,
3422             ImageCreateInfo {
3423                 dimensions: ImageDimensions::Dim2d {
3424                     width: 32,
3425                     height: 32,
3426                     array_layers: 1,
3427                 },
3428                 format: Some(Format::ASTC_5x4_UNORM_BLOCK),
3429                 usage: ImageUsage::COLOR_ATTACHMENT,
3430                 ..Default::default()
3431             },
3432         );
3433 
3434         match res {
3435             Err(ImageError::FormatNotSupported) => (),
3436             Err(ImageError::FormatUsageNotSupported {
3437                 usage: "color_attachment",
3438             }) => (),
3439             _ => panic!(),
3440         };
3441     }
3442 
3443     #[test]
transient_forbidden_with_some_usages()3444     fn transient_forbidden_with_some_usages() {
3445         let (device, _) = gfx_dev_and_queue!();
3446 
3447         assert_should_panic!({
3448             let _ = RawImage::new(
3449                 device,
3450                 ImageCreateInfo {
3451                     dimensions: ImageDimensions::Dim2d {
3452                         width: 32,
3453                         height: 32,
3454                         array_layers: 1,
3455                     },
3456                     format: Some(Format::R8G8B8A8_UNORM),
3457                     usage: ImageUsage::TRANSIENT_ATTACHMENT | ImageUsage::SAMPLED,
3458                     ..Default::default()
3459                 },
3460             );
3461         })
3462     }
3463 
3464     #[test]
cubecompatible_dims_mismatch()3465     fn cubecompatible_dims_mismatch() {
3466         let (device, _) = gfx_dev_and_queue!();
3467 
3468         let res = RawImage::new(
3469             device,
3470             ImageCreateInfo {
3471                 flags: ImageCreateFlags::CUBE_COMPATIBLE,
3472                 dimensions: ImageDimensions::Dim2d {
3473                     width: 32,
3474                     height: 64,
3475                     array_layers: 1,
3476                 },
3477                 format: Some(Format::R8G8B8A8_UNORM),
3478                 usage: ImageUsage::SAMPLED,
3479                 ..Default::default()
3480             },
3481         );
3482 
3483         match res {
3484             Err(ImageError::CubeCompatibleNotEnoughArrayLayers) => (),
3485             Err(ImageError::CubeCompatibleNotSquare) => (),
3486             _ => panic!(),
3487         };
3488     }
3489 
3490     #[test]
3491     #[allow(clippy::erasing_op, clippy::identity_op)]
subresource_range_iterator()3492     fn subresource_range_iterator() {
3493         // A fictitious set of aspects that no real image would actually ever have.
3494         let image_aspect_list: SmallVec<[ImageAspect; 4]> = (ImageAspects::COLOR
3495             | ImageAspects::DEPTH
3496             | ImageAspects::STENCIL
3497             | ImageAspects::PLANE_0)
3498             .into_iter()
3499             .collect();
3500         let image_mip_levels = 6;
3501         let image_array_layers = 8;
3502 
3503         let mip = image_array_layers as DeviceSize;
3504         let asp = mip * image_mip_levels as DeviceSize;
3505 
3506         // Whole image
3507         let mut iter = SubresourceRangeIterator::new(
3508             ImageSubresourceRange {
3509                 aspects: ImageAspects::COLOR
3510                     | ImageAspects::DEPTH
3511                     | ImageAspects::STENCIL
3512                     | ImageAspects::PLANE_0,
3513                 mip_levels: 0..6,
3514                 array_layers: 0..8,
3515             },
3516             &image_aspect_list,
3517             asp,
3518             image_mip_levels,
3519             mip,
3520             image_array_layers,
3521         );
3522 
3523         assert_eq!(iter.next(), Some(0 * asp..4 * asp));
3524         assert_eq!(iter.next(), None);
3525 
3526         // Only some aspects
3527         let mut iter = SubresourceRangeIterator::new(
3528             ImageSubresourceRange {
3529                 aspects: ImageAspects::COLOR | ImageAspects::DEPTH | ImageAspects::PLANE_0,
3530                 mip_levels: 0..6,
3531                 array_layers: 0..8,
3532             },
3533             &image_aspect_list,
3534             asp,
3535             image_mip_levels,
3536             mip,
3537             image_array_layers,
3538         );
3539 
3540         assert_eq!(iter.next(), Some(0 * asp..2 * asp));
3541         assert_eq!(iter.next(), Some(3 * asp..4 * asp));
3542         assert_eq!(iter.next(), None);
3543 
3544         // Two aspects, and only some of the mip levels
3545         let mut iter = SubresourceRangeIterator::new(
3546             ImageSubresourceRange {
3547                 aspects: ImageAspects::DEPTH | ImageAspects::STENCIL,
3548                 mip_levels: 2..4,
3549                 array_layers: 0..8,
3550             },
3551             &image_aspect_list,
3552             asp,
3553             image_mip_levels,
3554             mip,
3555             image_array_layers,
3556         );
3557         assert_eq!(iter.next(), Some(1 * asp + 2 * mip..1 * asp + 4 * mip));
3558         assert_eq!(iter.next(), Some(2 * asp + 2 * mip..2 * asp + 4 * mip));
3559         assert_eq!(iter.next(), None);
3560 
3561         // One aspect, one mip level, only some of the array layers
3562         let mut iter = SubresourceRangeIterator::new(
3563             ImageSubresourceRange {
3564                 aspects: ImageAspects::COLOR,
3565 
3566                 mip_levels: 0..1,
3567                 array_layers: 2..4,
3568             },
3569             &image_aspect_list,
3570             asp,
3571             image_mip_levels,
3572             mip,
3573             image_array_layers,
3574         );
3575 
3576         assert_eq!(
3577             iter.next(),
3578             Some(0 * asp + 0 * mip + 2..0 * asp + 0 * mip + 4)
3579         );
3580         assert_eq!(iter.next(), None);
3581 
3582         // Two aspects, two mip levels, only some of the array layers
3583         let mut iter = SubresourceRangeIterator::new(
3584             ImageSubresourceRange {
3585                 aspects: ImageAspects::DEPTH | ImageAspects::STENCIL,
3586                 mip_levels: 2..4,
3587                 array_layers: 6..8,
3588             },
3589             &image_aspect_list,
3590             asp,
3591             image_mip_levels,
3592             mip,
3593             image_array_layers,
3594         );
3595         assert_eq!(
3596             iter.next(),
3597             Some(1 * asp + 2 * mip + 6..1 * asp + 2 * mip + 8)
3598         );
3599         assert_eq!(
3600             iter.next(),
3601             Some(1 * asp + 3 * mip + 6..1 * asp + 3 * mip + 8)
3602         );
3603         assert_eq!(
3604             iter.next(),
3605             Some(2 * asp + 2 * mip + 6..2 * asp + 2 * mip + 8)
3606         );
3607         assert_eq!(
3608             iter.next(),
3609             Some(2 * asp + 3 * mip + 6..2 * asp + 3 * mip + 8)
3610         );
3611         assert_eq!(iter.next(), None);
3612     }
3613 }
3614