• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 crate::check_errors;
17 use crate::device::Device;
18 use crate::format::Format;
19 use crate::format::FormatTy;
20 use crate::image::sys::UnsafeImage;
21 use crate::image::ImageAccess;
22 use crate::image::ImageDimensions;
23 use crate::memory::DeviceMemoryAllocError;
24 use crate::sampler::Sampler;
25 use crate::OomError;
26 use crate::SafeDeref;
27 use crate::VulkanObject;
28 use std::error;
29 use std::fmt;
30 use std::hash::Hash;
31 use std::hash::Hasher;
32 use std::mem::MaybeUninit;
33 use std::ops::Range;
34 use std::ptr;
35 use std::sync::Arc;
36 
37 /// A safe image view that checks for validity and keeps its attached image alive.
38 pub struct ImageView<I>
39 where
40     I: ImageAccess,
41 {
42     image: I,
43     inner: UnsafeImageView,
44     format: Format,
45 
46     ty: ImageViewType,
47     component_mapping: ComponentMapping,
48     array_layers: Range<u32>,
49 }
50 
51 impl<I> ImageView<I>
52 where
53     I: ImageAccess,
54 {
55     /// Creates a default `ImageView`. Equivalent to `ImageView::start(image).build()`.
56     #[inline]
new(image: I) -> Result<Arc<ImageView<I>>, ImageViewCreationError>57     pub fn new(image: I) -> Result<Arc<ImageView<I>>, ImageViewCreationError> {
58         Self::start(image).build()
59     }
60 
61     /// Begins building an `ImageView`.
start(image: I) -> ImageViewBuilder<I>62     pub fn start(image: I) -> ImageViewBuilder<I> {
63         let ty = match image.dimensions() {
64             ImageDimensions::Dim1d {
65                 array_layers: 1, ..
66             } => ImageViewType::Dim1d,
67             ImageDimensions::Dim1d { .. } => ImageViewType::Dim1dArray,
68             ImageDimensions::Dim2d {
69                 array_layers: 1, ..
70             } => ImageViewType::Dim2d,
71             ImageDimensions::Dim2d { .. } => ImageViewType::Dim2dArray,
72             ImageDimensions::Dim3d { .. } => ImageViewType::Dim3d,
73         };
74         let mipmap_levels = 0..image.mipmap_levels();
75         let array_layers = 0..image.dimensions().array_layers();
76 
77         ImageViewBuilder {
78             image,
79             ty,
80             component_mapping: ComponentMapping::default(),
81             mipmap_levels,
82             array_layers,
83         }
84     }
85 
86     /// Returns the wrapped image that this image view was created from.
image(&self) -> &I87     pub fn image(&self) -> &I {
88         &self.image
89     }
90 }
91 
92 #[derive(Debug)]
93 pub struct ImageViewBuilder<I> {
94     image: I,
95     ty: ImageViewType,
96     component_mapping: ComponentMapping,
97     mipmap_levels: Range<u32>,
98     array_layers: Range<u32>,
99 }
100 
101 impl<I> ImageViewBuilder<I>
102 where
103     I: ImageAccess,
104 {
105     /// Sets the image view type.
106     ///
107     /// By default, this is determined from the image, based on its dimensions and number of layers.
108     /// The value of `ty` must be compatible with the dimensions of the image and the selected
109     /// array layers.
110     #[inline]
with_type(mut self, ty: ImageViewType) -> Self111     pub fn with_type(mut self, ty: ImageViewType) -> Self {
112         self.ty = ty;
113         self
114     }
115 
116     /// Sets how to map components of each pixel.
117     ///
118     /// By default, this is the identity mapping, with every component mapped directly.
119     #[inline]
with_component_mapping(mut self, component_mapping: ComponentMapping) -> Self120     pub fn with_component_mapping(mut self, component_mapping: ComponentMapping) -> Self {
121         self.component_mapping = component_mapping;
122         self
123     }
124 
125     /// Sets the range of mipmap levels that the view should cover.
126     ///
127     /// By default, this is the full range of mipmaps present in the image.
128     #[inline]
with_mipmap_levels(mut self, mipmap_levels: Range<u32>) -> Self129     pub fn with_mipmap_levels(mut self, mipmap_levels: Range<u32>) -> Self {
130         self.mipmap_levels = mipmap_levels;
131         self
132     }
133 
134     /// Sets the range of array layers that the view should cover.
135     ///
136     /// By default, this is the full range of array layers present in the image.
137     #[inline]
with_array_layers(mut self, array_layers: Range<u32>) -> Self138     pub fn with_array_layers(mut self, array_layers: Range<u32>) -> Self {
139         self.array_layers = array_layers;
140         self
141     }
142 
143     /// Builds the `ImageView`.
build(self) -> Result<Arc<ImageView<I>>, ImageViewCreationError>144     pub fn build(self) -> Result<Arc<ImageView<I>>, ImageViewCreationError> {
145         let dimensions = self.image.dimensions();
146         let format = self.image.format();
147         let image_inner = self.image.inner().image;
148         let usage = image_inner.usage();
149         let flags = image_inner.flags();
150 
151         if self.mipmap_levels.end <= self.mipmap_levels.start
152             || self.mipmap_levels.end > image_inner.mipmap_levels()
153         {
154             return Err(ImageViewCreationError::MipMapLevelsOutOfRange);
155         }
156 
157         if self.array_layers.end <= self.array_layers.start
158             || self.array_layers.end > dimensions.array_layers()
159         {
160             return Err(ImageViewCreationError::ArrayLayersOutOfRange);
161         }
162 
163         if !(usage.sampled
164             || usage.storage
165             || usage.color_attachment
166             || usage.depth_stencil_attachment
167             || usage.input_attachment
168             || usage.transient_attachment)
169         {
170             return Err(ImageViewCreationError::InvalidImageUsage);
171         }
172 
173         // Check for compatibility with the image
174         match (
175             self.ty,
176             self.image.dimensions(),
177             self.array_layers.end - self.array_layers.start,
178             self.mipmap_levels.end - self.mipmap_levels.start,
179         ) {
180             (ImageViewType::Dim1d, ImageDimensions::Dim1d { .. }, 1, _) => (),
181             (ImageViewType::Dim1dArray, ImageDimensions::Dim1d { .. }, _, _) => (),
182             (ImageViewType::Dim2d, ImageDimensions::Dim2d { .. }, 1, _) => (),
183             (ImageViewType::Dim2dArray, ImageDimensions::Dim2d { .. }, _, _) => (),
184             (ImageViewType::Cubemap, ImageDimensions::Dim2d { .. }, 6, _)
185                 if flags.cube_compatible =>
186             {
187                 ()
188             }
189             (ImageViewType::CubemapArray, ImageDimensions::Dim2d { .. }, n, _)
190                 if flags.cube_compatible && n % 6 == 0 =>
191             {
192                 ()
193             }
194             (ImageViewType::Dim3d, ImageDimensions::Dim3d { .. }, 1, _) => (),
195             (ImageViewType::Dim2d, ImageDimensions::Dim3d { .. }, 1, 1)
196                 if flags.array_2d_compatible =>
197             {
198                 ()
199             }
200             (ImageViewType::Dim2dArray, ImageDimensions::Dim3d { .. }, _, 1)
201                 if flags.array_2d_compatible =>
202             {
203                 ()
204             }
205             _ => return Err(ImageViewCreationError::IncompatibleType),
206         }
207 
208         let inner = unsafe {
209             UnsafeImageView::new(
210                 image_inner,
211                 self.ty,
212                 self.component_mapping,
213                 self.mipmap_levels,
214                 self.array_layers.clone(),
215             )?
216         };
217 
218         Ok(Arc::new(ImageView {
219             image: self.image,
220             inner,
221             format,
222 
223             ty: self.ty,
224             component_mapping: self.component_mapping,
225             array_layers: self.array_layers,
226         }))
227     }
228 }
229 
230 /// Error that can happen when creating an image view.
231 #[derive(Clone, Debug, PartialEq, Eq)]
232 pub enum ImageViewCreationError {
233     /// Allocating memory failed.
234     AllocError(DeviceMemoryAllocError),
235     /// The specified range of array layers was out of range for the image.
236     ArrayLayersOutOfRange,
237     /// The specified range of mipmap levels was out of range for the image.
238     MipMapLevelsOutOfRange,
239     /// The requested [`ImageViewType`] was not compatible with the image, or with the specified ranges of array layers and mipmap levels.
240     IncompatibleType,
241     /// The image was not created with
242     /// [one of the required usages](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#valid-imageview-imageusage)
243     /// for image views.
244     InvalidImageUsage,
245 }
246 
247 impl error::Error for ImageViewCreationError {
248     #[inline]
source(&self) -> Option<&(dyn error::Error + 'static)>249     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
250         match *self {
251             ImageViewCreationError::AllocError(ref err) => Some(err),
252             _ => None,
253         }
254     }
255 }
256 
257 impl fmt::Display for ImageViewCreationError {
258     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>259     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
260         write!(
261             fmt,
262             "{}",
263             match *self {
264                 ImageViewCreationError::AllocError(err) => "allocating memory failed",
265                 ImageViewCreationError::ArrayLayersOutOfRange => "array layers are out of range",
266                 ImageViewCreationError::MipMapLevelsOutOfRange => "mipmap levels are out of range",
267                 ImageViewCreationError::IncompatibleType =>
268                     "image view type is not compatible with image, array layers or mipmap levels",
269                 ImageViewCreationError::InvalidImageUsage =>
270                     "the usage of the image is not compatible with image views",
271             }
272         )
273     }
274 }
275 
276 impl From<OomError> for ImageViewCreationError {
277     #[inline]
from(err: OomError) -> ImageViewCreationError278     fn from(err: OomError) -> ImageViewCreationError {
279         ImageViewCreationError::AllocError(DeviceMemoryAllocError::OomError(err))
280     }
281 }
282 
283 /// A low-level wrapper around a `vkImageView`.
284 pub struct UnsafeImageView {
285     view: ash::vk::ImageView,
286     device: Arc<Device>,
287 }
288 
289 impl UnsafeImageView {
290     /// Creates a new view from an image.
291     ///
292     /// # Safety
293     /// - The returned `UnsafeImageView` must not outlive `image`.
294     /// - `image` must have a usage that is compatible with image views.
295     /// - `ty` must be compatible with the dimensions and flags of the image.
296     /// - `mipmap_levels` must not be empty, must be within the range of levels of the image, and be compatible with the requested `ty`.
297     /// - `array_layers` must not be empty, must be within the range of layers of the image, and be compatible with the requested `ty`.
298     ///
299     /// # Panics
300     /// Panics if the image is a YcbCr image, since the Vulkano API is not yet flexible enough to
301     /// specify the aspect of image.
new( image: &UnsafeImage, ty: ImageViewType, component_mapping: ComponentMapping, mipmap_levels: Range<u32>, array_layers: Range<u32>, ) -> Result<UnsafeImageView, OomError>302     pub unsafe fn new(
303         image: &UnsafeImage,
304         ty: ImageViewType,
305         component_mapping: ComponentMapping,
306         mipmap_levels: Range<u32>,
307         array_layers: Range<u32>,
308     ) -> Result<UnsafeImageView, OomError> {
309         let fns = image.device().fns();
310 
311         debug_assert!(mipmap_levels.end > mipmap_levels.start);
312         debug_assert!(mipmap_levels.end <= image.mipmap_levels());
313         debug_assert!(array_layers.end > array_layers.start);
314         debug_assert!(array_layers.end <= image.dimensions().array_layers());
315 
316         if image.format().ty() == FormatTy::Ycbcr {
317             unimplemented!();
318         }
319 
320         // TODO: Let user choose
321         let aspects = image.format().aspects();
322 
323         let view = {
324             let infos = ash::vk::ImageViewCreateInfo {
325                 flags: ash::vk::ImageViewCreateFlags::empty(),
326                 image: image.internal_object(),
327                 view_type: ty.into(),
328                 format: image.format().into(),
329                 components: component_mapping.into(),
330                 subresource_range: ash::vk::ImageSubresourceRange {
331                     aspect_mask: aspects.into(),
332                     base_mip_level: mipmap_levels.start,
333                     level_count: mipmap_levels.end - mipmap_levels.start,
334                     base_array_layer: array_layers.start,
335                     layer_count: array_layers.end - array_layers.start,
336                 },
337                 ..Default::default()
338             };
339 
340             let mut output = MaybeUninit::uninit();
341             check_errors(fns.v1_0.create_image_view(
342                 image.device().internal_object(),
343                 &infos,
344                 ptr::null(),
345                 output.as_mut_ptr(),
346             ))?;
347             output.assume_init()
348         };
349 
350         Ok(UnsafeImageView {
351             view,
352             device: image.device().clone(),
353         })
354     }
355 }
356 
357 unsafe impl VulkanObject for UnsafeImageView {
358     type Object = ash::vk::ImageView;
359 
360     #[inline]
internal_object(&self) -> ash::vk::ImageView361     fn internal_object(&self) -> ash::vk::ImageView {
362         self.view
363     }
364 }
365 
366 impl fmt::Debug for UnsafeImageView {
367     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>368     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
369         write!(fmt, "<Vulkan image view {:?}>", self.view)
370     }
371 }
372 
373 impl Drop for UnsafeImageView {
374     #[inline]
drop(&mut self)375     fn drop(&mut self) {
376         unsafe {
377             let fns = self.device.fns();
378             fns.v1_0
379                 .destroy_image_view(self.device.internal_object(), self.view, ptr::null());
380         }
381     }
382 }
383 
384 impl PartialEq for UnsafeImageView {
385     #[inline]
eq(&self, other: &Self) -> bool386     fn eq(&self, other: &Self) -> bool {
387         self.view == other.view && self.device == other.device
388     }
389 }
390 
391 impl Eq for UnsafeImageView {}
392 
393 impl Hash for UnsafeImageView {
394     #[inline]
hash<H: Hasher>(&self, state: &mut H)395     fn hash<H: Hasher>(&self, state: &mut H) {
396         self.view.hash(state);
397         self.device.hash(state);
398     }
399 }
400 
401 /// The geometry type of an image view.
402 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
403 #[repr(i32)]
404 pub enum ImageViewType {
405     Dim1d = ash::vk::ImageViewType::TYPE_1D.as_raw(),
406     Dim1dArray = ash::vk::ImageViewType::TYPE_1D_ARRAY.as_raw(),
407     Dim2d = ash::vk::ImageViewType::TYPE_2D.as_raw(),
408     Dim2dArray = ash::vk::ImageViewType::TYPE_2D_ARRAY.as_raw(),
409     Dim3d = ash::vk::ImageViewType::TYPE_3D.as_raw(),
410     Cubemap = ash::vk::ImageViewType::CUBE.as_raw(),
411     CubemapArray = ash::vk::ImageViewType::CUBE_ARRAY.as_raw(),
412 }
413 
414 impl From<ImageViewType> for ash::vk::ImageViewType {
from(val: ImageViewType) -> Self415     fn from(val: ImageViewType) -> Self {
416         Self::from_raw(val as i32)
417     }
418 }
419 
420 /// Specifies how the components of an image must be mapped.
421 ///
422 /// When creating an image view, it is possible to ask the implementation to modify the value
423 /// returned when accessing a given component from within a shader.
424 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
425 pub struct ComponentMapping {
426     /// First component.
427     pub r: ComponentSwizzle,
428     /// Second component.
429     pub g: ComponentSwizzle,
430     /// Third component.
431     pub b: ComponentSwizzle,
432     /// Fourth component.
433     pub a: ComponentSwizzle,
434 }
435 
436 impl ComponentMapping {
437     /// Returns `true` if the component mapping is identity swizzled,
438     /// meaning that all the members are `Identity`.
439     ///
440     /// Certain operations require views that are identity swizzled, and will return an error
441     /// otherwise. For example, attaching a view to a framebuffer is only possible if the view is
442     /// identity swizzled.
443     #[inline]
is_identity(&self) -> bool444     pub fn is_identity(&self) -> bool {
445         self.r == ComponentSwizzle::Identity
446             && self.g == ComponentSwizzle::Identity
447             && self.b == ComponentSwizzle::Identity
448             && self.a == ComponentSwizzle::Identity
449     }
450 }
451 
452 impl From<ComponentMapping> for ash::vk::ComponentMapping {
453     #[inline]
from(value: ComponentMapping) -> Self454     fn from(value: ComponentMapping) -> Self {
455         Self {
456             r: value.r.into(),
457             g: value.g.into(),
458             b: value.b.into(),
459             a: value.a.into(),
460         }
461     }
462 }
463 
464 /// Describes the value that an individual component must return when being accessed.
465 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
466 #[repr(i32)]
467 pub enum ComponentSwizzle {
468     /// Returns the value that this component should normally have.
469     ///
470     /// This is the `Default` value.
471     Identity = ash::vk::ComponentSwizzle::IDENTITY.as_raw(),
472     /// Always return zero.
473     Zero = ash::vk::ComponentSwizzle::ZERO.as_raw(),
474     /// Always return one.
475     One = ash::vk::ComponentSwizzle::ONE.as_raw(),
476     /// Returns the value of the first component.
477     Red = ash::vk::ComponentSwizzle::R.as_raw(),
478     /// Returns the value of the second component.
479     Green = ash::vk::ComponentSwizzle::G.as_raw(),
480     /// Returns the value of the third component.
481     Blue = ash::vk::ComponentSwizzle::B.as_raw(),
482     /// Returns the value of the fourth component.
483     Alpha = ash::vk::ComponentSwizzle::A.as_raw(),
484 }
485 
486 impl From<ComponentSwizzle> for ash::vk::ComponentSwizzle {
487     #[inline]
from(val: ComponentSwizzle) -> Self488     fn from(val: ComponentSwizzle) -> Self {
489         Self::from_raw(val as i32)
490     }
491 }
492 
493 impl Default for ComponentSwizzle {
494     #[inline]
default() -> ComponentSwizzle495     fn default() -> ComponentSwizzle {
496         ComponentSwizzle::Identity
497     }
498 }
499 
500 /// Trait for types that represent the GPU can access an image view.
501 pub unsafe trait ImageViewAbstract {
502     /// Returns the wrapped image that this image view was created from.
image(&self) -> &dyn ImageAccess503     fn image(&self) -> &dyn ImageAccess;
504 
505     /// Returns the inner unsafe image view object used by this image view.
inner(&self) -> &UnsafeImageView506     fn inner(&self) -> &UnsafeImageView;
507 
508     /// Returns the range of array layers of the wrapped image that this view exposes.
array_layers(&self) -> Range<u32>509     fn array_layers(&self) -> Range<u32>;
510 
511     /// Returns the format of this view. This can be different from the parent's format.
format(&self) -> Format512     fn format(&self) -> Format;
513 
514     /// Returns the component mapping of this view.
component_mapping(&self) -> ComponentMapping515     fn component_mapping(&self) -> ComponentMapping;
516 
517     /// Returns the [`ImageViewType`] of this image view.
ty(&self) -> ImageViewType518     fn ty(&self) -> ImageViewType;
519 
520     /// Returns true if the given sampler can be used with this image view.
521     ///
522     /// This method should check whether the sampler's configuration can be used with the format
523     /// of the view.
524     // TODO: return a Result and propagate it when binding to a descriptor set
can_be_sampled(&self, _sampler: &Sampler) -> bool525     fn can_be_sampled(&self, _sampler: &Sampler) -> bool {
526         true /* FIXME */
527     }
528 }
529 
530 unsafe impl<I> ImageViewAbstract for ImageView<I>
531 where
532     I: ImageAccess,
533 {
534     #[inline]
image(&self) -> &dyn ImageAccess535     fn image(&self) -> &dyn ImageAccess {
536         &self.image
537     }
538 
539     #[inline]
inner(&self) -> &UnsafeImageView540     fn inner(&self) -> &UnsafeImageView {
541         &self.inner
542     }
543 
544     #[inline]
array_layers(&self) -> Range<u32>545     fn array_layers(&self) -> Range<u32> {
546         self.array_layers.clone()
547     }
548 
549     #[inline]
format(&self) -> Format550     fn format(&self) -> Format {
551         // TODO: remove this default impl
552         self.format
553     }
554 
555     #[inline]
component_mapping(&self) -> ComponentMapping556     fn component_mapping(&self) -> ComponentMapping {
557         self.component_mapping
558     }
559 
560     #[inline]
ty(&self) -> ImageViewType561     fn ty(&self) -> ImageViewType {
562         self.ty
563     }
564 }
565 
566 unsafe impl<T> ImageViewAbstract for T
567 where
568     T: SafeDeref,
569     T::Target: ImageViewAbstract,
570 {
571     #[inline]
image(&self) -> &dyn ImageAccess572     fn image(&self) -> &dyn ImageAccess {
573         (**self).image()
574     }
575 
576     #[inline]
inner(&self) -> &UnsafeImageView577     fn inner(&self) -> &UnsafeImageView {
578         (**self).inner()
579     }
580 
581     #[inline]
array_layers(&self) -> Range<u32>582     fn array_layers(&self) -> Range<u32> {
583         (**self).array_layers()
584     }
585 
586     #[inline]
format(&self) -> Format587     fn format(&self) -> Format {
588         (**self).format()
589     }
590 
591     #[inline]
component_mapping(&self) -> ComponentMapping592     fn component_mapping(&self) -> ComponentMapping {
593         (**self).component_mapping()
594     }
595 
596     #[inline]
ty(&self) -> ImageViewType597     fn ty(&self) -> ImageViewType {
598         (**self).ty()
599     }
600 
601     #[inline]
can_be_sampled(&self, sampler: &Sampler) -> bool602     fn can_be_sampled(&self, sampler: &Sampler) -> bool {
603         (**self).can_be_sampled(sampler)
604     }
605 }
606 
607 impl PartialEq for dyn ImageViewAbstract + Send + Sync {
608     #[inline]
eq(&self, other: &Self) -> bool609     fn eq(&self, other: &Self) -> bool {
610         self.inner() == other.inner()
611     }
612 }
613 
614 impl Eq for dyn ImageViewAbstract + Send + Sync {}
615 
616 impl Hash for dyn ImageViewAbstract + Send + Sync {
617     #[inline]
hash<H: Hasher>(&self, state: &mut H)618     fn hash<H: Hasher>(&self, state: &mut H) {
619         self.inner().hash(state);
620     }
621 }
622