1 use std::{borrow::Borrow, fmt, os::raw::c_void, sync::Arc, time::Instant};
2 
3 use ash::{extensions::khr, version::DeviceV1_0 as _, vk};
4 use hal::{format::Format, window as w};
5 
6 use crate::{
7     conv, info, native, Backend, Device, Instance, PhysicalDevice, QueueFamily, RawDevice,
8     RawInstance,
9 };
10 
11 #[derive(Debug)]
12 struct SurfaceFrame {
13     image: vk::Image,
14     view: vk::ImageView,
15 }
16 
17 #[derive(Debug)]
18 pub struct SurfaceSwapchain {
19     pub(crate) swapchain: Swapchain,
20     device: Arc<RawDevice>,
21     fence: native::Fence,
22     pub(crate) semaphore: native::Semaphore,
23     frames: Vec<SurfaceFrame>,
24 }
25 
26 impl SurfaceSwapchain {
release_resources(self, device: &ash::Device) -> Swapchain27     unsafe fn release_resources(self, device: &ash::Device) -> Swapchain {
28         let _ = device.device_wait_idle();
29         device.destroy_fence(self.fence.0, None);
30         device.destroy_semaphore(self.semaphore.0, None);
31         for frame in self.frames {
32             device.destroy_image_view(frame.view, None);
33         }
34         self.swapchain
35     }
36 }
37 
38 pub struct Surface {
39     // Vk (EXT) specs [29.2.7 Platform-Independent Information]
40     // For vkDestroySurfaceKHR: Host access to surface must be externally synchronized
41     pub(crate) raw: Arc<RawSurface>,
42     pub(crate) swapchain: Option<SurfaceSwapchain>,
43 }
44 
45 impl fmt::Debug for Surface {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result46     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
47         fmt.write_str("Surface")
48     }
49 }
50 
51 pub struct RawSurface {
52     pub(crate) handle: vk::SurfaceKHR,
53     pub(crate) functor: khr::Surface,
54     pub(crate) instance: Arc<RawInstance>,
55 }
56 
57 impl Instance {
58     #[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
create_surface_from_xlib(&self, dpy: *mut vk::Display, window: vk::Window) -> Surface59     pub fn create_surface_from_xlib(&self, dpy: *mut vk::Display, window: vk::Window) -> Surface {
60         if !self.extensions.contains(&khr::XlibSurface::name()) {
61             panic!("Vulkan driver does not support VK_KHR_XLIB_SURFACE");
62         }
63 
64         let surface = {
65             let xlib_loader = khr::XlibSurface::new(&self.entry, &self.raw.inner);
66             let info = vk::XlibSurfaceCreateInfoKHR::builder()
67                 .flags(vk::XlibSurfaceCreateFlagsKHR::empty())
68                 .window(window)
69                 .dpy(dpy);
70 
71             unsafe { xlib_loader.create_xlib_surface(&info, None) }
72                 .expect("XlibSurface::create_xlib_surface() failed")
73         };
74 
75         self.create_surface_from_vk_surface_khr(surface)
76     }
77 
78     #[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
create_surface_from_xcb( &self, connection: *mut vk::xcb_connection_t, window: vk::xcb_window_t, ) -> Surface79     pub fn create_surface_from_xcb(
80         &self,
81         connection: *mut vk::xcb_connection_t,
82         window: vk::xcb_window_t,
83     ) -> Surface {
84         if !self.extensions.contains(&khr::XcbSurface::name()) {
85             panic!("Vulkan driver does not support VK_KHR_XCB_SURFACE");
86         }
87 
88         let surface = {
89             let xcb_loader = khr::XcbSurface::new(&self.entry, &self.raw.inner);
90             let info = vk::XcbSurfaceCreateInfoKHR::builder()
91                 .flags(vk::XcbSurfaceCreateFlagsKHR::empty())
92                 .window(window)
93                 .connection(connection);
94 
95             unsafe { xcb_loader.create_xcb_surface(&info, None) }
96                 .expect("XcbSurface::create_xcb_surface() failed")
97         };
98 
99         self.create_surface_from_vk_surface_khr(surface)
100     }
101 
102     #[cfg(all(unix, not(target_os = "android")))]
create_surface_from_wayland( &self, display: *mut c_void, surface: *mut c_void, ) -> Surface103     pub fn create_surface_from_wayland(
104         &self,
105         display: *mut c_void,
106         surface: *mut c_void,
107     ) -> Surface {
108         if !self.extensions.contains(&khr::WaylandSurface::name()) {
109             panic!("Vulkan driver does not support VK_KHR_WAYLAND_SURFACE");
110         }
111 
112         let surface = {
113             let w_loader = khr::WaylandSurface::new(&self.entry, &self.raw.inner);
114             let info = vk::WaylandSurfaceCreateInfoKHR::builder()
115                 .flags(vk::WaylandSurfaceCreateFlagsKHR::empty())
116                 .display(display)
117                 .surface(surface);
118 
119             unsafe { w_loader.create_wayland_surface(&info, None) }.expect("WaylandSurface failed")
120         };
121 
122         self.create_surface_from_vk_surface_khr(surface)
123     }
124 
125     #[cfg(target_os = "android")]
create_surface_android(&self, window: *const c_void) -> Surface126     pub fn create_surface_android(&self, window: *const c_void) -> Surface {
127         let surface = {
128             let a_loader = khr::AndroidSurface::new(&self.entry, &self.raw.inner);
129             let info = vk::AndroidSurfaceCreateInfoKHR::builder()
130                 .flags(vk::AndroidSurfaceCreateFlagsKHR::empty())
131                 .window(window as *mut _);
132 
133             unsafe { a_loader.create_android_surface(&info, None) }.expect("AndroidSurface failed")
134         };
135 
136         self.create_surface_from_vk_surface_khr(surface)
137     }
138 
139     #[cfg(windows)]
create_surface_from_hwnd(&self, hinstance: *mut c_void, hwnd: *mut c_void) -> Surface140     pub fn create_surface_from_hwnd(&self, hinstance: *mut c_void, hwnd: *mut c_void) -> Surface {
141         if !self.extensions.contains(&khr::Win32Surface::name()) {
142             panic!("Vulkan driver does not support VK_KHR_WIN32_SURFACE");
143         }
144 
145         let surface = {
146             let info = vk::Win32SurfaceCreateInfoKHR::builder()
147                 .flags(vk::Win32SurfaceCreateFlagsKHR::empty())
148                 .hinstance(hinstance)
149                 .hwnd(hwnd);
150             let win32_loader = khr::Win32Surface::new(&self.entry, &self.raw.inner);
151             unsafe {
152                 win32_loader
153                     .create_win32_surface(&info, None)
154                     .expect("Unable to create Win32 surface")
155             }
156         };
157 
158         self.create_surface_from_vk_surface_khr(surface)
159     }
160 
161     #[cfg(target_os = "macos")]
create_surface_from_ns_view(&self, view: *mut c_void) -> Surface162     pub fn create_surface_from_ns_view(&self, view: *mut c_void) -> Surface {
163         use ash::extensions::mvk;
164         use core_graphics_types::{base::CGFloat, geometry::CGRect};
165         use objc::runtime::{Object, BOOL, YES};
166 
167         // TODO: this logic is duplicated from gfx-backend-metal, refactor?
168         unsafe {
169             let view = view as *mut Object;
170             let existing: *mut Object = msg_send![view, layer];
171             let class = class!(CAMetalLayer);
172 
173             let use_current = if existing.is_null() {
174                 false
175             } else {
176                 let result: BOOL = msg_send![existing, isKindOfClass: class];
177                 result == YES
178             };
179 
180             if !use_current {
181                 let layer: *mut Object = msg_send![class, new];
182                 let () = msg_send![view, setLayer: layer];
183                 let bounds: CGRect = msg_send![view, bounds];
184                 let () = msg_send![layer, setBounds: bounds];
185 
186                 let window: *mut Object = msg_send![view, window];
187                 if !window.is_null() {
188                     let scale_factor: CGFloat = msg_send![window, backingScaleFactor];
189                     let () = msg_send![layer, setContentsScale: scale_factor];
190                 }
191             }
192         }
193 
194         if !self.extensions.contains(&mvk::MacOSSurface::name()) {
195             panic!("Vulkan driver does not support VK_MVK_MACOS_SURFACE");
196         }
197 
198         let surface = {
199             let mac_os_loader = mvk::MacOSSurface::new(&self.entry, &self.raw.inner);
200             let mut info = vk::MacOSSurfaceCreateInfoMVK::builder()
201                 .flags(vk::MacOSSurfaceCreateFlagsMVK::empty());
202             if let Some(view) = unsafe { view.as_ref() } {
203                 info = info.view(view);
204             }
205 
206             unsafe {
207                 mac_os_loader
208                     .create_mac_os_surface_mvk(&info, None)
209                     .expect("Unable to create macOS surface")
210             }
211         };
212 
213         self.create_surface_from_vk_surface_khr(surface)
214     }
215 
create_surface_from_vk_surface_khr(&self, surface: vk::SurfaceKHR) -> Surface216     pub fn create_surface_from_vk_surface_khr(&self, surface: vk::SurfaceKHR) -> Surface {
217         let functor = khr::Surface::new(&self.entry, &self.raw.inner);
218 
219         let raw = Arc::new(RawSurface {
220             handle: surface,
221             functor,
222             instance: self.raw.clone(),
223         });
224 
225         Surface {
226             raw,
227             swapchain: None,
228         }
229     }
230 }
231 
232 impl w::Surface<Backend> for Surface {
supports_queue_family(&self, queue_family: &QueueFamily) -> bool233     fn supports_queue_family(&self, queue_family: &QueueFamily) -> bool {
234         match unsafe {
235             self.raw.functor.get_physical_device_surface_support(
236                 queue_family.device,
237                 queue_family.index,
238                 self.raw.handle,
239             )
240         } {
241             Ok(ok) => ok,
242             Err(e) => {
243                 error!("get_physical_device_surface_support error {:?}", e);
244                 false
245             }
246         }
247     }
248 
capabilities(&self, physical_device: &PhysicalDevice) -> w::SurfaceCapabilities249     fn capabilities(&self, physical_device: &PhysicalDevice) -> w::SurfaceCapabilities {
250         // Capabilities
251         let caps = unsafe {
252             match self
253                 .raw
254                 .functor
255                 .get_physical_device_surface_capabilities(physical_device.handle, self.raw.handle)
256             {
257                 Ok(caps) => caps,
258                 Err(vk::Result::ERROR_SURFACE_LOST_KHR) => {
259                     error!(
260                         "get_physical_device_surface_capabilities error {:?}",
261                         vk::Result::ERROR_SURFACE_LOST_KHR
262                     );
263                     vk::SurfaceCapabilitiesKHR::default()
264                 }
265                 Err(e) => panic!("Unable to query surface capabilities {:?}", e),
266             }
267         };
268 
269         // If image count is 0, the support number of images is unlimited.
270         let max_images = if caps.max_image_count == 0 {
271             !0
272         } else {
273             caps.max_image_count
274         };
275 
276         // `0xFFFFFFFF` indicates that the extent depends on the created swapchain.
277         let current_extent = if caps.current_extent.width != !0 && caps.current_extent.height != !0
278         {
279             Some(w::Extent2D {
280                 width: caps.current_extent.width,
281                 height: caps.current_extent.height,
282             })
283         } else {
284             None
285         };
286 
287         let min_extent = w::Extent2D {
288             width: caps.min_image_extent.width,
289             height: caps.min_image_extent.height,
290         };
291 
292         let max_extent = w::Extent2D {
293             width: caps.max_image_extent.width,
294             height: caps.max_image_extent.height,
295         };
296 
297         let raw_present_modes = unsafe {
298             match self
299                 .raw
300                 .functor
301                 .get_physical_device_surface_present_modes(physical_device.handle, self.raw.handle)
302             {
303                 Ok(present_modes) => present_modes,
304                 Err(vk::Result::ERROR_SURFACE_LOST_KHR) => {
305                     error!(
306                         "get_physical_device_surface_present_modes error {:?}",
307                         vk::Result::ERROR_SURFACE_LOST_KHR
308                     );
309                     Vec::new()
310                 }
311                 Err(e) => panic!("Unable to query present modes {:?}", e),
312             }
313         };
314 
315         w::SurfaceCapabilities {
316             present_modes: raw_present_modes
317                 .into_iter()
318                 .fold(w::PresentMode::empty(), |u, m| {
319                     u | conv::map_vk_present_mode(m)
320                 }),
321             composite_alpha_modes: conv::map_vk_composite_alpha(caps.supported_composite_alpha),
322             image_count: caps.min_image_count..=max_images,
323             current_extent,
324             extents: min_extent..=max_extent,
325             max_image_layers: caps.max_image_array_layers as _,
326             usage: conv::map_vk_image_usage(caps.supported_usage_flags),
327         }
328     }
329 
supported_formats(&self, physical_device: &PhysicalDevice) -> Option<Vec<Format>>330     fn supported_formats(&self, physical_device: &PhysicalDevice) -> Option<Vec<Format>> {
331         // Swapchain formats
332         let raw_formats = unsafe {
333             match self
334                 .raw
335                 .functor
336                 .get_physical_device_surface_formats(physical_device.handle, self.raw.handle)
337             {
338                 Ok(formats) => formats,
339                 Err(vk::Result::ERROR_SURFACE_LOST_KHR) => {
340                     error!(
341                         "get_physical_device_surface_formats error {:?}",
342                         vk::Result::ERROR_SURFACE_LOST_KHR
343                     );
344                     return Some(Vec::new());
345                 }
346                 Err(e) => panic!("Unable to query surface formats {:?}", e),
347             }
348         };
349 
350         match raw_formats[0].format {
351             // If pSurfaceFormats includes just one entry, whose value for format is
352             // VK_FORMAT_UNDEFINED, surface has no preferred format. In this case, the application
353             // can use any valid VkFormat value.
354             vk::Format::UNDEFINED => None,
355             _ => Some(
356                 raw_formats
357                     .into_iter()
358                     .filter_map(|sf| conv::map_vk_format(sf.format))
359                     .collect(),
360             ),
361         }
362     }
363 }
364 
365 #[derive(Debug)]
366 pub struct SurfaceImage {
367     pub(crate) index: w::SwapImageIndex,
368     image: native::Image,
369     view: native::ImageView,
370 }
371 
372 impl Borrow<native::Image> for SurfaceImage {
borrow(&self) -> &native::Image373     fn borrow(&self) -> &native::Image {
374         &self.image
375     }
376 }
377 
378 impl Borrow<native::ImageView> for SurfaceImage {
borrow(&self) -> &native::ImageView379     fn borrow(&self) -> &native::ImageView {
380         &self.view
381     }
382 }
383 
384 impl w::PresentationSurface<Backend> for Surface {
385     type SwapchainImage = SurfaceImage;
386 
configure_swapchain( &mut self, device: &Device, config: w::SwapchainConfig, ) -> Result<(), w::SwapchainError>387     unsafe fn configure_swapchain(
388         &mut self,
389         device: &Device,
390         config: w::SwapchainConfig,
391     ) -> Result<(), w::SwapchainError> {
392         use hal::device::Device as _;
393 
394         let usage = config.image_usage;
395         let format = config.format;
396         let old = self
397             .swapchain
398             .take()
399             .map(|ssc| ssc.release_resources(&device.shared.raw));
400 
401         let (swapchain, images) = device.create_swapchain(self, config, old)?;
402 
403         self.swapchain = Some(SurfaceSwapchain {
404             swapchain,
405             device: Arc::clone(&device.shared),
406             fence: device.create_fence(false).unwrap(),
407             semaphore: device.create_semaphore().unwrap(),
408             frames: images
409                 .iter()
410                 .map(|image| {
411                     let view = device
412                         .create_image_view(
413                             image,
414                             hal::image::ViewKind::D2,
415                             format,
416                             hal::format::Swizzle::NO,
417                             usage,
418                             hal::image::SubresourceRange {
419                                 aspects: hal::format::Aspects::COLOR,
420                                 ..Default::default()
421                             },
422                         )
423                         .unwrap();
424                     SurfaceFrame {
425                         image: view.image,
426                         view: view.raw,
427                     }
428                 })
429                 .collect(),
430         });
431 
432         Ok(())
433     }
434 
unconfigure_swapchain(&mut self, device: &Device)435     unsafe fn unconfigure_swapchain(&mut self, device: &Device) {
436         if let Some(ssc) = self.swapchain.take() {
437             let swapchain = ssc.release_resources(&device.shared.raw);
438             swapchain.functor.destroy_swapchain(swapchain.raw, None);
439         }
440     }
441 
acquire_image( &mut self, mut timeout_ns: u64, ) -> Result<(Self::SwapchainImage, Option<w::Suboptimal>), w::AcquireError>442     unsafe fn acquire_image(
443         &mut self,
444         mut timeout_ns: u64,
445     ) -> Result<(Self::SwapchainImage, Option<w::Suboptimal>), w::AcquireError> {
446         let ssc = self.swapchain.as_mut().unwrap();
447         let moment = Instant::now();
448         let (index, suboptimal) =
449             ssc.swapchain
450                 .acquire_image(timeout_ns, None, Some(&ssc.fence))?;
451         timeout_ns = timeout_ns.saturating_sub(moment.elapsed().as_nanos() as u64);
452         let fences = &[ssc.fence.0];
453 
454         match ssc.device.raw.wait_for_fences(fences, true, timeout_ns) {
455             Ok(()) => {
456                 ssc.device.raw.reset_fences(fences).unwrap();
457                 let frame = &ssc.frames[index as usize];
458                 let image = Self::SwapchainImage {
459                     index,
460                     image: native::Image {
461                         raw: frame.image,
462                         ty: vk::ImageType::TYPE_2D,
463                         flags: vk::ImageCreateFlags::empty(),
464                         extent: ssc.swapchain.extent,
465                     },
466                     view: native::ImageView {
467                         image: frame.image,
468                         raw: frame.view,
469                         range: hal::image::SubresourceRange {
470                             aspects: hal::format::Aspects::COLOR,
471                             ..Default::default()
472                         },
473                     },
474                 };
475                 Ok((image, suboptimal))
476             }
477             Err(vk::Result::NOT_READY) => Err(w::AcquireError::NotReady { timeout: false }),
478             Err(vk::Result::TIMEOUT) => Err(w::AcquireError::NotReady { timeout: true }),
479             Err(vk::Result::ERROR_OUT_OF_DATE_KHR) => Err(w::OutOfDate.into()),
480             Err(vk::Result::ERROR_SURFACE_LOST_KHR) => Err(w::SurfaceLost.into()),
481             Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => Err(hal::device::OutOfMemory::Host.into()),
482             Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => {
483                 Err(hal::device::OutOfMemory::Device.into())
484             }
485             Err(vk::Result::ERROR_DEVICE_LOST) => Err(hal::device::DeviceLost.into()),
486             _ => unreachable!(),
487         }
488     }
489 }
490 
491 pub struct Swapchain {
492     pub(crate) raw: vk::SwapchainKHR,
493     pub(crate) functor: khr::Swapchain,
494     pub(crate) vendor_id: u32,
495     pub(crate) extent: vk::Extent3D,
496 }
497 
498 impl fmt::Debug for Swapchain {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result499     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
500         fmt.write_str("Swapchain")
501     }
502 }
503 
504 impl Swapchain {
acquire_image( &mut self, timeout_ns: u64, semaphore: Option<&native::Semaphore>, fence: Option<&native::Fence>, ) -> Result<(w::SwapImageIndex, Option<w::Suboptimal>), w::AcquireError>505     unsafe fn acquire_image(
506         &mut self,
507         timeout_ns: u64,
508         semaphore: Option<&native::Semaphore>,
509         fence: Option<&native::Fence>,
510     ) -> Result<(w::SwapImageIndex, Option<w::Suboptimal>), w::AcquireError> {
511         let semaphore = semaphore.map_or(vk::Semaphore::null(), |s| s.0);
512         let fence = fence.map_or(vk::Fence::null(), |f| f.0);
513 
514         // will block if no image is available
515         let index = self
516             .functor
517             .acquire_next_image(self.raw, timeout_ns, semaphore, fence);
518 
519         match index {
520             // special case for Intel Vulkan returning bizzare values (ugh)
521             Ok((i, _)) if self.vendor_id == info::intel::VENDOR && i > 0x100 => {
522                 Err(w::OutOfDate.into())
523             }
524             Ok((i, true)) => Ok((i, Some(w::Suboptimal))),
525             Ok((i, false)) => Ok((i, None)),
526             Err(vk::Result::NOT_READY) => Err(w::AcquireError::NotReady { timeout: false }),
527             Err(vk::Result::TIMEOUT) => Err(w::AcquireError::NotReady { timeout: true }),
528             Err(vk::Result::ERROR_OUT_OF_DATE_KHR) => Err(w::OutOfDate.into()),
529             Err(vk::Result::ERROR_SURFACE_LOST_KHR) => Err(w::SurfaceLost.into()),
530             Err(vk::Result::ERROR_OUT_OF_HOST_MEMORY) => Err(hal::device::OutOfMemory::Host.into()),
531             Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => {
532                 Err(hal::device::OutOfMemory::Device.into())
533             }
534             Err(vk::Result::ERROR_DEVICE_LOST) => Err(hal::device::DeviceLost.into()),
535             _ => panic!("Failed to acquire image."),
536         }
537     }
538 }
539