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