// Copyright (c) 2016 The vulkano developers // Licensed under the Apache License, Version 2.0 // or the MIT // license , // at your option. All files in the project carrying such // notice may not be copied, modified, or distributed except // according to those terms. use super::{ sys::Image, ImageAspects, ImageDescriptorLayouts, ImageDimensions, ImageLayout, ImageSubresourceLayers, ImageSubresourceRange, ImageUsage, SampleCount, }; use crate::{ device::{Device, DeviceOwned}, format::{Format, FormatFeatures}, SafeDeref, }; use std::{ fmt::{Debug, Error as FmtError, Formatter}, hash::{Hash, Hasher}, sync::Arc, }; /// Trait for types that represent the way a GPU can access an image. pub unsafe trait ImageAccess: DeviceOwned + Send + Sync { /// Returns the inner unsafe image object used by this image. fn inner(&self) -> ImageInner<'_>; /// Returns the dimensions of the image. #[inline] fn dimensions(&self) -> ImageDimensions { let inner = self.inner(); match self .inner() .image .dimensions() .mip_level_dimensions(inner.first_mipmap_level) .unwrap() { ImageDimensions::Dim1d { width, array_layers: _, } => ImageDimensions::Dim1d { width, array_layers: inner.num_layers, }, ImageDimensions::Dim2d { width, height, array_layers: _, } => ImageDimensions::Dim2d { width, height, array_layers: inner.num_layers, }, ImageDimensions::Dim3d { width, height, depth, } => ImageDimensions::Dim3d { width, height, depth, }, } } /// Returns the format of this image. #[inline] fn format(&self) -> Format { self.inner().image.format().unwrap() } /// Returns the features supported by the image's format. #[inline] fn format_features(&self) -> FormatFeatures { self.inner().image.format_features() } /// Returns the number of mipmap levels of this image. #[inline] fn mip_levels(&self) -> u32 { self.inner().num_mipmap_levels } /// Returns the number of samples of this image. #[inline] fn samples(&self) -> SampleCount { self.inner().image.samples() } /// Returns the usage the image was created with. #[inline] fn usage(&self) -> ImageUsage { self.inner().image.usage() } /// Returns the stencil usage the image was created with. #[inline] fn stencil_usage(&self) -> ImageUsage { self.inner().image.stencil_usage() } /// Returns an `ImageSubresourceLayers` covering the first mip level of the image. All aspects /// of the image are selected, or `plane0` if the image is multi-planar. #[inline] fn subresource_layers(&self) -> ImageSubresourceLayers { ImageSubresourceLayers::from_parameters(self.format(), self.dimensions().array_layers()) } /// Returns an `ImageSubresourceRange` covering the whole image. If the image is multi-planar, /// only the `color` aspect is selected. #[inline] fn subresource_range(&self) -> ImageSubresourceRange { ImageSubresourceRange { aspects: self.format().aspects() - (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2), mip_levels: 0..self.mip_levels(), array_layers: 0..self.dimensions().array_layers(), } } /// When images are created their memory layout is initially `Undefined` or `Preinitialized`. /// This method allows the image memory barrier creation process to signal when an image /// has been transitioned out of its initial `Undefined` or `Preinitialized` state. This /// allows vulkano to avoid creating unnecessary image memory barriers between future /// uses of the image. /// /// ## Unsafe /// /// If a user calls this method outside of the intended context and signals that the layout /// is no longer `Undefined` or `Preinitialized` when it is still in an `Undefined` or /// `Preinitialized` state, this may result in the vulkan implementation attempting to use /// an image in an invalid layout. The same problem must be considered by the implementer /// of the method. #[inline] unsafe fn layout_initialized(&self) {} #[inline] fn is_layout_initialized(&self) -> bool { false } #[inline] fn initial_layout(&self) -> ImageLayout { self.inner().image.initial_layout() } /// Returns the layout that the image has when it is first used in a primary command buffer. /// /// The first time you use an image in an `AutoCommandBufferBuilder`, vulkano will suppose that /// the image is in the layout returned by this function. Later when the command buffer is /// submitted vulkano will check whether the image is actually in this layout, and if it is not /// the case then an error will be returned. /// TODO: ^ that check is not yet implemented fn initial_layout_requirement(&self) -> ImageLayout; /// Returns the layout that the image must be returned to before the end of the command buffer. /// /// When an image is used in an `AutoCommandBufferBuilder` vulkano will automatically /// transition this image to the layout returned by this function at the end of the command /// buffer, if necessary. /// /// Except for special cases, this value should likely be the same as the one returned by /// `initial_layout_requirement` so that the user can submit multiple command buffers that use /// this image one after the other. fn final_layout_requirement(&self) -> ImageLayout; /// Wraps around this `ImageAccess` and returns an identical `ImageAccess` but whose initial /// layout requirement is either `Undefined` or `Preinitialized`. #[inline] unsafe fn forced_undefined_initial_layout( self, preinitialized: bool, ) -> Arc> where Self: Sized, { Arc::new(ImageAccessFromUndefinedLayout { image: self, preinitialized, }) } /// Returns an [`ImageDescriptorLayouts`] structure specifying the image layout to use /// in descriptors of various kinds. /// /// This must return `Some` if the image is to be used to create an image view. fn descriptor_layouts(&self) -> Option; } /// Inner information about an image. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct ImageInner<'a> { /// The underlying image object. pub image: &'a Arc, /// The first layer of `image` to consider. pub first_layer: u32, /// The number of layers of `image` to consider. pub num_layers: u32, /// The first mipmap level of `image` to consider. pub first_mipmap_level: u32, /// The number of mipmap levels of `image` to consider. pub num_mipmap_levels: u32, } impl Debug for dyn ImageAccess { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { f.debug_struct("dyn ImageAccess") .field("inner", &self.inner()) .finish() } } impl PartialEq for dyn ImageAccess { #[inline] fn eq(&self, other: &Self) -> bool { self.inner() == other.inner() } } impl Eq for dyn ImageAccess {} impl Hash for dyn ImageAccess { fn hash(&self, state: &mut H) { self.inner().hash(state); } } /// Wraps around an object that implements `ImageAccess` and modifies the initial layout /// requirement to be either `Undefined` or `Preinitialized`. #[derive(Debug, Copy, Clone)] pub struct ImageAccessFromUndefinedLayout { image: I, preinitialized: bool, } unsafe impl DeviceOwned for ImageAccessFromUndefinedLayout where I: ImageAccess, { fn device(&self) -> &Arc { self.image.device() } } unsafe impl ImageAccess for ImageAccessFromUndefinedLayout where I: ImageAccess, { fn inner(&self) -> ImageInner<'_> { self.image.inner() } fn initial_layout_requirement(&self) -> ImageLayout { if self.preinitialized { ImageLayout::Preinitialized } else { ImageLayout::Undefined } } fn final_layout_requirement(&self) -> ImageLayout { self.image.final_layout_requirement() } fn descriptor_layouts(&self) -> Option { self.image.descriptor_layouts() } } impl PartialEq for ImageAccessFromUndefinedLayout where I: ImageAccess, { fn eq(&self, other: &Self) -> bool { self.inner() == other.inner() } } impl Eq for ImageAccessFromUndefinedLayout where I: ImageAccess {} impl Hash for ImageAccessFromUndefinedLayout where I: ImageAccess, { fn hash(&self, state: &mut H) { self.inner().hash(state); } } pub unsafe trait ImageContent

: ImageAccess { /// Checks whether pixels of type `P` match the format of the image. fn matches_format(&self) -> bool; } unsafe impl ImageAccess for T where T: SafeDeref + Send + Sync, T::Target: ImageAccess, { fn inner(&self) -> ImageInner<'_> { (**self).inner() } fn initial_layout_requirement(&self) -> ImageLayout { (**self).initial_layout_requirement() } fn final_layout_requirement(&self) -> ImageLayout { (**self).final_layout_requirement() } fn descriptor_layouts(&self) -> Option { (**self).descriptor_layouts() } unsafe fn layout_initialized(&self) { (**self).layout_initialized(); } fn is_layout_initialized(&self) -> bool { (**self).is_layout_initialized() } }