aboutsummaryrefslogtreecommitdiff
path: root/src/image/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/image/mod.rs')
-rw-r--r--src/image/mod.rs701
1 files changed, 0 insertions, 701 deletions
diff --git a/src/image/mod.rs b/src/image/mod.rs
deleted file mode 100644
index 4e7f4af..0000000
--- a/src/image/mod.rs
+++ /dev/null
@@ -1,701 +0,0 @@
-// Copyright (c) 2016 The vulkano developers
-// Licensed under the Apache License, Version 2.0
-// <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
-// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
-// at your option. All files in the project carrying such
-// notice may not be copied, modified, or distributed except
-// according to those terms.
-
-//! Image storage (1D, 2D, 3D, arrays, etc.) and image views.
-//!
-//! An *image* is a region of memory whose purpose is to store multi-dimensional data. Its
-//! most common use is to store a 2D array of color pixels (in other words an *image* in
-//! everyday language), but it can also be used to store arbitrary data.
-//!
-//! The advantage of using an image compared to a buffer is that the memory layout is optimized
-//! for locality. When reading a specific pixel of an image, reading the nearby pixels is really
-//! fast. Most implementations have hardware dedicated to reading from images if you access them
-//! through a sampler.
-//!
-//! # Properties of an image
-//!
-//! # Images and image views
-//!
-//! There is a distinction between *images* and *image views*. As its name suggests, an image
-//! view describes how the GPU must interpret the image.
-//!
-//! Transfer and memory operations operate on images themselves, while reading/writing an image
-//! operates on image views. You can create multiple image views from the same image.
-//!
-//! # High-level wrappers
-//!
-//! In the vulkano library, an image is any object that implements the [`ImageAccess`] trait. You
-//! can create a view by wrapping them in an [`ImageView`](crate::image::view::ImageView).
-//!
-//! Since the `ImageAccess` trait is low-level, you are encouraged to not implement it yourself but
-//! instead use one of the provided implementations that are specialized depending on the way you
-//! are going to use the image:
-//!
-//! - An `AttachmentImage` can be used when you want to draw to an image.
-//! - An `ImmutableImage` stores data which never need be changed after the initial upload,
-//! like a texture.
-//!
-//! # Low-level information
-//!
-//! To be written.
-//!
-
-pub use self::aspect::ImageAspect;
-pub use self::aspect::ImageAspects;
-pub use self::attachment::AttachmentImage;
-pub use self::immutable::ImmutableImage;
-pub use self::layout::ImageDescriptorLayouts;
-pub use self::layout::ImageLayout;
-pub use self::storage::StorageImage;
-pub use self::swapchain::SwapchainImage;
-pub use self::sys::ImageCreationError;
-pub use self::traits::ImageAccess;
-pub use self::traits::ImageInner;
-pub use self::usage::ImageUsage;
-pub use self::view::ImageViewAbstract;
-use std::cmp;
-use std::convert::TryFrom;
-
-mod aspect;
-pub mod attachment; // TODO: make private
-pub mod immutable; // TODO: make private
-mod layout;
-mod storage;
-pub mod swapchain; // TODO: make private
-pub mod sys;
-pub mod traits;
-mod usage;
-pub mod view;
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-#[repr(u32)]
-pub enum SampleCount {
- Sample1 = ash::vk::SampleCountFlags::TYPE_1.as_raw(),
- Sample2 = ash::vk::SampleCountFlags::TYPE_2.as_raw(),
- Sample4 = ash::vk::SampleCountFlags::TYPE_4.as_raw(),
- Sample8 = ash::vk::SampleCountFlags::TYPE_8.as_raw(),
- Sample16 = ash::vk::SampleCountFlags::TYPE_16.as_raw(),
- Sample32 = ash::vk::SampleCountFlags::TYPE_32.as_raw(),
- Sample64 = ash::vk::SampleCountFlags::TYPE_64.as_raw(),
-}
-
-impl From<SampleCount> for ash::vk::SampleCountFlags {
- #[inline]
- fn from(val: SampleCount) -> Self {
- Self::from_raw(val as u32)
- }
-}
-
-impl TryFrom<ash::vk::SampleCountFlags> for SampleCount {
- type Error = ();
-
- #[inline]
- fn try_from(val: ash::vk::SampleCountFlags) -> Result<Self, Self::Error> {
- match val {
- ash::vk::SampleCountFlags::TYPE_1 => Ok(Self::Sample1),
- ash::vk::SampleCountFlags::TYPE_2 => Ok(Self::Sample2),
- ash::vk::SampleCountFlags::TYPE_4 => Ok(Self::Sample4),
- ash::vk::SampleCountFlags::TYPE_8 => Ok(Self::Sample8),
- ash::vk::SampleCountFlags::TYPE_16 => Ok(Self::Sample16),
- ash::vk::SampleCountFlags::TYPE_32 => Ok(Self::Sample32),
- ash::vk::SampleCountFlags::TYPE_64 => Ok(Self::Sample64),
- _ => Err(()),
- }
- }
-}
-
-impl TryFrom<u32> for SampleCount {
- type Error = ();
-
- #[inline]
- fn try_from(val: u32) -> Result<Self, Self::Error> {
- match val {
- 1 => Ok(Self::Sample1),
- 2 => Ok(Self::Sample2),
- 4 => Ok(Self::Sample4),
- 8 => Ok(Self::Sample8),
- 16 => Ok(Self::Sample16),
- 32 => Ok(Self::Sample32),
- 64 => Ok(Self::Sample64),
- _ => Err(()),
- }
- }
-}
-
-/// Specifies how many sample counts supported for an image used for storage operations.
-#[derive(Debug, Copy, Clone, Default)]
-pub struct SampleCounts {
- // specify an image with one sample per pixel
- pub sample1: bool,
- // specify an image with 2 samples per pixel
- pub sample2: bool,
- // specify an image with 4 samples per pixel
- pub sample4: bool,
- // specify an image with 8 samples per pixel
- pub sample8: bool,
- // specify an image with 16 samples per pixel
- pub sample16: bool,
- // specify an image with 32 samples per pixel
- pub sample32: bool,
- // specify an image with 64 samples per pixel
- pub sample64: bool,
-}
-
-impl From<ash::vk::SampleCountFlags> for SampleCounts {
- fn from(sample_counts: ash::vk::SampleCountFlags) -> SampleCounts {
- SampleCounts {
- sample1: !(sample_counts & ash::vk::SampleCountFlags::TYPE_1).is_empty(),
- sample2: !(sample_counts & ash::vk::SampleCountFlags::TYPE_2).is_empty(),
- sample4: !(sample_counts & ash::vk::SampleCountFlags::TYPE_4).is_empty(),
- sample8: !(sample_counts & ash::vk::SampleCountFlags::TYPE_8).is_empty(),
- sample16: !(sample_counts & ash::vk::SampleCountFlags::TYPE_16).is_empty(),
- sample32: !(sample_counts & ash::vk::SampleCountFlags::TYPE_32).is_empty(),
- sample64: !(sample_counts & ash::vk::SampleCountFlags::TYPE_64).is_empty(),
- }
- }
-}
-
-impl From<SampleCounts> for ash::vk::SampleCountFlags {
- fn from(val: SampleCounts) -> ash::vk::SampleCountFlags {
- let mut sample_counts = ash::vk::SampleCountFlags::default();
-
- if val.sample1 {
- sample_counts |= ash::vk::SampleCountFlags::TYPE_1;
- }
- if val.sample2 {
- sample_counts |= ash::vk::SampleCountFlags::TYPE_2;
- }
- if val.sample4 {
- sample_counts |= ash::vk::SampleCountFlags::TYPE_4;
- }
- if val.sample8 {
- sample_counts |= ash::vk::SampleCountFlags::TYPE_8;
- }
- if val.sample16 {
- sample_counts |= ash::vk::SampleCountFlags::TYPE_16;
- }
- if val.sample32 {
- sample_counts |= ash::vk::SampleCountFlags::TYPE_32;
- }
- if val.sample64 {
- sample_counts |= ash::vk::SampleCountFlags::TYPE_64;
- }
-
- sample_counts
- }
-}
-
-/// Specifies how many mipmaps must be allocated.
-///
-/// Note that at least one mipmap must be allocated, to store the main level of the image.
-#[derive(Debug, Copy, Clone)]
-pub enum MipmapsCount {
- /// Allocates the number of mipmaps required to store all the mipmaps of the image where each
- /// mipmap is half the dimensions of the previous level. Guaranteed to be always supported.
- ///
- /// Note that this is not necessarily the maximum number of mipmaps, as the Vulkan
- /// implementation may report that it supports a greater value.
- Log2,
-
- /// Allocate one mipmap (ie. just the main level). Always supported.
- One,
-
- /// Allocate the given number of mipmaps. May result in an error if the value is out of range
- /// of what the implementation supports.
- Specific(u32),
-}
-
-impl From<u32> for MipmapsCount {
- #[inline]
- fn from(num: u32) -> MipmapsCount {
- MipmapsCount::Specific(num)
- }
-}
-
-/// Helper type for creating extents
-#[derive(Debug, Copy, Clone)]
-pub enum Extent {
- E1D([u32; 1]),
- E2D([u32; 2]),
- E3D([u32; 3]),
-}
-
-impl From<ash::vk::Extent2D> for Extent {
- fn from(extent: ash::vk::Extent2D) -> Self {
- Extent::E2D([extent.width, extent.height])
- }
-}
-
-impl From<ash::vk::Extent3D> for Extent {
- fn from(extent: ash::vk::Extent3D) -> Self {
- Extent::E3D([extent.width, extent.height, extent.depth])
- }
-}
-impl TryFrom<Extent> for ash::vk::Extent2D {
- type Error = ();
-
- fn try_from(extent: Extent) -> Result<Self, Self::Error> {
- match extent {
- Extent::E2D(a) => Ok(ash::vk::Extent2D {
- width: a[0],
- height: a[1],
- }),
- _ => Err(()),
- }
- }
-}
-
-impl TryFrom<Extent> for ash::vk::Extent3D {
- type Error = ();
-
- fn try_from(extent: Extent) -> Result<Self, Self::Error> {
- match extent {
- Extent::E3D(a) => Ok(ash::vk::Extent3D {
- width: a[0],
- height: a[1],
- depth: a[2],
- }),
- _ => Err(()),
- }
- }
-}
-
-/// Helper type returned from Device's `fn image_format_properties()`
-pub struct ImageFormatProperties {
- pub max_extent: Extent,
- pub max_mip_levels: MipmapsCount,
- pub max_array_layers: u32,
- pub sample_counts: SampleCounts,
- pub max_resource_size: usize,
-}
-
-impl From<ash::vk::ImageFormatProperties> for ImageFormatProperties {
- fn from(props: ash::vk::ImageFormatProperties) -> Self {
- Self {
- max_extent: props.max_extent.into(),
- max_mip_levels: props.max_mip_levels.into(),
- max_array_layers: props.max_array_layers,
- sample_counts: props.sample_counts.into(),
- max_resource_size: props.max_resource_size as usize,
- }
- }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
-pub struct ImageCreateFlags {
- pub sparse_binding: bool,
- pub sparse_residency: bool,
- pub sparse_aliased: bool,
- pub mutable_format: bool,
- pub cube_compatible: bool,
- pub array_2d_compatible: bool,
-}
-
-impl ImageCreateFlags {
- pub fn all() -> Self {
- Self {
- sparse_binding: true,
- sparse_residency: true,
- sparse_aliased: true,
- mutable_format: true,
- cube_compatible: true,
- array_2d_compatible: true,
- }
- }
-
- pub fn none() -> Self {
- Self::default()
- }
-}
-
-impl From<ImageCreateFlags> for ash::vk::ImageCreateFlags {
- fn from(flags: ImageCreateFlags) -> Self {
- let mut vk_flags = Self::default();
- if flags.sparse_binding {
- vk_flags |= ash::vk::ImageCreateFlags::SPARSE_BINDING
- };
- if flags.sparse_residency {
- vk_flags |= ash::vk::ImageCreateFlags::SPARSE_RESIDENCY
- };
- if flags.sparse_aliased {
- vk_flags |= ash::vk::ImageCreateFlags::SPARSE_ALIASED
- };
- if flags.mutable_format {
- vk_flags |= ash::vk::ImageCreateFlags::MUTABLE_FORMAT
- };
- if flags.cube_compatible {
- vk_flags |= ash::vk::ImageCreateFlags::CUBE_COMPATIBLE
- };
- if flags.array_2d_compatible {
- vk_flags |= ash::vk::ImageCreateFlags::TYPE_2D_ARRAY_COMPATIBLE_KHR
- };
- vk_flags
- }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-#[repr(i32)]
-pub enum ImageType {
- Dim1d = ash::vk::ImageType::TYPE_1D.as_raw(),
- Dim2d = ash::vk::ImageType::TYPE_2D.as_raw(),
- Dim3d = ash::vk::ImageType::TYPE_3D.as_raw(),
-}
-impl From<ImageType> for ash::vk::ImageType {
- fn from(val: ImageType) -> Self {
- ash::vk::ImageType::from_raw(val as i32)
- }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-#[repr(i32)]
-pub enum ImageTiling {
- Optimal = ash::vk::ImageTiling::OPTIMAL.as_raw(),
- Linear = ash::vk::ImageTiling::LINEAR.as_raw(),
-}
-
-impl From<ImageTiling> for ash::vk::ImageTiling {
- fn from(val: ImageTiling) -> Self {
- ash::vk::ImageTiling::from_raw(val as i32)
- }
-}
-
-/// The dimensions of an image.
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum ImageDimensions {
- Dim1d {
- width: u32,
- array_layers: u32,
- },
- Dim2d {
- width: u32,
- height: u32,
- array_layers: u32,
- },
- Dim3d {
- width: u32,
- height: u32,
- depth: u32,
- },
-}
-
-impl ImageDimensions {
- #[inline]
- pub fn width(&self) -> u32 {
- match *self {
- ImageDimensions::Dim1d { width, .. } => width,
- ImageDimensions::Dim2d { width, .. } => width,
- ImageDimensions::Dim3d { width, .. } => width,
- }
- }
-
- #[inline]
- pub fn height(&self) -> u32 {
- match *self {
- ImageDimensions::Dim1d { .. } => 1,
- ImageDimensions::Dim2d { height, .. } => height,
- ImageDimensions::Dim3d { height, .. } => height,
- }
- }
-
- #[inline]
- pub fn width_height(&self) -> [u32; 2] {
- [self.width(), self.height()]
- }
-
- #[inline]
- pub fn depth(&self) -> u32 {
- match *self {
- ImageDimensions::Dim1d { .. } => 1,
- ImageDimensions::Dim2d { .. } => 1,
- ImageDimensions::Dim3d { depth, .. } => depth,
- }
- }
-
- #[inline]
- pub fn width_height_depth(&self) -> [u32; 3] {
- [self.width(), self.height(), self.depth()]
- }
-
- #[inline]
- pub fn array_layers(&self) -> u32 {
- match *self {
- ImageDimensions::Dim1d { array_layers, .. } => array_layers,
- ImageDimensions::Dim2d { array_layers, .. } => array_layers,
- ImageDimensions::Dim3d { .. } => 1,
- }
- }
-
- /// Returns the total number of texels for an image of these dimensions.
- #[inline]
- pub fn num_texels(&self) -> u32 {
- self.width() * self.height() * self.depth() * self.array_layers()
- }
-
- /// Returns the maximum number of mipmaps for these image dimensions.
- ///
- /// The returned value is always at least superior or equal to 1.
- ///
- /// # Example
- ///
- /// ```
- /// use vulkano::image::ImageDimensions;
- ///
- /// let dims = ImageDimensions::Dim2d {
- /// width: 32,
- /// height: 50,
- /// array_layers: 1,
- /// };
- ///
- /// assert_eq!(dims.max_mipmaps(), 6);
- /// ```
- ///
- pub fn max_mipmaps(&self) -> u32 {
- 32 - (self.width() | self.height() | self.depth()).leading_zeros()
- }
-
- /// Returns the dimensions of the `level`th mipmap level. If `level` is 0, then the dimensions
- /// are left unchanged.
- ///
- /// Returns `None` if `level` is superior or equal to `max_mipmaps()`.
- ///
- /// # Example
- ///
- /// ```
- /// use vulkano::image::ImageDimensions;
- ///
- /// let dims = ImageDimensions::Dim2d {
- /// width: 963,
- /// height: 256,
- /// array_layers: 1,
- /// };
- ///
- /// assert_eq!(dims.mipmap_dimensions(0), Some(dims));
- /// assert_eq!(dims.mipmap_dimensions(1), Some(ImageDimensions::Dim2d {
- /// width: 481,
- /// height: 128,
- /// array_layers: 1,
- /// }));
- /// assert_eq!(dims.mipmap_dimensions(6), Some(ImageDimensions::Dim2d {
- /// width: 15,
- /// height: 4,
- /// array_layers: 1,
- /// }));
- /// assert_eq!(dims.mipmap_dimensions(9), Some(ImageDimensions::Dim2d {
- /// width: 1,
- /// height: 1,
- /// array_layers: 1,
- /// }));
- /// assert_eq!(dims.mipmap_dimensions(11), None);
- /// ```
- ///
- /// # Panic
- ///
- /// In debug mode, Panics if `width`, `height` or `depth` is equal to 0. In release, returns
- /// an unspecified value.
- ///
- pub fn mipmap_dimensions(&self, level: u32) -> Option<ImageDimensions> {
- if level == 0 {
- return Some(*self);
- }
-
- if level >= self.max_mipmaps() {
- return None;
- }
-
- Some(match *self {
- ImageDimensions::Dim1d {
- width,
- array_layers,
- } => {
- debug_assert_ne!(width, 0);
- ImageDimensions::Dim1d {
- array_layers,
- width: cmp::max(1, width >> level),
- }
- }
-
- ImageDimensions::Dim2d {
- width,
- height,
- array_layers,
- } => {
- debug_assert_ne!(width, 0);
- debug_assert_ne!(height, 0);
- ImageDimensions::Dim2d {
- width: cmp::max(1, width >> level),
- height: cmp::max(1, height >> level),
- array_layers,
- }
- }
-
- ImageDimensions::Dim3d {
- width,
- height,
- depth,
- } => {
- debug_assert_ne!(width, 0);
- debug_assert_ne!(height, 0);
- ImageDimensions::Dim3d {
- width: cmp::max(1, width >> level),
- height: cmp::max(1, height >> level),
- depth: cmp::max(1, depth >> level),
- }
- }
- })
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::format::Format;
- use crate::image::ImageDimensions;
- use crate::image::ImmutableImage;
- use crate::image::MipmapsCount;
-
- #[test]
- fn max_mipmaps() {
- let dims = ImageDimensions::Dim2d {
- width: 2,
- height: 1,
- array_layers: 1,
- };
- assert_eq!(dims.max_mipmaps(), 2);
-
- let dims = ImageDimensions::Dim2d {
- width: 2,
- height: 3,
- array_layers: 1,
- };
- assert_eq!(dims.max_mipmaps(), 2);
-
- let dims = ImageDimensions::Dim2d {
- width: 512,
- height: 512,
- array_layers: 1,
- };
- assert_eq!(dims.max_mipmaps(), 10);
- }
-
- #[test]
- fn mipmap_dimensions() {
- let dims = ImageDimensions::Dim2d {
- width: 283,
- height: 175,
- array_layers: 1,
- };
- assert_eq!(dims.mipmap_dimensions(0), Some(dims));
- assert_eq!(
- dims.mipmap_dimensions(1),
- Some(ImageDimensions::Dim2d {
- width: 141,
- height: 87,
- array_layers: 1,
- })
- );
- assert_eq!(
- dims.mipmap_dimensions(2),
- Some(ImageDimensions::Dim2d {
- width: 70,
- height: 43,
- array_layers: 1,
- })
- );
- assert_eq!(
- dims.mipmap_dimensions(3),
- Some(ImageDimensions::Dim2d {
- width: 35,
- height: 21,
- array_layers: 1,
- })
- );
-
- assert_eq!(
- dims.mipmap_dimensions(4),
- Some(ImageDimensions::Dim2d {
- width: 17,
- height: 10,
- array_layers: 1,
- })
- );
- assert_eq!(
- dims.mipmap_dimensions(5),
- Some(ImageDimensions::Dim2d {
- width: 8,
- height: 5,
- array_layers: 1,
- })
- );
- assert_eq!(
- dims.mipmap_dimensions(6),
- Some(ImageDimensions::Dim2d {
- width: 4,
- height: 2,
- array_layers: 1,
- })
- );
- assert_eq!(
- dims.mipmap_dimensions(7),
- Some(ImageDimensions::Dim2d {
- width: 2,
- height: 1,
- array_layers: 1,
- })
- );
- assert_eq!(
- dims.mipmap_dimensions(8),
- Some(ImageDimensions::Dim2d {
- width: 1,
- height: 1,
- array_layers: 1,
- })
- );
- assert_eq!(dims.mipmap_dimensions(9), None);
- }
-
- #[test]
- fn mipmap_working_immutable_image() {
- let (device, queue) = gfx_dev_and_queue!();
-
- let dimensions = ImageDimensions::Dim2d {
- width: 512,
- height: 512,
- array_layers: 1,
- };
- {
- let mut vec = Vec::new();
-
- vec.resize(512 * 512, 0u8);
-
- let (image, _) = ImmutableImage::from_iter(
- vec.into_iter(),
- dimensions,
- MipmapsCount::One,
- Format::R8Unorm,
- queue.clone(),
- )
- .unwrap();
- assert_eq!(image.mipmap_levels(), 1);
- }
- {
- let mut vec = Vec::new();
-
- vec.resize(512 * 512, 0u8);
-
- let (image, _) = ImmutableImage::from_iter(
- vec.into_iter(),
- dimensions,
- MipmapsCount::Log2,
- Format::R8Unorm,
- queue.clone(),
- )
- .unwrap();
- assert_eq!(image.mipmap_levels(), 10);
- }
- }
-}