• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 crate::format::ClearValue;
11 use crate::image::traits::ImageAccess;
12 use crate::image::traits::ImageClearValue;
13 use crate::image::traits::ImageContent;
14 use crate::image::ImageDescriptorLayouts;
15 use crate::image::ImageInner;
16 use crate::image::ImageLayout;
17 use crate::swapchain::Swapchain;
18 use crate::sync::AccessError;
19 use crate::OomError;
20 use std::hash::Hash;
21 use std::hash::Hasher;
22 use std::sync::Arc;
23 
24 /// An image that is part of a swapchain.
25 ///
26 /// Creating a `SwapchainImage` is automatically done when creating a swapchain.
27 ///
28 /// A swapchain image is special in the sense that it can only be used after being acquired by
29 /// calling the `acquire` method on the swapchain. You have no way to know in advance which
30 /// swapchain image is going to be acquired, so you should keep all of them alive.
31 ///
32 /// After a swapchain image has been acquired, you are free to perform all the usual operations
33 /// on it. When you are done you can then *present* the image (by calling the corresponding
34 /// method on the swapchain), which will have the effect of showing the content of the image to
35 /// the screen. Once an image has been presented, it can no longer be used unless it is acquired
36 /// again.
37 // TODO: #[derive(Debug)]
38 pub struct SwapchainImage<W> {
39     swapchain: Arc<Swapchain<W>>,
40     image_offset: usize,
41 }
42 
43 impl<W> SwapchainImage<W> {
44     /// Builds a `SwapchainImage` from raw components.
45     ///
46     /// This is an internal method that you shouldn't call.
from_raw( swapchain: Arc<Swapchain<W>>, id: usize, ) -> Result<Arc<SwapchainImage<W>>, OomError>47     pub unsafe fn from_raw(
48         swapchain: Arc<Swapchain<W>>,
49         id: usize,
50     ) -> Result<Arc<SwapchainImage<W>>, OomError> {
51         let image = swapchain.raw_image(id).unwrap();
52 
53         Ok(Arc::new(SwapchainImage {
54             swapchain: swapchain.clone(),
55             image_offset: id,
56         }))
57     }
58 
59     /// Returns the dimensions of the image.
60     ///
61     /// A `SwapchainImage` is always two-dimensional.
62     #[inline]
dimensions(&self) -> [u32; 2]63     pub fn dimensions(&self) -> [u32; 2] {
64         let dims = self.my_image().image.dimensions();
65         [dims.width(), dims.height()]
66     }
67 
68     /// Returns the swapchain this image belongs to.
69     #[inline]
swapchain(&self) -> &Arc<Swapchain<W>>70     pub fn swapchain(&self) -> &Arc<Swapchain<W>> {
71         &self.swapchain
72     }
73 
74     #[inline]
my_image(&self) -> ImageInner75     fn my_image(&self) -> ImageInner {
76         self.swapchain.raw_image(self.image_offset).unwrap()
77     }
78 
79     #[inline]
layout_initialized(&self)80     fn layout_initialized(&self) {
81         self.swapchain.image_layout_initialized(self.image_offset);
82     }
83 
84     #[inline]
is_layout_initialized(&self) -> bool85     fn is_layout_initialized(&self) -> bool {
86         self.swapchain
87             .is_image_layout_initialized(self.image_offset)
88     }
89 }
90 
91 unsafe impl<W> ImageAccess for SwapchainImage<W> {
92     #[inline]
inner(&self) -> ImageInner93     fn inner(&self) -> ImageInner {
94         self.my_image()
95     }
96 
97     #[inline]
initial_layout_requirement(&self) -> ImageLayout98     fn initial_layout_requirement(&self) -> ImageLayout {
99         ImageLayout::PresentSrc
100     }
101 
102     #[inline]
final_layout_requirement(&self) -> ImageLayout103     fn final_layout_requirement(&self) -> ImageLayout {
104         ImageLayout::PresentSrc
105     }
106 
107     #[inline]
descriptor_layouts(&self) -> Option<ImageDescriptorLayouts>108     fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
109         Some(ImageDescriptorLayouts {
110             storage_image: ImageLayout::ShaderReadOnlyOptimal,
111             combined_image_sampler: ImageLayout::ShaderReadOnlyOptimal,
112             sampled_image: ImageLayout::ShaderReadOnlyOptimal,
113             input_attachment: ImageLayout::ShaderReadOnlyOptimal,
114         })
115     }
116 
117     #[inline]
conflict_key(&self) -> u64118     fn conflict_key(&self) -> u64 {
119         self.my_image().image.key()
120     }
121 
122     #[inline]
try_gpu_lock(&self, _: bool, _: bool, _: ImageLayout) -> Result<(), AccessError>123     fn try_gpu_lock(&self, _: bool, _: bool, _: ImageLayout) -> Result<(), AccessError> {
124         if self.swapchain.is_fullscreen_exclusive() {
125             Ok(())
126         } else {
127             // Swapchain image are only accessible after being acquired.
128             Err(AccessError::SwapchainImageAcquireOnly)
129         }
130     }
131 
132     #[inline]
layout_initialized(&self)133     unsafe fn layout_initialized(&self) {
134         self.layout_initialized();
135     }
136 
137     #[inline]
is_layout_initialized(&self) -> bool138     fn is_layout_initialized(&self) -> bool {
139         self.is_layout_initialized()
140     }
141 
142     #[inline]
increase_gpu_lock(&self)143     unsafe fn increase_gpu_lock(&self) {}
144 
145     #[inline]
unlock(&self, _: Option<ImageLayout>)146     unsafe fn unlock(&self, _: Option<ImageLayout>) {
147         // TODO: store that the image was initialized
148     }
149 
150     #[inline]
current_miplevels_access(&self) -> std::ops::Range<u32>151     fn current_miplevels_access(&self) -> std::ops::Range<u32> {
152         0..self.mipmap_levels()
153     }
154 
155     #[inline]
current_layer_levels_access(&self) -> std::ops::Range<u32>156     fn current_layer_levels_access(&self) -> std::ops::Range<u32> {
157         0..1
158     }
159 }
160 
161 unsafe impl<W> ImageClearValue<ClearValue> for SwapchainImage<W> {
162     #[inline]
decode(&self, value: ClearValue) -> Option<ClearValue>163     fn decode(&self, value: ClearValue) -> Option<ClearValue> {
164         Some(self.swapchain.format().decode_clear_value(value))
165     }
166 }
167 
168 unsafe impl<P, W> ImageContent<P> for SwapchainImage<W> {
169     #[inline]
matches_format(&self) -> bool170     fn matches_format(&self) -> bool {
171         true // FIXME:
172     }
173 }
174 
175 impl<W> PartialEq for SwapchainImage<W> {
176     #[inline]
eq(&self, other: &Self) -> bool177     fn eq(&self, other: &Self) -> bool {
178         ImageAccess::inner(self) == ImageAccess::inner(other)
179     }
180 }
181 
182 impl<W> Eq for SwapchainImage<W> {}
183 
184 impl<W> Hash for SwapchainImage<W> {
185     #[inline]
hash<H: Hasher>(&self, state: &mut H)186     fn hash<H: Hasher>(&self, state: &mut H) {
187         ImageAccess::inner(self).hash(state);
188     }
189 }
190