1 // Copyright (c) 2016 The vulkano developers 2 // Licensed under the Apache License, Version 2.0 3 // <LICENSE-APACHE or 4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT 5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, 6 // at your option. All files in the project carrying such 7 // notice may not be copied, modified, or distributed except 8 // according to those terms. 9 10 use super::{ 11 sys::Image, ImageAspects, ImageDescriptorLayouts, ImageDimensions, ImageLayout, 12 ImageSubresourceLayers, ImageSubresourceRange, ImageUsage, SampleCount, 13 }; 14 use crate::{ 15 device::{Device, DeviceOwned}, 16 format::{Format, FormatFeatures}, 17 SafeDeref, 18 }; 19 use std::{ 20 fmt::{Debug, Error as FmtError, Formatter}, 21 hash::{Hash, Hasher}, 22 sync::Arc, 23 }; 24 25 /// Trait for types that represent the way a GPU can access an image. 26 pub unsafe trait ImageAccess: DeviceOwned + Send + Sync { 27 /// Returns the inner unsafe image object used by this image. inner(&self) -> ImageInner<'_>28 fn inner(&self) -> ImageInner<'_>; 29 30 /// Returns the dimensions of the image. 31 #[inline] dimensions(&self) -> ImageDimensions32 fn dimensions(&self) -> ImageDimensions { 33 let inner = self.inner(); 34 35 match self 36 .inner() 37 .image 38 .dimensions() 39 .mip_level_dimensions(inner.first_mipmap_level) 40 .unwrap() 41 { 42 ImageDimensions::Dim1d { 43 width, 44 array_layers: _, 45 } => ImageDimensions::Dim1d { 46 width, 47 array_layers: inner.num_layers, 48 }, 49 ImageDimensions::Dim2d { 50 width, 51 height, 52 array_layers: _, 53 } => ImageDimensions::Dim2d { 54 width, 55 height, 56 array_layers: inner.num_layers, 57 }, 58 ImageDimensions::Dim3d { 59 width, 60 height, 61 depth, 62 } => ImageDimensions::Dim3d { 63 width, 64 height, 65 depth, 66 }, 67 } 68 } 69 70 /// Returns the format of this image. 71 #[inline] format(&self) -> Format72 fn format(&self) -> Format { 73 self.inner().image.format().unwrap() 74 } 75 76 /// Returns the features supported by the image's format. 77 #[inline] format_features(&self) -> FormatFeatures78 fn format_features(&self) -> FormatFeatures { 79 self.inner().image.format_features() 80 } 81 82 /// Returns the number of mipmap levels of this image. 83 #[inline] mip_levels(&self) -> u3284 fn mip_levels(&self) -> u32 { 85 self.inner().num_mipmap_levels 86 } 87 88 /// Returns the number of samples of this image. 89 #[inline] samples(&self) -> SampleCount90 fn samples(&self) -> SampleCount { 91 self.inner().image.samples() 92 } 93 94 /// Returns the usage the image was created with. 95 #[inline] usage(&self) -> ImageUsage96 fn usage(&self) -> ImageUsage { 97 self.inner().image.usage() 98 } 99 100 /// Returns the stencil usage the image was created with. 101 #[inline] stencil_usage(&self) -> ImageUsage102 fn stencil_usage(&self) -> ImageUsage { 103 self.inner().image.stencil_usage() 104 } 105 106 /// Returns an `ImageSubresourceLayers` covering the first mip level of the image. All aspects 107 /// of the image are selected, or `plane0` if the image is multi-planar. 108 #[inline] subresource_layers(&self) -> ImageSubresourceLayers109 fn subresource_layers(&self) -> ImageSubresourceLayers { 110 ImageSubresourceLayers::from_parameters(self.format(), self.dimensions().array_layers()) 111 } 112 113 /// Returns an `ImageSubresourceRange` covering the whole image. If the image is multi-planar, 114 /// only the `color` aspect is selected. 115 #[inline] subresource_range(&self) -> ImageSubresourceRange116 fn subresource_range(&self) -> ImageSubresourceRange { 117 ImageSubresourceRange { 118 aspects: self.format().aspects() 119 - (ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2), 120 mip_levels: 0..self.mip_levels(), 121 array_layers: 0..self.dimensions().array_layers(), 122 } 123 } 124 125 /// When images are created their memory layout is initially `Undefined` or `Preinitialized`. 126 /// This method allows the image memory barrier creation process to signal when an image 127 /// has been transitioned out of its initial `Undefined` or `Preinitialized` state. This 128 /// allows vulkano to avoid creating unnecessary image memory barriers between future 129 /// uses of the image. 130 /// 131 /// ## Unsafe 132 /// 133 /// If a user calls this method outside of the intended context and signals that the layout 134 /// is no longer `Undefined` or `Preinitialized` when it is still in an `Undefined` or 135 /// `Preinitialized` state, this may result in the vulkan implementation attempting to use 136 /// an image in an invalid layout. The same problem must be considered by the implementer 137 /// of the method. 138 #[inline] layout_initialized(&self)139 unsafe fn layout_initialized(&self) {} 140 141 #[inline] is_layout_initialized(&self) -> bool142 fn is_layout_initialized(&self) -> bool { 143 false 144 } 145 146 #[inline] initial_layout(&self) -> ImageLayout147 fn initial_layout(&self) -> ImageLayout { 148 self.inner().image.initial_layout() 149 } 150 151 /// Returns the layout that the image has when it is first used in a primary command buffer. 152 /// 153 /// The first time you use an image in an `AutoCommandBufferBuilder`, vulkano will suppose that 154 /// the image is in the layout returned by this function. Later when the command buffer is 155 /// submitted vulkano will check whether the image is actually in this layout, and if it is not 156 /// the case then an error will be returned. 157 /// TODO: ^ that check is not yet implemented initial_layout_requirement(&self) -> ImageLayout158 fn initial_layout_requirement(&self) -> ImageLayout; 159 160 /// Returns the layout that the image must be returned to before the end of the command buffer. 161 /// 162 /// When an image is used in an `AutoCommandBufferBuilder` vulkano will automatically 163 /// transition this image to the layout returned by this function at the end of the command 164 /// buffer, if necessary. 165 /// 166 /// Except for special cases, this value should likely be the same as the one returned by 167 /// `initial_layout_requirement` so that the user can submit multiple command buffers that use 168 /// this image one after the other. final_layout_requirement(&self) -> ImageLayout169 fn final_layout_requirement(&self) -> ImageLayout; 170 171 /// Wraps around this `ImageAccess` and returns an identical `ImageAccess` but whose initial 172 /// layout requirement is either `Undefined` or `Preinitialized`. 173 #[inline] forced_undefined_initial_layout( self, preinitialized: bool, ) -> Arc<ImageAccessFromUndefinedLayout<Self>> where Self: Sized,174 unsafe fn forced_undefined_initial_layout( 175 self, 176 preinitialized: bool, 177 ) -> Arc<ImageAccessFromUndefinedLayout<Self>> 178 where 179 Self: Sized, 180 { 181 Arc::new(ImageAccessFromUndefinedLayout { 182 image: self, 183 preinitialized, 184 }) 185 } 186 187 /// Returns an [`ImageDescriptorLayouts`] structure specifying the image layout to use 188 /// in descriptors of various kinds. 189 /// 190 /// This must return `Some` if the image is to be used to create an image view. descriptor_layouts(&self) -> Option<ImageDescriptorLayouts>191 fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts>; 192 } 193 194 /// Inner information about an image. 195 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] 196 pub struct ImageInner<'a> { 197 /// The underlying image object. 198 pub image: &'a Arc<Image>, 199 200 /// The first layer of `image` to consider. 201 pub first_layer: u32, 202 203 /// The number of layers of `image` to consider. 204 pub num_layers: u32, 205 206 /// The first mipmap level of `image` to consider. 207 pub first_mipmap_level: u32, 208 209 /// The number of mipmap levels of `image` to consider. 210 pub num_mipmap_levels: u32, 211 } 212 213 impl Debug for dyn ImageAccess { fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>214 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { 215 f.debug_struct("dyn ImageAccess") 216 .field("inner", &self.inner()) 217 .finish() 218 } 219 } 220 221 impl PartialEq for dyn ImageAccess { 222 #[inline] eq(&self, other: &Self) -> bool223 fn eq(&self, other: &Self) -> bool { 224 self.inner() == other.inner() 225 } 226 } 227 228 impl Eq for dyn ImageAccess {} 229 230 impl Hash for dyn ImageAccess { hash<H: Hasher>(&self, state: &mut H)231 fn hash<H: Hasher>(&self, state: &mut H) { 232 self.inner().hash(state); 233 } 234 } 235 236 /// Wraps around an object that implements `ImageAccess` and modifies the initial layout 237 /// requirement to be either `Undefined` or `Preinitialized`. 238 #[derive(Debug, Copy, Clone)] 239 pub struct ImageAccessFromUndefinedLayout<I> { 240 image: I, 241 preinitialized: bool, 242 } 243 244 unsafe impl<I> DeviceOwned for ImageAccessFromUndefinedLayout<I> 245 where 246 I: ImageAccess, 247 { device(&self) -> &Arc<Device>248 fn device(&self) -> &Arc<Device> { 249 self.image.device() 250 } 251 } 252 253 unsafe impl<I> ImageAccess for ImageAccessFromUndefinedLayout<I> 254 where 255 I: ImageAccess, 256 { inner(&self) -> ImageInner<'_>257 fn inner(&self) -> ImageInner<'_> { 258 self.image.inner() 259 } 260 initial_layout_requirement(&self) -> ImageLayout261 fn initial_layout_requirement(&self) -> ImageLayout { 262 if self.preinitialized { 263 ImageLayout::Preinitialized 264 } else { 265 ImageLayout::Undefined 266 } 267 } 268 final_layout_requirement(&self) -> ImageLayout269 fn final_layout_requirement(&self) -> ImageLayout { 270 self.image.final_layout_requirement() 271 } 272 descriptor_layouts(&self) -> Option<ImageDescriptorLayouts>273 fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> { 274 self.image.descriptor_layouts() 275 } 276 } 277 278 impl<I> PartialEq for ImageAccessFromUndefinedLayout<I> 279 where 280 I: ImageAccess, 281 { eq(&self, other: &Self) -> bool282 fn eq(&self, other: &Self) -> bool { 283 self.inner() == other.inner() 284 } 285 } 286 287 impl<I> Eq for ImageAccessFromUndefinedLayout<I> where I: ImageAccess {} 288 289 impl<I> Hash for ImageAccessFromUndefinedLayout<I> 290 where 291 I: ImageAccess, 292 { hash<H: Hasher>(&self, state: &mut H)293 fn hash<H: Hasher>(&self, state: &mut H) { 294 self.inner().hash(state); 295 } 296 } 297 298 pub unsafe trait ImageContent<P>: ImageAccess { 299 /// Checks whether pixels of type `P` match the format of the image. matches_format(&self) -> bool300 fn matches_format(&self) -> bool; 301 } 302 303 unsafe impl<T> ImageAccess for T 304 where 305 T: SafeDeref + Send + Sync, 306 T::Target: ImageAccess, 307 { inner(&self) -> ImageInner<'_>308 fn inner(&self) -> ImageInner<'_> { 309 (**self).inner() 310 } 311 initial_layout_requirement(&self) -> ImageLayout312 fn initial_layout_requirement(&self) -> ImageLayout { 313 (**self).initial_layout_requirement() 314 } 315 final_layout_requirement(&self) -> ImageLayout316 fn final_layout_requirement(&self) -> ImageLayout { 317 (**self).final_layout_requirement() 318 } 319 descriptor_layouts(&self) -> Option<ImageDescriptorLayouts>320 fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> { 321 (**self).descriptor_layouts() 322 } 323 layout_initialized(&self)324 unsafe fn layout_initialized(&self) { 325 (**self).layout_initialized(); 326 } 327 is_layout_initialized(&self) -> bool328 fn is_layout_initialized(&self) -> bool { 329 (**self).is_layout_initialized() 330 } 331 } 332