voodoo/
swapchain.rs

1use std::sync::Arc;
2use std::marker::PhantomData;
3use smallvec::SmallVec;
4use vks;
5use ::{VdResult, SurfaceKhr, Device, PhysicalDevice, Image, Handle, Semaphore, Fence};
6
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9#[repr(C)]
10pub struct SwapchainKhrHandle(pub(crate) vks::VkSwapchainKHR);
11
12impl SwapchainKhrHandle {
13    #[inline(always)]
14    pub fn to_raw(&self) -> vks::VkSwapchainKHR {
15        self.0
16    }
17}
18
19unsafe impl Handle for SwapchainKhrHandle {
20    type Target = SwapchainKhrHandle;
21
22    /// Returns this object's handle.
23    #[inline(always)]
24    fn handle(&self) -> Self::Target {
25        *self
26    }
27}
28
29
30pub struct SwapchainSupportDetails {
31    pub capabilities: ::SurfaceCapabilitiesKhr,
32    pub formats: SmallVec<[::SurfaceFormatKhr; 64]>,
33    pub present_modes: SmallVec<[::PresentModeKhr; 16]>,
34}
35
36impl SwapchainSupportDetails {
37    pub fn new(surface: &SurfaceKhr, physical_device: &PhysicalDevice)
38            -> VdResult<SwapchainSupportDetails> {
39        let capabilities = physical_device.surface_capabilities_khr(surface)?;
40        let formats = physical_device.surface_formats_khr(surface)?;
41        let present_modes = physical_device.surface_present_modes_khr(surface)?;
42
43        Ok(SwapchainSupportDetails {
44            capabilities,
45            formats,
46            present_modes,
47        })
48    }
49}
50
51
52#[derive(Debug)]
53struct Inner {
54    handle: SwapchainKhrHandle,
55    device: Device,
56    surface: SurfaceKhr,
57    images: SmallVec<[Image; 4]>,
58    image_format: ::Format,
59    extent: ::Extent2d,
60}
61
62#[derive(Debug, Clone)]
63pub struct SwapchainKhr {
64    inner: Arc<Inner>,
65}
66
67impl SwapchainKhr {
68    /// Returns a new `SwapchainKhrBuilder`.
69    pub fn builder<'b>() -> SwapchainKhrBuilder<'b> {
70        SwapchainKhrBuilder::new()
71    }
72
73    /// Returns the images associated with this swapchain.
74    pub fn images(&self) -> &[Image] {
75        &self.inner.images
76    }
77
78    /// Returns this swapchain's image format.
79    pub fn image_format(&self) -> ::Format {
80        self.inner.image_format
81    }
82
83    /// Returns this swapchain's extent.
84    pub fn extent(&self) -> &::Extent2d {
85        &self.inner.extent
86    }
87
88    /// Returns this swapchain's handle.
89    pub fn handle(&self) -> SwapchainKhrHandle {
90        self.inner.handle
91    }
92
93    /// Returns a reference to the associated device.
94    pub fn device(&self) -> &Device {
95        &self.inner.device
96    }
97
98    /// Retrieves the index of the next available presentable image.
99    ///
100    /// https://manned.org/vkAcquireNextImageKHR.3
101    //
102    #[inline]
103    pub fn acquire_next_image_khr(&self, timeout: u64, semaphore: Option<&Semaphore>,
104            fence: Option<&Fence>) -> VdResult<u32> {
105        unsafe { self.inner.device.acquire_next_image_khr(self.handle(), timeout,
106            semaphore.map(|s| s.handle()), fence.map(|f| f.handle())) }
107    }
108}
109
110unsafe impl<'s> Handle for &'s SwapchainKhr {
111    type Target = SwapchainKhrHandle;
112
113    #[inline(always)]
114    fn handle(&self) -> Self::Target {
115        self.inner.handle
116    }
117}
118
119
120impl Drop for Inner {
121    fn drop(&mut self) {
122        unsafe { self.device.destroy_swapchain_khr(self.handle, None); }
123    }
124}
125
126unsafe impl Sync for SwapchainKhr {}
127
128
129/// A Swapchain builder.
130#[derive(Debug, Clone)]
131pub struct SwapchainKhrBuilder<'b> {
132    create_info: ::SwapchainCreateInfoKhr<'b>,
133    // Must keep alive to maintain destruction order:
134    surface: Option<&'b SurfaceKhr>,
135    _p: PhantomData<&'b ()>,
136}
137
138impl<'b> SwapchainKhrBuilder<'b> {
139    /// Returns a new swapchain builder.
140    pub fn new() -> SwapchainKhrBuilder<'b> {
141        SwapchainKhrBuilder {
142            create_info: ::SwapchainCreateInfoKhr::default(),
143            surface: None,
144            _p: PhantomData,
145        }
146    }
147
148    /// Specifies the parameters of swapchain creation.
149    pub fn flags<'s>(&'s mut self, flags: ::SwapchainCreateFlagsKhr)
150            -> &'s mut SwapchainKhrBuilder<'b> {
151        self.create_info.set_flags(flags);
152        self
153    }
154
155    /// Specifies the surface that the swapchain will present images to.
156    pub fn surface<'s, 'p>(&'s mut self, surface: &'p SurfaceKhr)
157            -> &'s mut SwapchainKhrBuilder<'b>
158            where 'p: 'b {
159        self.create_info.set_surface(surface.handle());
160        self.surface = Some(surface);
161        self
162    }
163
164    /// Specifies the minimum number of presentable images that the
165    /// application needs. The platform will either create the swapchain with
166    /// at least that many images, or will fail to create the swapchain.
167    pub fn min_image_count<'s>(&'s mut self, min_image_count: u32)
168            -> &'s mut SwapchainKhrBuilder<'b> {
169        self.create_info.set_min_image_count(min_image_count);
170        self
171    }
172
173    /// Specifies the format that is valid for swapchains on the specified
174    /// surface.
175    pub fn image_format<'s>(&'s mut self, image_format: ::Format)
176            -> &'s mut SwapchainKhrBuilder<'b> {
177        self.create_info.set_image_format(image_format);
178        self
179    }
180
181    /// Specifies the color space that is valid for swapchains on the
182    /// specified surface.
183    pub fn image_color_space<'s>(&'s mut self, image_color_space: ::ColorSpaceKhr)
184            -> &'s mut SwapchainKhrBuilder<'b> {
185        self.create_info.set_image_color_space(image_color_space);
186        self
187    }
188
189    /// Specifies the size (in pixels) of the swapchain. Behavior is
190    /// platform-dependent when the image extent does not match the surface’s
191    /// current extent as returned by `vkGetPhysicalDeviceSurfaceCapabilitiesKHR`.
192    pub fn image_extent<'s>(&'s mut self, image_extent: ::Extent2d)
193            -> &'s mut SwapchainKhrBuilder<'b> {
194        self.create_info.set_image_extent(image_extent);
195        self
196    }
197
198    /// Specifies the number of views in a multiview/stereo surface. For
199    /// non-stereoscopic-3D applications, this value is 1.
200    pub fn image_array_layers<'s>(&'s mut self, image_array_layers: u32)
201            -> &'s mut SwapchainKhrBuilder<'b> {
202        self.create_info.set_image_array_layers(image_array_layers);
203        self
204    }
205
206    /// Specifies the bitmask of `ImageUsageFlagBits`, indicating how the
207    /// application will use the swapchain’s presentable images
208    pub fn image_usage<'s>(&'s mut self, image_usage: ::ImageUsageFlags)
209            -> &'s mut SwapchainKhrBuilder<'b> {
210        self.create_info.set_image_usage(image_usage);
211        self
212    }
213
214    /// Specifies the sharing mode used for the images of the swapchain.
215    pub fn image_sharing_mode<'s>(&'s mut self, image_sharing_mode: ::SharingMode)
216            -> &'s mut SwapchainKhrBuilder<'b> {
217        self.create_info.set_image_sharing_mode(image_sharing_mode);
218        self
219    }
220
221    /// Specifies the queue family indices having access to the images of the
222    /// swapchain in case imageSharingMode is VK_SHARING_MODE_CONCURRENT.
223    pub fn queue_family_indices<'s, 'qfi>(&'s mut self, queue_family_indices: &'qfi [u32])
224            -> &'s mut SwapchainKhrBuilder<'b>
225            where 'qfi: 'b {
226        self.create_info.set_queue_family_indices(queue_family_indices);
227        self
228    }
229
230    /// Specifies the bitmask of VkSurfaceTransformFlagBitsKHR, describing the
231    /// transform, relative to the presentation engine’s natural orientation,
232    /// applied to the image content prior to presentation. If it does not
233    /// match the currentTransform value returned by
234    /// vkGetPhysicalDeviceSurfaceCapabilitiesKHR, the presentation engine
235    /// will transform the image content as part of the presentation operation.
236    pub fn pre_transform<'s>(&'s mut self, pre_transform: ::SurfaceTransformFlagsKhr)
237            -> &'s mut SwapchainKhrBuilder<'b> {
238        self.create_info.set_pre_transform(pre_transform);
239        self
240    }
241
242    /// Specifies the bitmask of VkCompositeAlphaFlagBitsKHR indicating the
243    /// alpha compositing mode to use when this surface is composited together
244    /// with other surfaces on certain window systems.
245    pub fn composite_alpha<'s>(&'s mut self, composite_alpha: ::CompositeAlphaFlagsKhr)
246            -> &'s mut SwapchainKhrBuilder<'b> {
247        self.create_info.set_composite_alpha(composite_alpha);
248        self
249    }
250
251    /// Specifies the presentation mode the swapchain will use. A swapchain’s
252    /// present mode determines how incoming present requests will be
253    /// processed and queued internally.
254    pub fn present_mode<'s>(&'s mut self, present_mode: ::PresentModeKhr)
255            -> &'s mut SwapchainKhrBuilder<'b> {
256        self.create_info.set_present_mode(present_mode);
257        self
258    }
259
260    /// Specifies the whether the Vulkan implementation is allowed to discard
261    /// rendering operations that affect regions of the surface which are not
262    /// visible.
263    ///
264    /// * If set to `true`, the presentable images associated with the
265    ///   swapchain may not own all of their pixels. Pixels in the presentable
266    ///   images that correspond to regions of the target surface obscured by
267    ///   another window on the desktop or subject to some other clipping
268    ///   mechanism will have undefined content when read back. Pixel shaders
269    ///   may not execute for these pixels, and thus any side affects they
270    ///   would have had will not occur.
271    ///
272    /// * If set to `false`, presentable images associated with the swapchain
273    ///   will own all the pixels they contain. Setting this value to VK_TRUE
274    ///   does not guarantee any clipping will occur, but allows more optimal
275    ///   presentation methods to be used on some platforms.
276    ///
277    ///
278    /// Note: Applications should set this value to VK_TRUE if they do not
279    /// expect to read back the content of presentable images before
280    /// presenting them or after reacquiring them and if their pixel shaders
281    /// do not have any side effects that require them to run for all pixels
282    /// in the presentable image.
283    ///
284    pub fn clipped<'s>(&'s mut self, clipped: bool)
285            -> &'s mut SwapchainKhrBuilder<'b> {
286        self.create_info.set_clipped(clipped);
287        self
288    }
289
290    /// If not VK_NULL_HANDLE, specifies the swapchain that will be replaced
291    /// by the new swapchain being created. The new swapchain will be a
292    /// descendant of oldSwapchain. Further, any descendants of the new
293    /// swapchain will also be descendants of oldSwapchain. Upon calling
294    /// vkCreateSwapchainKHR with a oldSwapchain that is not VK_NULL_HANDLE,
295    /// any images not acquired by the application may be freed by the
296    /// implementation, which may occur even if creation of the new swapchain
297    /// fails. The application must destroy the old swapchain to free all
298    /// memory associated with the old swapchain. The application must wait
299    /// for the completion of any outstanding rendering to images it currently
300    /// has acquired at the time the swapchain is destroyed. The application
301    /// can continue to present any images it acquired and has not yet
302    /// presented using the old swapchain, as long as it has not entered a
303    /// state that causes it to return VK_ERROR_OUT_OF_DATE_KHR. However, the
304    /// application cannot acquire any more images from the old swapchain
305    /// regardless of whether or not creation of the new swapchain succeeds.
306    /// The application can continue to use a shared presentable image
307    /// obtained from oldSwapchain until a presentable image is acquired from
308    /// the new swapchain, as long as it has not entered a state that causes
309    /// it to return VK_ERROR_OUT_OF_DATE_KHR.
310    pub fn old_swapchain<'s, H>(&'s mut self, old_swapchain: H)
311            -> &'s mut SwapchainKhrBuilder<'b>
312            where H: Handle<Target=SwapchainKhrHandle> {
313        self.create_info.set_old_swapchain(old_swapchain);
314        self
315    }
316
317    /// Builds and returns a new `SwapchainKhr`.
318    pub fn build(&mut self, device: Device) -> VdResult<SwapchainKhr> {
319        let image_format = self.create_info.image_format().clone();
320        let extent = self.create_info.image_extent().clone();
321
322        let handle = unsafe { device.create_swapchain_khr(&self.create_info, None)? };
323
324        let images = unsafe {
325            device.get_swapchain_images_khr(handle)?.iter().map(|&h| {
326                Image::from_handle(device.clone(), h, true)
327            }).collect()
328        };
329
330        Ok(SwapchainKhr {
331            inner: Arc::new(Inner {
332                handle,
333                device,
334                surface: self.surface.cloned()
335                    .expect("unable to create swapchain: no surface specified"),
336                images,
337                image_format: image_format,
338                extent,
339            })
340        })
341    }
342}