1 // Copyright (c) 2021 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 //! Image views.
11 //!
12 //! This module contains types related to image views. An image view wraps around
13 //! an image and describes how the GPU should interpret the data. It is needed when an image is
14 //! to be used in a shader descriptor or as a framebuffer attachment.
15 
16 use super::{
17     sys::Image, ImageAccess, ImageDimensions, ImageFormatInfo, ImageSubresourceRange, ImageUsage,
18 };
19 use crate::{
20     device::{Device, DeviceOwned},
21     format::{ChromaSampling, Format, FormatFeatures},
22     image::{ImageAspects, ImageCreateFlags, ImageTiling, ImageType, SampleCount},
23     macros::{impl_id_counter, vulkan_enum},
24     sampler::{ycbcr::SamplerYcbcrConversion, ComponentMapping},
25     OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
26 };
27 use std::{
28     error::Error,
29     fmt::{Debug, Display, Error as FmtError, Formatter},
30     hash::{Hash, Hasher},
31     mem::MaybeUninit,
32     num::NonZeroU64,
33     ptr,
34     sync::Arc,
35 };
36 
37 /// A wrapper around an image that makes it available to shaders or framebuffers.
38 #[derive(Debug)]
39 pub struct ImageView<I>
40 where
41     I: ImageAccess + ?Sized,
42 {
43     handle: ash::vk::ImageView,
44     image: Arc<I>,
45     id: NonZeroU64,
46 
47     component_mapping: ComponentMapping,
48     format: Option<Format>,
49     format_features: FormatFeatures,
50     sampler_ycbcr_conversion: Option<Arc<SamplerYcbcrConversion>>,
51     subresource_range: ImageSubresourceRange,
52     usage: ImageUsage,
53     view_type: ImageViewType,
54 
55     filter_cubic: bool,
56     filter_cubic_minmax: bool,
57 }
58 
59 impl<I> ImageView<I>
60 where
61     I: ImageAccess + ?Sized,
62 {
63     /// Creates a new `ImageView`.
64     ///
65     /// # Panics
66     ///
67     /// - Panics if `create_info.array_layers` is empty.
68     /// - Panics if `create_info.mip_levels` is empty.
69     /// - Panics if `create_info.aspects` contains any aspects other than `color`, `depth`,
70     ///   `stencil`, `plane0`, `plane1` or `plane2`.
71     /// - Panics if `create_info.aspects` contains more more than one aspect, unless `depth` and
72     ///   `stencil` are the only aspects selected.
new( image: Arc<I>, create_info: ImageViewCreateInfo, ) -> Result<Arc<ImageView<I>>, ImageViewCreationError>73     pub fn new(
74         image: Arc<I>,
75         create_info: ImageViewCreateInfo,
76     ) -> Result<Arc<ImageView<I>>, ImageViewCreationError> {
77         let format_features = Self::validate_new(&image, &create_info)?;
78 
79         unsafe {
80             Ok(Self::new_unchecked_with_format_features(
81                 image,
82                 create_info,
83                 format_features,
84             )?)
85         }
86     }
87 
validate_new( image: &I, create_info: &ImageViewCreateInfo, ) -> Result<FormatFeatures, ImageViewCreationError>88     fn validate_new(
89         image: &I,
90         create_info: &ImageViewCreateInfo,
91     ) -> Result<FormatFeatures, ImageViewCreationError> {
92         let &ImageViewCreateInfo {
93             view_type,
94             format,
95             component_mapping,
96             ref subresource_range,
97             mut usage,
98             ref sampler_ycbcr_conversion,
99             _ne: _,
100         } = create_info;
101 
102         let image_inner = image.inner().image;
103         let device = image_inner.device();
104         let format = format.unwrap();
105 
106         let level_count = subresource_range.mip_levels.end - subresource_range.mip_levels.start;
107         let layer_count = subresource_range.array_layers.end - subresource_range.array_layers.start;
108 
109         // VUID-VkImageSubresourceRange-aspectMask-requiredbitmask
110         assert!(!subresource_range.aspects.is_empty());
111 
112         // VUID-VkImageSubresourceRange-levelCount-01720
113         assert!(level_count != 0);
114 
115         // VUID-VkImageSubresourceRange-layerCount-01721
116         assert!(layer_count != 0);
117 
118         let default_usage = Self::get_default_usage(subresource_range.aspects, image_inner);
119 
120         let has_non_default_usage = if usage.is_empty() {
121             usage = default_usage;
122             false
123         } else {
124             usage == default_usage
125         };
126 
127         // VUID-VkImageViewCreateInfo-viewType-parameter
128         view_type.validate_device(device)?;
129 
130         // VUID-VkImageViewCreateInfo-format-parameter
131         format.validate_device(device)?;
132 
133         // VUID-VkComponentMapping-r-parameter
134         component_mapping.r.validate_device(device)?;
135 
136         // VUID-VkComponentMapping-g-parameter
137         component_mapping.g.validate_device(device)?;
138 
139         // VUID-VkComponentMapping-b-parameter
140         component_mapping.b.validate_device(device)?;
141 
142         // VUID-VkComponentMapping-a-parameter
143         component_mapping.a.validate_device(device)?;
144 
145         // VUID-VkImageSubresourceRange-aspectMask-parameter
146         subresource_range.aspects.validate_device(device)?;
147 
148         assert!(!subresource_range.aspects.intersects(
149             ImageAspects::METADATA
150                 | ImageAspects::MEMORY_PLANE_0
151                 | ImageAspects::MEMORY_PLANE_1
152                 | ImageAspects::MEMORY_PLANE_2
153         ));
154         assert!({
155             subresource_range.aspects.count() == 1
156                 || subresource_range
157                     .aspects
158                     .contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
159                     && !subresource_range.aspects.intersects(
160                         ImageAspects::COLOR
161                             | ImageAspects::PLANE_0
162                             | ImageAspects::PLANE_1
163                             | ImageAspects::PLANE_2,
164                     )
165         });
166 
167         // Get format features
168         let format_features = unsafe { Self::get_format_features(format, image_inner) };
169 
170         // No VUID apparently, but this seems like something we want to check?
171         if !image_inner
172             .format()
173             .unwrap()
174             .aspects()
175             .contains(subresource_range.aspects)
176         {
177             return Err(ImageViewCreationError::ImageAspectsNotCompatible {
178                 aspects: subresource_range.aspects,
179                 image_aspects: image_inner.format().unwrap().aspects(),
180             });
181         }
182 
183         // VUID-VkImageViewCreateInfo-None-02273
184         if format_features == FormatFeatures::default() {
185             return Err(ImageViewCreationError::FormatNotSupported);
186         }
187 
188         // Check for compatibility with the image
189         let image_type = image.dimensions().image_type();
190 
191         // VUID-VkImageViewCreateInfo-subResourceRange-01021
192         if !view_type.is_compatible_with(image_type) {
193             return Err(ImageViewCreationError::ImageTypeNotCompatible);
194         }
195 
196         // VUID-VkImageViewCreateInfo-image-01003
197         if (view_type == ImageViewType::Cube || view_type == ImageViewType::CubeArray)
198             && !image_inner
199                 .flags()
200                 .intersects(ImageCreateFlags::CUBE_COMPATIBLE)
201         {
202             return Err(ImageViewCreationError::ImageNotCubeCompatible);
203         }
204 
205         // VUID-VkImageViewCreateInfo-viewType-01004
206         if view_type == ImageViewType::CubeArray && !device.enabled_features().image_cube_array {
207             return Err(ImageViewCreationError::RequirementNotMet {
208                 required_for: "`create_info.viewtype` is `ImageViewType::CubeArray`",
209                 requires_one_of: RequiresOneOf {
210                     features: &["image_cube_array"],
211                     ..Default::default()
212                 },
213             });
214         }
215 
216         // VUID-VkImageViewCreateInfo-subresourceRange-01718
217         if subresource_range.mip_levels.end > image_inner.mip_levels() {
218             return Err(ImageViewCreationError::MipLevelsOutOfRange {
219                 range_end: subresource_range.mip_levels.end,
220                 max: image_inner.mip_levels(),
221             });
222         }
223 
224         if image_type == ImageType::Dim3d
225             && (view_type == ImageViewType::Dim2d || view_type == ImageViewType::Dim2dArray)
226         {
227             // VUID-VkImageViewCreateInfo-image-01005
228             if !image_inner
229                 .flags()
230                 .intersects(ImageCreateFlags::ARRAY_2D_COMPATIBLE)
231             {
232                 return Err(ImageViewCreationError::ImageNotArray2dCompatible);
233             }
234 
235             // VUID-VkImageViewCreateInfo-image-04970
236             if level_count != 1 {
237                 return Err(ImageViewCreationError::Array2dCompatibleMultipleMipLevels);
238             }
239 
240             // VUID-VkImageViewCreateInfo-image-02724
241             // VUID-VkImageViewCreateInfo-subresourceRange-02725
242             // We're using the depth dimension as array layers, but because of mip scaling, the
243             // depth, and therefore number of layers available, shrinks as the mip level gets
244             // higher.
245             let max = image_inner
246                 .dimensions()
247                 .mip_level_dimensions(subresource_range.mip_levels.start)
248                 .unwrap()
249                 .depth();
250             if subresource_range.array_layers.end > max {
251                 return Err(ImageViewCreationError::ArrayLayersOutOfRange {
252                     range_end: subresource_range.array_layers.end,
253                     max,
254                 });
255             }
256         } else {
257             // VUID-VkImageViewCreateInfo-image-01482
258             // VUID-VkImageViewCreateInfo-subresourceRange-01483
259             if subresource_range.array_layers.end > image_inner.dimensions().array_layers() {
260                 return Err(ImageViewCreationError::ArrayLayersOutOfRange {
261                     range_end: subresource_range.array_layers.end,
262                     max: image_inner.dimensions().array_layers(),
263                 });
264             }
265         }
266 
267         // VUID-VkImageViewCreateInfo-image-04972
268         if image_inner.samples() != SampleCount::Sample1
269             && !(view_type == ImageViewType::Dim2d || view_type == ImageViewType::Dim2dArray)
270         {
271             return Err(ImageViewCreationError::MultisamplingNot2d);
272         }
273 
274         /* Check usage requirements */
275 
276         if has_non_default_usage {
277             if !(device.api_version() >= Version::V1_1
278                 || device.enabled_extensions().khr_maintenance2)
279             {
280                 return Err(ImageViewCreationError::RequirementNotMet {
281                     required_for: "`create_info.usage` is not the default value",
282                     requires_one_of: RequiresOneOf {
283                         api_version: Some(Version::V1_1),
284                         device_extensions: &["khr_maintenance2"],
285                         ..Default::default()
286                     },
287                 });
288             }
289 
290             // VUID-VkImageViewUsageCreateInfo-usage-parameter
291             usage.validate_device(device)?;
292 
293             // VUID-VkImageViewUsageCreateInfo-usage-requiredbitmask
294             assert!(!usage.is_empty());
295 
296             // VUID-VkImageViewCreateInfo-pNext-02662
297             // VUID-VkImageViewCreateInfo-pNext-02663
298             // VUID-VkImageViewCreateInfo-pNext-02664
299             if !default_usage.contains(usage) {
300                 return Err(ImageViewCreationError::UsageNotSupportedByImage {
301                     usage,
302                     supported_usage: default_usage,
303                 });
304             }
305         }
306 
307         // VUID-VkImageViewCreateInfo-image-04441
308         if !image_inner.usage().intersects(
309             ImageUsage::SAMPLED
310                 | ImageUsage::STORAGE
311                 | ImageUsage::COLOR_ATTACHMENT
312                 | ImageUsage::DEPTH_STENCIL_ATTACHMENT
313                 | ImageUsage::INPUT_ATTACHMENT
314                 | ImageUsage::TRANSIENT_ATTACHMENT,
315         ) {
316             return Err(ImageViewCreationError::ImageMissingUsage);
317         }
318 
319         // VUID-VkImageViewCreateInfo-usage-02274
320         if usage.intersects(ImageUsage::SAMPLED)
321             && !format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
322         {
323             return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "sampled" });
324         }
325 
326         // VUID-VkImageViewCreateInfo-usage-02275
327         if usage.intersects(ImageUsage::STORAGE)
328             && !format_features.intersects(FormatFeatures::STORAGE_IMAGE)
329         {
330             return Err(ImageViewCreationError::FormatUsageNotSupported { usage: "storage" });
331         }
332 
333         // VUID-VkImageViewCreateInfo-usage-02276
334         if usage.intersects(ImageUsage::COLOR_ATTACHMENT)
335             && !format_features.intersects(FormatFeatures::COLOR_ATTACHMENT)
336         {
337             return Err(ImageViewCreationError::FormatUsageNotSupported {
338                 usage: "color_attachment",
339             });
340         }
341 
342         // VUID-VkImageViewCreateInfo-usage-02277
343         if usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
344             && !format_features.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
345         {
346             return Err(ImageViewCreationError::FormatUsageNotSupported {
347                 usage: "depth_stencil_attachment",
348             });
349         }
350 
351         // VUID-VkImageViewCreateInfo-usage-02652
352         if usage.intersects(ImageUsage::INPUT_ATTACHMENT)
353             && !format_features.intersects(
354                 FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT,
355             )
356         {
357             return Err(ImageViewCreationError::FormatUsageNotSupported {
358                 usage: "input_attachment",
359             });
360         }
361 
362         /* Check flags requirements */
363 
364         if Some(format) != image_inner.format() {
365             // VUID-VkImageViewCreateInfo-image-01762
366             if !image_inner
367                 .flags()
368                 .intersects(ImageCreateFlags::MUTABLE_FORMAT)
369                 || !image_inner.format().unwrap().planes().is_empty()
370                     && subresource_range.aspects.intersects(ImageAspects::COLOR)
371             {
372                 return Err(ImageViewCreationError::FormatNotCompatible);
373             }
374 
375             // VUID-VkImageViewCreateInfo-imageViewFormatReinterpretation-04466
376             // TODO: it is unclear what the number of bits is for compressed formats.
377             // See https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/2361
378             if device.enabled_extensions().khr_portability_subset
379                 && !device.enabled_features().image_view_format_reinterpretation
380                 && format.components() != image_inner.format().unwrap().components()
381             {
382                 return Err(ImageViewCreationError::RequirementNotMet {
383                     required_for: "this device is a portability subset device, and the format of \
384                         the image view does not have the same components and number of bits per \
385                         component as the parent image",
386                     requires_one_of: RequiresOneOf {
387                         features: &["image_view_format_reinterpretation"],
388                         ..Default::default()
389                     },
390                 });
391             }
392 
393             if image_inner
394                 .flags()
395                 .intersects(ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE)
396             {
397                 // VUID-VkImageViewCreateInfo-image-01583
398                 if !(format.compatibility() == image_inner.format().unwrap().compatibility()
399                     || format.block_size() == image_inner.format().unwrap().block_size())
400                 {
401                     return Err(ImageViewCreationError::FormatNotCompatible);
402                 }
403 
404                 if format.compression().is_none() {
405                     // VUID-VkImageViewCreateInfo-image-01584
406                     if layer_count != 1 {
407                         return Err(
408                             ImageViewCreationError::BlockTexelViewCompatibleMultipleArrayLayers,
409                         );
410                     }
411 
412                     // VUID-VkImageViewCreateInfo-image-01584
413                     if level_count != 1 {
414                         return Err(
415                             ImageViewCreationError::BlockTexelViewCompatibleMultipleMipLevels,
416                         );
417                     }
418                 }
419             } else {
420                 if image_inner.format().unwrap().planes().is_empty() {
421                     // VUID-VkImageViewCreateInfo-image-01761
422                     if format.compatibility() != image_inner.format().unwrap().compatibility() {
423                         return Err(ImageViewCreationError::FormatNotCompatible);
424                     }
425                 } else {
426                     let plane = if subresource_range.aspects.intersects(ImageAspects::PLANE_0) {
427                         0
428                     } else if subresource_range.aspects.intersects(ImageAspects::PLANE_1) {
429                         1
430                     } else if subresource_range.aspects.intersects(ImageAspects::PLANE_2) {
431                         2
432                     } else {
433                         unreachable!()
434                     };
435                     let plane_format = image_inner.format().unwrap().planes()[plane];
436 
437                     // VUID-VkImageViewCreateInfo-image-01586
438                     if format.compatibility() != plane_format.compatibility() {
439                         return Err(ImageViewCreationError::FormatNotCompatible);
440                     }
441                 }
442             }
443         }
444 
445         // VUID-VkImageViewCreateInfo-imageViewType-04973
446         if (view_type == ImageViewType::Dim1d
447             || view_type == ImageViewType::Dim2d
448             || view_type == ImageViewType::Dim3d)
449             && layer_count != 1
450         {
451             return Err(ImageViewCreationError::TypeNonArrayedMultipleArrayLayers);
452         }
453         // VUID-VkImageViewCreateInfo-viewType-02960
454         else if view_type == ImageViewType::Cube && layer_count != 6 {
455             return Err(ImageViewCreationError::TypeCubeNot6ArrayLayers);
456         }
457         // VUID-VkImageViewCreateInfo-viewType-02961
458         else if view_type == ImageViewType::CubeArray && layer_count % 6 != 0 {
459             return Err(ImageViewCreationError::TypeCubeArrayNotMultipleOf6ArrayLayers);
460         }
461 
462         // VUID-VkImageViewCreateInfo-imageViewFormatSwizzle-04465
463         if device.enabled_extensions().khr_portability_subset
464             && !device.enabled_features().image_view_format_swizzle
465             && !component_mapping.is_identity()
466         {
467             return Err(ImageViewCreationError::RequirementNotMet {
468                 required_for: "this device is a portability subset device, and \
469                     `create_info.component_mapping` is not the identity mapping",
470                 requires_one_of: RequiresOneOf {
471                     features: &["image_view_format_swizzle"],
472                     ..Default::default()
473                 },
474             });
475         }
476 
477         // VUID-VkImageViewCreateInfo-format-04714
478         // VUID-VkImageViewCreateInfo-format-04715
479         match format.ycbcr_chroma_sampling() {
480             Some(ChromaSampling::Mode422) => {
481                 if image_inner.dimensions().width() % 2 != 0 {
482                     return Err(
483                         ImageViewCreationError::FormatChromaSubsamplingInvalidImageDimensions,
484                     );
485                 }
486             }
487             Some(ChromaSampling::Mode420) => {
488                 if image_inner.dimensions().width() % 2 != 0
489                     || image_inner.dimensions().height() % 2 != 0
490                 {
491                     return Err(
492                         ImageViewCreationError::FormatChromaSubsamplingInvalidImageDimensions,
493                     );
494                 }
495             }
496             _ => (),
497         }
498 
499         // Don't need to check features because you can't create a conversion object without the
500         // feature anyway.
501         if let Some(conversion) = &sampler_ycbcr_conversion {
502             assert_eq!(device, conversion.device());
503 
504             // VUID-VkImageViewCreateInfo-pNext-01970
505             if !component_mapping.is_identity() {
506                 return Err(
507                     ImageViewCreationError::SamplerYcbcrConversionComponentMappingNotIdentity {
508                         component_mapping,
509                     },
510                 );
511             }
512         } else {
513             // VUID-VkImageViewCreateInfo-format-06415
514             if format.ycbcr_chroma_sampling().is_some() {
515                 return Err(
516                     ImageViewCreationError::FormatRequiresSamplerYcbcrConversion { format },
517                 );
518             }
519         }
520 
521         Ok(format_features)
522     }
523 
524     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
new_unchecked( image: Arc<I>, create_info: ImageViewCreateInfo, ) -> Result<Arc<Self>, VulkanError>525     pub unsafe fn new_unchecked(
526         image: Arc<I>,
527         create_info: ImageViewCreateInfo,
528     ) -> Result<Arc<Self>, VulkanError> {
529         let format_features =
530             Self::get_format_features(create_info.format.unwrap(), image.inner().image);
531         Self::new_unchecked_with_format_features(image, create_info, format_features)
532     }
533 
new_unchecked_with_format_features( image: Arc<I>, create_info: ImageViewCreateInfo, format_features: FormatFeatures, ) -> Result<Arc<Self>, VulkanError>534     unsafe fn new_unchecked_with_format_features(
535         image: Arc<I>,
536         create_info: ImageViewCreateInfo,
537         format_features: FormatFeatures,
538     ) -> Result<Arc<Self>, VulkanError> {
539         let &ImageViewCreateInfo {
540             view_type,
541             format,
542             component_mapping,
543             ref subresource_range,
544             mut usage,
545             ref sampler_ycbcr_conversion,
546             _ne: _,
547         } = &create_info;
548 
549         let image_inner = image.inner().image;
550         let device = image_inner.device();
551 
552         let default_usage = Self::get_default_usage(subresource_range.aspects, image_inner);
553 
554         let has_non_default_usage = if usage.is_empty() {
555             usage = default_usage;
556             false
557         } else {
558             usage == default_usage
559         };
560 
561         let mut info_vk = ash::vk::ImageViewCreateInfo {
562             flags: ash::vk::ImageViewCreateFlags::empty(),
563             image: image_inner.handle(),
564             view_type: view_type.into(),
565             format: format.unwrap().into(),
566             components: component_mapping.into(),
567             subresource_range: subresource_range.clone().into(),
568             ..Default::default()
569         };
570         let mut image_view_usage_info_vk = None;
571         let mut sampler_ycbcr_conversion_info_vk = None;
572 
573         if has_non_default_usage {
574             let next = image_view_usage_info_vk.insert(ash::vk::ImageViewUsageCreateInfo {
575                 usage: usage.into(),
576                 ..Default::default()
577             });
578 
579             next.p_next = info_vk.p_next;
580             info_vk.p_next = next as *const _ as *const _;
581         }
582 
583         if let Some(conversion) = sampler_ycbcr_conversion {
584             let next =
585                 sampler_ycbcr_conversion_info_vk.insert(ash::vk::SamplerYcbcrConversionInfo {
586                     conversion: conversion.handle(),
587                     ..Default::default()
588                 });
589 
590             next.p_next = info_vk.p_next;
591             info_vk.p_next = next as *const _ as *const _;
592         }
593 
594         let handle = {
595             let fns = device.fns();
596             let mut output = MaybeUninit::uninit();
597             (fns.v1_0.create_image_view)(
598                 device.handle(),
599                 &info_vk,
600                 ptr::null(),
601                 output.as_mut_ptr(),
602             )
603             .result()
604             .map_err(VulkanError::from)?;
605             output.assume_init()
606         };
607 
608         Self::from_handle_with_format_features(image, handle, create_info, format_features)
609     }
610 
611     /// Creates a default `ImageView`. Equivalent to
612     /// `ImageView::new(image, ImageViewCreateInfo::from_image(image))`.
new_default(image: Arc<I>) -> Result<Arc<ImageView<I>>, ImageViewCreationError>613     pub fn new_default(image: Arc<I>) -> Result<Arc<ImageView<I>>, ImageViewCreationError> {
614         let create_info = ImageViewCreateInfo::from_image(&image);
615         Self::new(image, create_info)
616     }
617 
618     /// Creates a new `ImageView` from a raw object handle.
619     ///
620     /// # Safety
621     ///
622     /// - `handle` must be a valid Vulkan object handle created from `image`.
623     /// - `create_info` must match the info used to create the object.
from_handle( image: Arc<I>, handle: ash::vk::ImageView, create_info: ImageViewCreateInfo, ) -> Result<Arc<Self>, VulkanError>624     pub unsafe fn from_handle(
625         image: Arc<I>,
626         handle: ash::vk::ImageView,
627         create_info: ImageViewCreateInfo,
628     ) -> Result<Arc<Self>, VulkanError> {
629         let format_features =
630             Self::get_format_features(create_info.format.unwrap(), image.inner().image);
631         Self::from_handle_with_format_features(image, handle, create_info, format_features)
632     }
633 
from_handle_with_format_features( image: Arc<I>, handle: ash::vk::ImageView, create_info: ImageViewCreateInfo, format_features: FormatFeatures, ) -> Result<Arc<Self>, VulkanError>634     unsafe fn from_handle_with_format_features(
635         image: Arc<I>,
636         handle: ash::vk::ImageView,
637         create_info: ImageViewCreateInfo,
638         format_features: FormatFeatures,
639     ) -> Result<Arc<Self>, VulkanError> {
640         let ImageViewCreateInfo {
641             view_type,
642             format,
643             component_mapping,
644             subresource_range,
645             mut usage,
646             sampler_ycbcr_conversion,
647             _ne: _,
648         } = create_info;
649 
650         let image_inner = image.inner().image;
651         let device = image_inner.device();
652 
653         if usage.is_empty() {
654             usage = Self::get_default_usage(subresource_range.aspects, image_inner);
655         }
656 
657         let mut filter_cubic = false;
658         let mut filter_cubic_minmax = false;
659 
660         if device
661             .physical_device()
662             .supported_extensions()
663             .ext_filter_cubic
664         {
665             // Use unchecked, because all validation has been done above or is validated by the
666             // image.
667             let properties =
668                 device
669                     .physical_device()
670                     .image_format_properties_unchecked(ImageFormatInfo {
671                         flags: image_inner.flags(),
672                         format: image_inner.format(),
673                         image_type: image.dimensions().image_type(),
674                         tiling: image_inner.tiling(),
675                         usage: image_inner.usage(),
676                         image_view_type: Some(view_type),
677                         ..Default::default()
678                     })?;
679 
680             if let Some(properties) = properties {
681                 filter_cubic = properties.filter_cubic;
682                 filter_cubic_minmax = properties.filter_cubic_minmax;
683             }
684         }
685 
686         Ok(Arc::new(ImageView {
687             handle,
688             image,
689             id: Self::next_id(),
690             view_type,
691             format,
692             format_features,
693             component_mapping,
694             subresource_range,
695             usage,
696             sampler_ycbcr_conversion,
697             filter_cubic,
698             filter_cubic_minmax,
699         }))
700     }
701 
702     // https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkImageViewCreateInfo.html#_description
get_default_usage(aspects: ImageAspects, image: &Image) -> ImageUsage703     fn get_default_usage(aspects: ImageAspects, image: &Image) -> ImageUsage {
704         let has_stencil_aspect = aspects.intersects(ImageAspects::STENCIL);
705         let has_non_stencil_aspect = !(aspects - ImageAspects::STENCIL).is_empty();
706 
707         if has_stencil_aspect && has_non_stencil_aspect {
708             image.usage() & image.stencil_usage()
709         } else if has_stencil_aspect {
710             image.stencil_usage()
711         } else if has_non_stencil_aspect {
712             image.usage()
713         } else {
714             unreachable!()
715         }
716     }
717 
718     // https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/chap12.html#resources-image-view-format-features
get_format_features(format: Format, image: &Image) -> FormatFeatures719     unsafe fn get_format_features(format: Format, image: &Image) -> FormatFeatures {
720         let device = image.device();
721 
722         let mut format_features = if Some(format) != image.format() {
723             // Use unchecked, because all validation should have been done before calling.
724             let format_properties = device.physical_device().format_properties_unchecked(format);
725 
726             match image.tiling() {
727                 ImageTiling::Optimal => format_properties.optimal_tiling_features,
728                 ImageTiling::Linear => format_properties.linear_tiling_features,
729                 ImageTiling::DrmFormatModifier => format_properties.linear_tiling_features,
730             }
731         } else {
732             image.format_features()
733         };
734 
735         if !device.enabled_extensions().khr_format_feature_flags2 {
736             if format.type_color().is_none()
737                 && format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
738             {
739                 format_features |= FormatFeatures::SAMPLED_IMAGE_DEPTH_COMPARISON;
740             }
741 
742             if format.shader_storage_image_without_format() {
743                 if device
744                     .enabled_features()
745                     .shader_storage_image_read_without_format
746                 {
747                     format_features |= FormatFeatures::STORAGE_READ_WITHOUT_FORMAT;
748                 }
749 
750                 if device
751                     .enabled_features()
752                     .shader_storage_image_write_without_format
753                 {
754                     format_features |= FormatFeatures::STORAGE_WRITE_WITHOUT_FORMAT;
755                 }
756             }
757         }
758 
759         format_features
760     }
761 
762     /// Returns the wrapped image that this image view was created from.
image(&self) -> &Arc<I>763     pub fn image(&self) -> &Arc<I> {
764         &self.image
765     }
766 }
767 
768 impl<I> Drop for ImageView<I>
769 where
770     I: ImageAccess + ?Sized,
771 {
drop(&mut self)772     fn drop(&mut self) {
773         unsafe {
774             let device = self.device();
775             let fns = device.fns();
776             (fns.v1_0.destroy_image_view)(device.handle(), self.handle, ptr::null());
777         }
778     }
779 }
780 
781 unsafe impl<I> VulkanObject for ImageView<I>
782 where
783     I: ImageAccess + ?Sized,
784 {
785     type Handle = ash::vk::ImageView;
786 
handle(&self) -> Self::Handle787     fn handle(&self) -> Self::Handle {
788         self.handle
789     }
790 }
791 
792 unsafe impl<I> DeviceOwned for ImageView<I>
793 where
794     I: ImageAccess + ?Sized,
795 {
device(&self) -> &Arc<Device>796     fn device(&self) -> &Arc<Device> {
797         self.image.inner().image.device()
798     }
799 }
800 
801 impl_id_counter!(ImageView<I: ImageAccess + ?Sized>);
802 
803 /// Parameters to create a new `ImageView`.
804 #[derive(Debug)]
805 pub struct ImageViewCreateInfo {
806     /// The image view type.
807     ///
808     /// The view type must be compatible with the dimensions of the image and the selected array
809     /// layers.
810     ///
811     /// The default value is [`ImageViewType::Dim2d`].
812     pub view_type: ImageViewType,
813 
814     /// The format of the image view.
815     ///
816     /// If this is set to a format that is different from the image, the image must be created with
817     /// the `mutable_format` flag.
818     ///
819     /// On [portability subset](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag)
820     /// devices, if `format` does not have the same number of components and bits per component as
821     /// the parent image's format, the
822     /// [`image_view_format_reinterpretation`](crate::device::Features::image_view_format_reinterpretation)
823     /// feature must be enabled on the device.
824     ///
825     /// The default value is `None`, which must be overridden.
826     pub format: Option<Format>,
827 
828     /// How to map components of each pixel.
829     ///
830     /// On [portability subset](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag)
831     /// devices, if `component_mapping` is not the identity mapping, the
832     /// [`image_view_format_swizzle`](crate::device::Features::image_view_format_swizzle)
833     /// feature must be enabled on the device.
834     ///
835     /// The default value is [`ComponentMapping::identity()`].
836     pub component_mapping: ComponentMapping,
837 
838     /// The subresource range of the image that the view should cover.
839     ///
840     /// The default value is empty, which must be overridden.
841     pub subresource_range: ImageSubresourceRange,
842 
843     /// How the image view is going to be used.
844     ///
845     /// If `usage` is empty, then a default value is used based on the parent image's usages.
846     /// Depending on the image aspects selected in `subresource_range`,
847     /// the default `usage` will be equal to the parent image's `usage`, its `stencil_usage`,
848     /// or the intersection of the two.
849     ///
850     /// If you set `usage` to a different value from the default, then the device API version must
851     /// be at least 1.1, or the [`khr_maintenance2`](crate::device::DeviceExtensions::khr_maintenance2)
852     /// extension must be enabled on the device. The specified `usage` must be a subset of the
853     /// default value; usages that are not set for the parent image are not allowed.
854     ///
855     /// The default value is [`ImageUsage::empty()`].
856     pub usage: ImageUsage,
857 
858     /// The sampler YCbCr conversion to be used with the image view.
859     ///
860     /// If set to `Some`, several restrictions apply:
861     /// - The `component_mapping` must be the identity swizzle for all components.
862     /// - If the image view is to be used in a shader, it must be in a combined image sampler
863     ///   descriptor, a separate sampled image descriptor is not allowed.
864     /// - The corresponding sampler must have the same sampler YCbCr object or an identically
865     ///   created one, and must be used as an immutable sampler within a descriptor set layout.
866     ///
867     /// The default value is `None`.
868     pub sampler_ycbcr_conversion: Option<Arc<SamplerYcbcrConversion>>,
869 
870     pub _ne: crate::NonExhaustive,
871 }
872 
873 impl Default for ImageViewCreateInfo {
874     #[inline]
default() -> Self875     fn default() -> Self {
876         Self {
877             view_type: ImageViewType::Dim2d,
878             format: None,
879             component_mapping: ComponentMapping::identity(),
880             subresource_range: ImageSubresourceRange {
881                 aspects: ImageAspects::empty(),
882                 array_layers: 0..0,
883                 mip_levels: 0..0,
884             },
885             usage: ImageUsage::empty(),
886             sampler_ycbcr_conversion: None,
887             _ne: crate::NonExhaustive(()),
888         }
889     }
890 }
891 
892 impl ImageViewCreateInfo {
893     /// Returns an `ImageViewCreateInfo` with the `view_type` determined from the image type and
894     /// array layers, and `subresource_range` determined from the image format and covering the
895     /// whole image.
from_image(image: &(impl ImageAccess + ?Sized)) -> Self896     pub fn from_image(image: &(impl ImageAccess + ?Sized)) -> Self {
897         Self {
898             view_type: match image.dimensions() {
899                 ImageDimensions::Dim1d {
900                     array_layers: 1, ..
901                 } => ImageViewType::Dim1d,
902                 ImageDimensions::Dim1d { .. } => ImageViewType::Dim1dArray,
903                 ImageDimensions::Dim2d {
904                     array_layers: 1, ..
905                 } => ImageViewType::Dim2d,
906                 ImageDimensions::Dim2d { .. } => ImageViewType::Dim2dArray,
907                 ImageDimensions::Dim3d { .. } => ImageViewType::Dim3d,
908             },
909             format: Some(image.format()),
910             subresource_range: image.subresource_range(),
911             ..Default::default()
912         }
913     }
914 }
915 
916 /// Error that can happen when creating an image view.
917 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
918 pub enum ImageViewCreationError {
919     /// Allocating memory failed.
920     OomError(OomError),
921 
922     RequirementNotMet {
923         required_for: &'static str,
924         requires_one_of: RequiresOneOf,
925     },
926 
927     /// A 2D image view was requested from a 3D image, but a range of multiple mip levels was
928     /// specified.
929     Array2dCompatibleMultipleMipLevels,
930 
931     /// The specified range of array layers was not a subset of those in the image.
932     ArrayLayersOutOfRange { range_end: u32, max: u32 },
933 
934     /// The image has the `block_texel_view_compatible` flag, but a range of multiple array layers
935     /// was specified.
936     BlockTexelViewCompatibleMultipleArrayLayers,
937 
938     /// The image has the `block_texel_view_compatible` flag, but a range of multiple mip levels
939     /// was specified.
940     BlockTexelViewCompatibleMultipleMipLevels,
941 
942     /// The requested format has chroma subsampling, but the width and/or height of the image was
943     /// not a multiple of 2.
944     FormatChromaSubsamplingInvalidImageDimensions,
945 
946     /// The requested format was not compatible with the image.
947     FormatNotCompatible,
948 
949     /// The given format was not supported by the device.
950     FormatNotSupported,
951 
952     /// The format requires a sampler YCbCr conversion, but none was provided.
953     FormatRequiresSamplerYcbcrConversion { format: Format },
954 
955     /// A requested usage flag was not supported by the given format.
956     FormatUsageNotSupported { usage: &'static str },
957 
958     /// An aspect was selected that was not present in the image.
959     ImageAspectsNotCompatible {
960         aspects: ImageAspects,
961         image_aspects: ImageAspects,
962     },
963 
964     /// The image was not created with
965     /// [one of the required usages](https://registry.khronos.org/vulkan/specs/1.2-extensions/html/vkspec.html#valid-imageview-imageusage)
966     /// for image views.
967     ImageMissingUsage,
968 
969     /// A 2D image view was requested from a 3D image, but the image was not created with the
970     /// `array_2d_compatible` flag.
971     ImageNotArray2dCompatible,
972 
973     /// A cube image view type was requested, but the image was not created with the
974     /// `cube_compatible` flag.
975     ImageNotCubeCompatible,
976 
977     /// The given image view type was not compatible with the type of the image.
978     ImageTypeNotCompatible,
979 
980     /// The requested [`ImageViewType`] was not compatible with the image, or with the specified
981     /// ranges of array layers and mipmap levels.
982     IncompatibleType,
983 
984     /// The specified range of mip levels was not a subset of those in the image.
985     MipLevelsOutOfRange { range_end: u32, max: u32 },
986 
987     /// The image has multisampling enabled, but the image view type was not `Dim2d` or
988     /// `Dim2dArray`.
989     MultisamplingNot2d,
990 
991     /// Sampler YCbCr conversion was enabled, but `component_mapping` was not the identity mapping.
992     SamplerYcbcrConversionComponentMappingNotIdentity { component_mapping: ComponentMapping },
993 
994     /// The `CubeArray` image view type was specified, but the range of array layers did not have a
995     /// size that is a multiple 6.
996     TypeCubeArrayNotMultipleOf6ArrayLayers,
997 
998     /// The `Cube` image view type was specified, but the range of array layers did not have a size
999     /// of 6.
1000     TypeCubeNot6ArrayLayers,
1001 
1002     /// A non-arrayed image view type was specified, but a range of multiple array layers was
1003     /// specified.
1004     TypeNonArrayedMultipleArrayLayers,
1005 
1006     /// The provided `usage` is not supported by the parent image.
1007     UsageNotSupportedByImage {
1008         usage: ImageUsage,
1009         supported_usage: ImageUsage,
1010     },
1011 }
1012 
1013 impl Error for ImageViewCreationError {
source(&self) -> Option<&(dyn Error + 'static)>1014     fn source(&self) -> Option<&(dyn Error + 'static)> {
1015         match self {
1016             ImageViewCreationError::OomError(err) => Some(err),
1017             _ => None,
1018         }
1019     }
1020 }
1021 
1022 impl Display for ImageViewCreationError {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>1023     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
1024         match self {
1025             Self::OomError(_) => write!(f, "allocating memory failed",),
1026             Self::RequirementNotMet {
1027                 required_for,
1028                 requires_one_of,
1029             } => write!(
1030                 f,
1031                 "a requirement was not met for: {}; requires one of: {}",
1032                 required_for, requires_one_of,
1033             ),
1034             Self::Array2dCompatibleMultipleMipLevels => write!(
1035                 f,
1036                 "a 2D image view was requested from a 3D image, but a range of multiple mip levels \
1037                 was specified",
1038             ),
1039             Self::ArrayLayersOutOfRange { .. } => write!(
1040                 f,
1041                 "the specified range of array layers was not a subset of those in the image",
1042             ),
1043             Self::BlockTexelViewCompatibleMultipleArrayLayers => write!(
1044                 f,
1045                 "the image has the `block_texel_view_compatible` flag, but a range of multiple \
1046                 array layers was specified",
1047             ),
1048             Self::BlockTexelViewCompatibleMultipleMipLevels => write!(
1049                 f,
1050                 "the image has the `block_texel_view_compatible` flag, but a range of multiple mip \
1051                 levels was specified",
1052             ),
1053             Self::FormatChromaSubsamplingInvalidImageDimensions => write!(
1054                 f,
1055                 "the requested format has chroma subsampling, but the width and/or height of the \
1056                 image was not a multiple of 2",
1057             ),
1058             Self::FormatNotCompatible => {
1059                 write!(f, "the requested format was not compatible with the image")
1060             }
1061             Self::FormatNotSupported => {
1062                 write!(f, "the given format was not supported by the device")
1063             }
1064             Self::FormatRequiresSamplerYcbcrConversion { .. } => write!(
1065                 f,
1066                 "the format requires a sampler YCbCr conversion, but none was provided",
1067             ),
1068             Self::FormatUsageNotSupported { .. } => write!(
1069                 f,
1070                 "a requested usage flag was not supported by the given format",
1071             ),
1072             Self::ImageAspectsNotCompatible { .. } => write!(
1073                 f,
1074                 "an aspect was selected that was not present in the image",
1075             ),
1076             Self::ImageMissingUsage => write!(
1077                 f,
1078                 "the image was not created with one of the required usages for image views",
1079             ),
1080             Self::ImageNotArray2dCompatible => write!(
1081                 f,
1082                 "a 2D image view was requested from a 3D image, but the image was not created with \
1083                 the `array_2d_compatible` flag",
1084             ),
1085             Self::ImageNotCubeCompatible => write!(
1086                 f,
1087                 "a cube image view type was requested, but the image was not created with the \
1088                 `cube_compatible` flag",
1089             ),
1090             Self::ImageTypeNotCompatible => write!(
1091                 f,
1092                 "the given image view type was not compatible with the type of the image",
1093             ),
1094             Self::IncompatibleType => write!(
1095                 f,
1096                 "image view type is not compatible with image, array layers or mipmap levels",
1097             ),
1098             Self::MipLevelsOutOfRange { .. } => write!(
1099                 f,
1100                 "the specified range of mip levels was not a subset of those in the image",
1101             ),
1102             Self::MultisamplingNot2d => write!(
1103                 f,
1104                 "the image has multisampling enabled, but the image view type was not `Dim2d` or \
1105                 `Dim2dArray`",
1106             ),
1107             Self::SamplerYcbcrConversionComponentMappingNotIdentity { .. } => write!(
1108                 f,
1109                 "sampler YCbCr conversion was enabled, but `component_mapping` was not the \
1110                 identity mapping",
1111             ),
1112             Self::TypeCubeArrayNotMultipleOf6ArrayLayers => write!(
1113                 f,
1114                 "the `CubeArray` image view type was specified, but the range of array layers did \
1115                 not have a size that is a multiple 6",
1116             ),
1117             Self::TypeCubeNot6ArrayLayers => write!(
1118                 f,
1119                 "the `Cube` image view type was specified, but the range of array layers did not \
1120                 have a size of 6",
1121             ),
1122             Self::TypeNonArrayedMultipleArrayLayers => write!(
1123                 f,
1124                 "a non-arrayed image view type was specified, but a range of multiple array layers \
1125                 was specified",
1126             ),
1127             Self::UsageNotSupportedByImage {
1128                 usage: _,
1129                 supported_usage: _,
1130             } => write!(
1131                 f,
1132                 "the provided `usage` is not supported by the parent image",
1133             ),
1134         }
1135     }
1136 }
1137 
1138 impl From<OomError> for ImageViewCreationError {
from(err: OomError) -> ImageViewCreationError1139     fn from(err: OomError) -> ImageViewCreationError {
1140         ImageViewCreationError::OomError(err)
1141     }
1142 }
1143 
1144 impl From<VulkanError> for ImageViewCreationError {
from(err: VulkanError) -> ImageViewCreationError1145     fn from(err: VulkanError) -> ImageViewCreationError {
1146         match err {
1147             err @ VulkanError::OutOfHostMemory => OomError::from(err).into(),
1148             err @ VulkanError::OutOfDeviceMemory => OomError::from(err).into(),
1149             _ => panic!("unexpected error: {:?}", err),
1150         }
1151     }
1152 }
1153 
1154 impl From<RequirementNotMet> for ImageViewCreationError {
from(err: RequirementNotMet) -> Self1155     fn from(err: RequirementNotMet) -> Self {
1156         Self::RequirementNotMet {
1157             required_for: err.required_for,
1158             requires_one_of: err.requires_one_of,
1159         }
1160     }
1161 }
1162 
1163 vulkan_enum! {
1164     #[non_exhaustive]
1165 
1166     /// The geometry type of an image view.
1167     ImageViewType impl {
1168         /// Returns whether the type is arrayed.
1169         #[inline]
1170         pub fn is_arrayed(self) -> bool {
1171             match self {
1172                 Self::Dim1d | Self::Dim2d | Self::Dim3d | Self::Cube => false,
1173                 Self::Dim1dArray | Self::Dim2dArray | Self::CubeArray => true,
1174             }
1175         }
1176 
1177         /// Returns whether `self` is compatible with the given `image_type`.
1178         #[inline]
1179         pub fn is_compatible_with(self, image_type: ImageType) -> bool {
1180             matches!(
1181                 (self, image_type,),
1182                 (
1183                     ImageViewType::Dim1d | ImageViewType::Dim1dArray,
1184                     ImageType::Dim1d
1185                 ) | (
1186                     ImageViewType::Dim2d | ImageViewType::Dim2dArray,
1187                     ImageType::Dim2d | ImageType::Dim3d
1188                 ) | (
1189                     ImageViewType::Cube | ImageViewType::CubeArray,
1190                     ImageType::Dim2d
1191                 ) | (ImageViewType::Dim3d, ImageType::Dim3d)
1192             )
1193         }
1194     }
1195     = ImageViewType(i32);
1196 
1197     // TODO: document
1198     Dim1d = TYPE_1D,
1199 
1200     // TODO: document
1201     Dim2d = TYPE_2D,
1202 
1203     // TODO: document
1204     Dim3d = TYPE_3D,
1205 
1206     // TODO: document
1207     Cube = CUBE,
1208 
1209     // TODO: document
1210     Dim1dArray = TYPE_1D_ARRAY,
1211 
1212     // TODO: document
1213     Dim2dArray = TYPE_2D_ARRAY,
1214 
1215     // TODO: document
1216     CubeArray = CUBE_ARRAY,
1217 }
1218 
1219 /// Trait for types that represent the GPU can access an image view.
1220 pub unsafe trait ImageViewAbstract:
1221     VulkanObject<Handle = ash::vk::ImageView> + DeviceOwned + Debug + Send + Sync
1222 {
1223     /// Returns the wrapped image that this image view was created from.
image(&self) -> Arc<dyn ImageAccess>1224     fn image(&self) -> Arc<dyn ImageAccess>;
1225 
1226     /// Returns the component mapping of this view.
component_mapping(&self) -> ComponentMapping1227     fn component_mapping(&self) -> ComponentMapping;
1228 
1229     /// Returns the dimensions of this view.
1230     #[inline]
dimensions(&self) -> ImageDimensions1231     fn dimensions(&self) -> ImageDimensions {
1232         let subresource_range = self.subresource_range();
1233         let array_layers =
1234             subresource_range.array_layers.end - subresource_range.array_layers.start;
1235 
1236         match self.image().dimensions() {
1237             ImageDimensions::Dim1d { width, .. } => ImageDimensions::Dim1d {
1238                 width,
1239                 array_layers,
1240             },
1241             ImageDimensions::Dim2d { width, height, .. } => ImageDimensions::Dim2d {
1242                 width,
1243                 height,
1244                 array_layers,
1245             },
1246             ImageDimensions::Dim3d {
1247                 width,
1248                 height,
1249                 depth,
1250             } => ImageDimensions::Dim3d {
1251                 width,
1252                 height,
1253                 depth,
1254             },
1255         }
1256     }
1257 
1258     /// Returns whether the image view supports sampling with a
1259     /// [`Cubic`](crate::sampler::Filter::Cubic) `mag_filter` or `min_filter`.
filter_cubic(&self) -> bool1260     fn filter_cubic(&self) -> bool;
1261 
1262     /// Returns whether the image view supports sampling with a
1263     /// [`Cubic`](crate::sampler::Filter::Cubic) `mag_filter` or `min_filter`, and with a
1264     /// [`Min`](crate::sampler::SamplerReductionMode::Min) or
1265     /// [`Max`](crate::sampler::SamplerReductionMode::Max) `reduction_mode`.
filter_cubic_minmax(&self) -> bool1266     fn filter_cubic_minmax(&self) -> bool;
1267 
1268     /// Returns the format of this view. This can be different from the parent's format.
format(&self) -> Option<Format>1269     fn format(&self) -> Option<Format>;
1270 
1271     /// Returns the features supported by the image view's format.
format_features(&self) -> FormatFeatures1272     fn format_features(&self) -> FormatFeatures;
1273 
1274     /// Returns the sampler YCbCr conversion that this image view was created with, if any.
sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>>1275     fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>>;
1276 
1277     /// Returns the subresource range of the wrapped image that this view exposes.
subresource_range(&self) -> &ImageSubresourceRange1278     fn subresource_range(&self) -> &ImageSubresourceRange;
1279 
1280     /// Returns the usage of the image view.
usage(&self) -> ImageUsage1281     fn usage(&self) -> ImageUsage;
1282 
1283     /// Returns the [`ImageViewType`] of this image view.
view_type(&self) -> ImageViewType1284     fn view_type(&self) -> ImageViewType;
1285 }
1286 
1287 unsafe impl<I> ImageViewAbstract for ImageView<I>
1288 where
1289     I: ImageAccess + Debug + 'static,
1290 {
image(&self) -> Arc<dyn ImageAccess>1291     fn image(&self) -> Arc<dyn ImageAccess> {
1292         self.image.clone()
1293     }
1294 
component_mapping(&self) -> ComponentMapping1295     fn component_mapping(&self) -> ComponentMapping {
1296         self.component_mapping
1297     }
1298 
filter_cubic(&self) -> bool1299     fn filter_cubic(&self) -> bool {
1300         self.filter_cubic
1301     }
1302 
filter_cubic_minmax(&self) -> bool1303     fn filter_cubic_minmax(&self) -> bool {
1304         self.filter_cubic_minmax
1305     }
1306 
format(&self) -> Option<Format>1307     fn format(&self) -> Option<Format> {
1308         self.format
1309     }
1310 
format_features(&self) -> FormatFeatures1311     fn format_features(&self) -> FormatFeatures {
1312         self.format_features
1313     }
1314 
sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>>1315     fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>> {
1316         self.sampler_ycbcr_conversion.as_ref()
1317     }
1318 
subresource_range(&self) -> &ImageSubresourceRange1319     fn subresource_range(&self) -> &ImageSubresourceRange {
1320         &self.subresource_range
1321     }
1322 
usage(&self) -> ImageUsage1323     fn usage(&self) -> ImageUsage {
1324         self.usage
1325     }
1326 
view_type(&self) -> ImageViewType1327     fn view_type(&self) -> ImageViewType {
1328         self.view_type
1329     }
1330 }
1331 
1332 unsafe impl ImageViewAbstract for ImageView<dyn ImageAccess> {
1333     #[inline]
image(&self) -> Arc<dyn ImageAccess>1334     fn image(&self) -> Arc<dyn ImageAccess> {
1335         self.image.clone()
1336     }
1337 
1338     #[inline]
component_mapping(&self) -> ComponentMapping1339     fn component_mapping(&self) -> ComponentMapping {
1340         self.component_mapping
1341     }
1342 
1343     #[inline]
filter_cubic(&self) -> bool1344     fn filter_cubic(&self) -> bool {
1345         self.filter_cubic
1346     }
1347 
1348     #[inline]
filter_cubic_minmax(&self) -> bool1349     fn filter_cubic_minmax(&self) -> bool {
1350         self.filter_cubic_minmax
1351     }
1352 
1353     #[inline]
format(&self) -> Option<Format>1354     fn format(&self) -> Option<Format> {
1355         self.format
1356     }
1357 
1358     #[inline]
format_features(&self) -> FormatFeatures1359     fn format_features(&self) -> FormatFeatures {
1360         self.format_features
1361     }
1362 
1363     #[inline]
sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>>1364     fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>> {
1365         self.sampler_ycbcr_conversion.as_ref()
1366     }
1367 
1368     #[inline]
subresource_range(&self) -> &ImageSubresourceRange1369     fn subresource_range(&self) -> &ImageSubresourceRange {
1370         &self.subresource_range
1371     }
1372 
1373     #[inline]
usage(&self) -> ImageUsage1374     fn usage(&self) -> ImageUsage {
1375         self.usage
1376     }
1377 
1378     #[inline]
view_type(&self) -> ImageViewType1379     fn view_type(&self) -> ImageViewType {
1380         self.view_type
1381     }
1382 }
1383 
1384 impl PartialEq for dyn ImageViewAbstract {
1385     #[inline]
eq(&self, other: &Self) -> bool1386     fn eq(&self, other: &Self) -> bool {
1387         self.handle() == other.handle() && self.device() == other.device()
1388     }
1389 }
1390 
1391 impl Eq for dyn ImageViewAbstract {}
1392 
1393 impl Hash for dyn ImageViewAbstract {
hash<H: Hasher>(&self, state: &mut H)1394     fn hash<H: Hasher>(&self, state: &mut H) {
1395         self.handle().hash(state);
1396         self.device().hash(state);
1397     }
1398 }
1399