bedrock/surface/
swapchain.rs

1use crate::{ffi_helper::slice_as_ptr_empty_null, *};
2use derives::implements;
3
4use super::CompletionHandlerMut;
5
6pub trait Swapchain: VkHandle<Handle = VkSwapchainKHR> + DeviceChild {
7    fn format(&self) -> VkFormat;
8    fn size(&self) -> &VkExtent2D;
9
10    /// Retrieve the index of the next available presentation image
11    /// # Failures
12    /// On failure, this command returns
13    ///
14    /// * `VK_ERROR_OUT_OF_HOST_MEMORY`
15    /// * `VK_ERROR_OUT_OF_DEVICE_MEMORY`
16    /// * `VK_ERROR_DEVICE_LOST`
17    /// * `VK_ERROR_OUT_OF_DATE_KHR`
18    /// * `VK_ERROR_SURFACE_LOST_KHR`
19    #[implements]
20    fn acquire_next(&mut self, timeout: Option<u64>, completion: CompletionHandlerMut) -> crate::Result<u32> {
21        let (semaphore, fence) = match completion {
22            CompletionHandlerMut::Host(f) => (VkSemaphore::NULL, f.0),
23            CompletionHandlerMut::Queue(s) => (s.0, VkFence::NULL),
24        };
25
26        let mut n = 0;
27        unsafe {
28            crate::vkfn::acquire_next_image_khr(
29                self.device().native_ptr(),
30                self.native_ptr(),
31                timeout.unwrap_or(std::u64::MAX),
32                semaphore,
33                fence,
34                &mut n,
35            )
36            .into_result()
37            .map(|_| n)
38        }
39    }
40
41    /// Acquire full-screen exclusive mode for a swapchain.
42    /// # Failures
43    /// On failure, this command returns
44    ///
45    /// * `VK_ERROR_OUT_OF_HOST_MEMORY`
46    /// * `VK_ERROR_OUT_OF_DEVICE_MEMORY`
47    /// * `VK_ERROR_INITIALIZATION_FAILED`
48    /// * `VK_ERROR_SURFACE_LOST_KHR`
49    #[implements("VK_EXT_full_screen_exclusive")]
50    fn acquire_full_screen_exclusive_mode(&self) -> crate::Result<()>
51    where
52        Self::ConcreteDevice: DeviceFullScreenExclusiveExtension,
53    {
54        unsafe {
55            self.device().acquire_full_screen_exclusive_mode_ext_fn().0(self.device().native_ptr(), self.native_ptr())
56                .into_result()
57                .map(drop)
58        }
59    }
60
61    /// Release full-screen exclusive mode from a swapchain.
62    #[implements("VK_EXT_full_screen_exclusive")]
63    fn release_full_screen_exclusive_mode(&self) -> crate::Result<()>
64    where
65        Self::ConcreteDevice: DeviceFullScreenExclusiveExtension,
66    {
67        unsafe {
68            self.device().release_full_screen_exclusive_mode_ext_fn().0(self.device().native_ptr(), self.native_ptr())
69                .into_result()
70                .map(drop)
71        }
72    }
73
74    /// Obtain a count of the array of presentable images associated with a swapchain
75    /// # Failures
76    /// On failure, this command returns
77    ///
78    /// * [`VK_ERROR_OUT_OF_HOST_MEMORY`]
79    /// * [`VK_ERROR_OUT_OF_DEVICE_MEMORY`]
80    #[implements]
81    #[inline]
82    fn image_count(&self) -> crate::Result<u32> {
83        let mut n = 0;
84        unsafe {
85            crate::vkfn::get_swapchain_images_khr(
86                self.device_handle(),
87                self.native_ptr(),
88                &mut n,
89                core::ptr::null_mut(),
90            )
91            .into_result()?;
92        }
93
94        Ok(n)
95    }
96
97    /// Obtain the array of presentable images associated with a swapchain
98    /// # Failures
99    /// On failure, this command returns
100    ///
101    /// * [`VK_ERROR_OUT_OF_HOST_MEMORY`]
102    /// * [`VK_ERROR_OUT_OF_DEVICE_MEMORY`]
103    #[implements]
104    #[inline]
105    fn images(&self, sink: &mut [core::mem::MaybeUninit<VkImage>]) -> crate::Result<(u32, crate::ArrayQueryResult)> {
106        let mut n = sink.len() as _;
107        let r = unsafe {
108            crate::vkfn::get_swapchain_images_khr(
109                self.device_handle(),
110                self.native_ptr(),
111                &mut n,
112                sink.as_mut_ptr() as _,
113            )
114        };
115
116        match r {
117            VK_SUCCESS => Ok((n, crate::ArrayQueryResult::Complete)),
118            VK_INCOMPLETE => Ok((n, crate::ArrayQueryResult::Incomplete)),
119            e => Err(e),
120        }
121    }
122
123    /// Obtain the array of presentable images associated with a swapchain
124    /// # Failures
125    /// On failure, this command returns
126    ///
127    /// * `VK_ERROR_OUT_OF_HOST_MEMORY`
128    /// * `VK_ERROR_OUT_OF_DEVICE_MEMORY`
129    #[implements("alloc")]
130    fn images_alloc(&self) -> crate::Result<Vec<crate::SwapchainImage<&Self>>>
131    where
132        Self: Sized,
133    {
134        let n = self.image_count()? as usize;
135        if n == 0 {
136            // no items
137            return Ok(crate::alloc::empty_sink_buffer());
138        }
139
140        let mut xs = Vec::with_capacity(n);
141        let (n, _) = self.images(xs.spare_capacity_mut())?;
142        unsafe {
143            xs.set_len(n as _);
144        }
145
146        Ok(crate::alloc::collect_vec(xs.into_iter().map(move |r| {
147            crate::SwapchainImage(r, self, self.size().with_depth(1))
148        })))
149    }
150}
151DerefContainerBracketImpl!(for Swapchain {
152    #[inline(always)]
153    fn format(&self) -> VkFormat {
154        T::format(self)
155    }
156
157    #[inline(always)]
158    fn size(&self) -> &VkExtent2D {
159        T::size(self)
160    }
161});
162
163#[repr(transparent)]
164#[derive(Clone)]
165pub struct SwapchainCreateInfo<'r, 'n, 'sw>(
166    VkSwapchainCreateInfoKHR,
167    core::marker::PhantomData<(
168        &'r dyn VkHandle<Handle = VkSurfaceKHR>,
169        Option<&'n dyn VulkanStructure>,
170        Option<&'r [u32]>,
171        Option<&'sw dyn VkHandle<Handle = VkSwapchainKHR>>,
172    )>,
173);
174impl<'r, 'n, 'sw> SwapchainCreateInfo<'r, 'n, 'sw> {
175    #[inline]
176    pub fn new(
177        surface: &'r (impl VkHandle<Handle = VkSurfaceKHR> + ?Sized),
178        min_image_count: u32,
179        format: VkSurfaceFormatKHR,
180        extent: VkExtent2D,
181        usage: ImageUsageFlags,
182    ) -> Self {
183        Self(
184            VkSwapchainCreateInfoKHR {
185                sType: VkSwapchainCreateInfoKHR::TYPE,
186                pNext: core::ptr::null(),
187                flags: 0,
188                surface: surface.native_ptr(),
189                minImageCount: min_image_count,
190                imageFormat: format.format,
191                imageColorSpace: format.colorSpace,
192                imageExtent: extent,
193                imageArrayLayers: 1,
194                imageUsage: usage.bits(),
195                imageSharingMode: VK_SHARING_MODE_EXCLUSIVE,
196                queueFamilyIndexCount: 0,
197                pQueueFamilyIndices: core::ptr::null(),
198                preTransform: VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR,
199                compositeAlpha: VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
200                presentMode: VK_PRESENT_MODE_IMMEDIATE_KHR,
201                clipped: false as _,
202                oldSwapchain: VkSwapchainKHR::NULL,
203            },
204            core::marker::PhantomData,
205        )
206    }
207
208    pub const unsafe fn from_raw(raw: VkSwapchainCreateInfoKHR) -> Self {
209        Self(raw, core::marker::PhantomData)
210    }
211
212    pub const fn into_raw(self) -> VkSwapchainCreateInfoKHR {
213        self.0
214    }
215
216    pub const fn with_next(mut self, next: &'n (impl VulkanStructure + ?Sized)) -> Self {
217        self.0.pNext = next as *const _ as _;
218        self
219    }
220
221    pub const fn array_layers(mut self, layers: u32) -> Self {
222        self.0.imageArrayLayers = layers;
223        self
224    }
225
226    pub const fn shared(mut self, queue_families: &'r [u32]) -> Self {
227        assert!(queue_families.len() > 0, "empty families not allowed");
228
229        self.0.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
230        self.0.queueFamilyIndexCount = queue_families.len() as _;
231        self.0.pQueueFamilyIndices = slice_as_ptr_empty_null(queue_families);
232        self
233    }
234
235    pub const fn exclusive(mut self) -> Self {
236        self.0.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
237        self.0.queueFamilyIndexCount = 0;
238        self.0.pQueueFamilyIndices = core::ptr::null();
239
240        self
241    }
242
243    /// Default: Inherit
244    pub const fn pre_transform(mut self, tf: SurfaceTransformFlags) -> Self {
245        self.0.preTransform = tf.bits();
246        self
247    }
248
249    /// Default: Inherit
250    pub const fn composite_alpha(mut self, a: CompositeAlphaFlags) -> Self {
251        self.0.compositeAlpha = a.bits();
252        self
253    }
254
255    /// Default: FIFO
256    pub const fn present_mode(mut self, mode: PresentMode) -> Self {
257        self.0.presentMode = mode as _;
258        self
259    }
260
261    /// Enables whether the Vulkan implementation is allowed to discard rendering operations
262    /// that affect regions of the surface which aren't visible
263    pub const fn enable_clip(mut self) -> Self {
264        self.0.clipped = true as _;
265        self
266    }
267
268    #[inline(always)]
269    pub fn old_swapchain(mut self, old_swapchain: &'sw (impl VkHandle<Handle = VkSwapchainKHR> + ?Sized)) -> Self {
270        self.0.oldSwapchain = old_swapchain.native_ptr();
271        self
272    }
273}