1use std::{borrow::Borrow, fmt, os::raw::c_void, sync::Arc, time::Instant};
2
3use ash::{extensions::khr, version::DeviceV1_0 as _, vk};
4use hal::{format::Format, window as w};
5
6use crate::{
7 conv, info, native, Backend, Device, Instance, PhysicalDevice, QueueFamily, RawDevice,
8 RawInstance,
9};
10
11#[derive(Debug)]
12struct SurfaceFrame {
13 image: vk::Image,
14 view: vk::ImageView,
15}
16
17#[derive(Debug)]
18pub 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
26impl SurfaceSwapchain {
27 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
38pub struct Surface {
39 pub(crate) raw: Arc<RawSurface>,
42 pub(crate) swapchain: Option<SurfaceSwapchain>,
43}
44
45impl fmt::Debug for Surface {
46 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
47 fmt.write_str("Surface")
48 }
49}
50
51pub struct RawSurface {
52 pub(crate) handle: vk::SurfaceKHR,
53 pub(crate) functor: khr::Surface,
54 pub(crate) instance: Arc<RawInstance>,
55}
56
57impl Instance {
58 #[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
59 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")))]
79 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")))]
103 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")]
126 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)]
140 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")]
162 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 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
216 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
232impl w::Surface<Backend> for Surface {
233 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
249 fn capabilities(&self, physical_device: &PhysicalDevice) -> w::SurfaceCapabilities {
250 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 let max_images = if caps.max_image_count == 0 {
271 !0
272 } else {
273 caps.max_image_count
274 };
275
276 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
330 fn supported_formats(&self, physical_device: &PhysicalDevice) -> Option<Vec<Format>> {
331 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 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)]
366pub struct SurfaceImage {
367 pub(crate) index: w::SwapImageIndex,
368 image: native::Image,
369 view: native::ImageView,
370}
371
372impl Borrow<native::Image> for SurfaceImage {
373 fn borrow(&self) -> &native::Image {
374 &self.image
375 }
376}
377
378impl Borrow<native::ImageView> for SurfaceImage {
379 fn borrow(&self) -> &native::ImageView {
380 &self.view
381 }
382}
383
384impl w::PresentationSurface<Backend> for Surface {
385 type SwapchainImage = SurfaceImage;
386
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
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
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
491pub 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
498impl fmt::Debug for Swapchain {
499 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
500 fmt.write_str("Swapchain")
501 }
502}
503
504impl Swapchain {
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 let index = self
516 .functor
517 .acquire_next_image(self.raw, timeout_ns, semaphore, fence);
518
519 match index {
520 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}