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