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