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}