diff --git a/ash-window/Cargo.toml b/ash-window/Cargo.toml index 9add9ac..9642f4f 100644 --- a/ash-window/Cargo.toml +++ b/ash-window/Cargo.toml @@ -16,13 +16,13 @@ rust-version = "1.59.0" [dependencies] ash = { path = "../ash", version = "0.37", default-features = false } -raw-window-handle = "0.4.2" +raw-window-handle = "0.5" [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] -raw-window-metal = "0.2" +raw-window-metal = "0.3" [dev-dependencies] -winit = "0.26" +winit = "0.27.1" ash = { path = "../ash", version = "0.37", default-features = false, features = ["linked"] } [[example]] diff --git a/ash-window/Changelog.md b/ash-window/Changelog.md index 8597d5b..26e414d 100644 --- a/ash-window/Changelog.md +++ b/ash-window/Changelog.md @@ -2,6 +2,9 @@ ## [Unreleased] - ReleaseDate +- Bumped `raw-window-handle` to `0.5.0`, now taking `RawDisplayHandle` and `RawWindowHandle` directly + instead of requiring dynamic dispatch through the `HasRaw{Display,Window}Handle` traits (#645) + ## [0.11.0] - 2022-07-29 ### Changed diff --git a/ash-window/README.md b/ash-window/README.md index 5fd5394..3bf7919 100644 --- a/ash-window/README.md +++ b/ash-window/README.md @@ -17,9 +17,9 @@ ash-window = "0.11.0" The library exposes two functions: -- [`enumerate_required_extensions`] returns the required instance extensions needed for surface creation from a specific window handle. +- [`enumerate_required_extensions`] returns the required instance extensions needed for surface creation from a specific display handle. -- [`create_surface`] allows to create a surface from a type implementing [`HasRawWindowHandle`]: +- [`create_surface`] allows to create a surface from a type implementing [`RawDisplayHandle`] and [`RawWindowHandle`]: ```rust ash_window::create_surface(&entry, &instance, &window, None)?; @@ -27,7 +27,8 @@ The library exposes two functions: [`enumerate_required_extensions`]: https://docs.rs/ash-window/latest/ash_window/fn.enumerate_required_extensions.html [`create_surface`]: https://docs.rs/ash-window/latest/ash_window/fn.create_surface.html -[`HasRawWindowHandle`]: https://docs.rs/raw-window-handle/latest/raw_window_handle/trait.HasRawWindowHandle.html +[`RawDisplayHandle`]: https://docs.rs/raw-window-handle/latest/raw_window_handle/enum.RawDisplayHandle.html +[`RawWindowHandle`]: https://docs.rs/raw-window-handle/latest/raw_window_handle/enum.RawWindowHandle.html ## Versions ```toml diff --git a/ash-window/examples/winit.rs b/ash-window/examples/winit.rs index 1830d69..6124de2 100644 --- a/ash-window/examples/winit.rs +++ b/ash-window/examples/winit.rs @@ -6,6 +6,7 @@ //! On instance extensions platform specific extensions need to be enabled. use ash::vk; +use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::error::Error; use winit::{ dpi::PhysicalSize, @@ -16,13 +17,11 @@ use winit::{ fn main() -> Result<(), Box> { let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_inner_size(PhysicalSize::::from((800, 600))) - .build(&event_loop)?; unsafe { let entry = ash::Entry::linked(); - let surface_extensions = ash_window::enumerate_required_extensions(&window)?; + let surface_extensions = + ash_window::enumerate_required_extensions(event_loop.raw_display_handle())?; let app_desc = vk::ApplicationInfo::builder().api_version(vk::make_api_version(0, 1, 0, 0)); let instance_desc = vk::InstanceCreateInfo::builder() .application_info(&app_desc) @@ -30,8 +29,18 @@ fn main() -> Result<(), Box> { let instance = entry.create_instance(&instance_desc, None)?; + let window = WindowBuilder::new() + .with_inner_size(PhysicalSize::::from((800, 600))) + .build(&event_loop)?; + // Create a surface from winit window. - let surface = ash_window::create_surface(&entry, &instance, &window, None)?; + let surface = ash_window::create_surface( + &entry, + &instance, + window.raw_display_handle(), + window.raw_window_handle(), + None, + )?; let surface_fn = ash::extensions::khr::Surface::new(&entry, &instance); println!("surface: {:?}", surface); diff --git a/ash-window/src/lib.rs b/ash-window/src/lib.rs index 15680e6..f320dc4 100644 --- a/ash-window/src/lib.rs +++ b/ash-window/src/lib.rs @@ -7,68 +7,76 @@ use ash::{ prelude::*, vk, Entry, Instance, }; -use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; +use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; /// Create a surface from a raw surface handle. /// -/// `instance` must have created with platform specific surface extensions enabled. +/// `instance` must have created with platform specific surface extensions enabled, acquired +/// through [`enumerate_required_extensions()`]. /// /// # Safety /// /// In order for the created [`vk::SurfaceKHR`] to be valid for the duration of its /// usage, the [`Instance`] this was called on must be dropped later than the /// resulting [`vk::SurfaceKHR`]. +/// +/// The window represented by `window_handle` must be associated with the display connection +/// in `display_handle`. +/// +/// `window_handle` and `display_handle` must be associated with a valid window and display +/// connection, which must not be destroyed for the lifetime of the returned [`vk::SurfaceKHR`]. pub unsafe fn create_surface( entry: &Entry, instance: &Instance, - window_handle: &dyn HasRawWindowHandle, + display_handle: RawDisplayHandle, + window_handle: RawWindowHandle, allocation_callbacks: Option<&vk::AllocationCallbacks>, ) -> VkResult { - match window_handle.raw_window_handle() { - RawWindowHandle::Win32(handle) => { + match (display_handle, window_handle) { + (RawDisplayHandle::Windows(_), RawWindowHandle::Win32(window)) => { let surface_desc = vk::Win32SurfaceCreateInfoKHR::builder() - .hinstance(handle.hinstance) - .hwnd(handle.hwnd); + .hinstance(window.hinstance) + .hwnd(window.hwnd); let surface_fn = khr::Win32Surface::new(entry, instance); surface_fn.create_win32_surface(&surface_desc, allocation_callbacks) } - RawWindowHandle::Wayland(handle) => { + (RawDisplayHandle::Wayland(display), RawWindowHandle::Wayland(window)) => { let surface_desc = vk::WaylandSurfaceCreateInfoKHR::builder() - .display(handle.display) - .surface(handle.surface); + .display(display.display) + .surface(window.surface); let surface_fn = khr::WaylandSurface::new(entry, instance); surface_fn.create_wayland_surface(&surface_desc, allocation_callbacks) } - RawWindowHandle::Xlib(handle) => { + (RawDisplayHandle::Xlib(display), RawWindowHandle::Xlib(window)) => { let surface_desc = vk::XlibSurfaceCreateInfoKHR::builder() - .dpy(handle.display as *mut _) - .window(handle.window); + .dpy(display.display as *mut _) + .window(window.window); let surface_fn = khr::XlibSurface::new(entry, instance); surface_fn.create_xlib_surface(&surface_desc, allocation_callbacks) } - RawWindowHandle::Xcb(handle) => { + (RawDisplayHandle::Xcb(display), RawWindowHandle::Xcb(window)) => { let surface_desc = vk::XcbSurfaceCreateInfoKHR::builder() - .connection(handle.connection) - .window(handle.window); + .connection(display.connection) + .window(window.window); let surface_fn = khr::XcbSurface::new(entry, instance); surface_fn.create_xcb_surface(&surface_desc, allocation_callbacks) } - RawWindowHandle::AndroidNdk(handle) => { + (RawDisplayHandle::Android(_), RawWindowHandle::AndroidNdk(window)) => { let surface_desc = - vk::AndroidSurfaceCreateInfoKHR::builder().window(handle.a_native_window); + vk::AndroidSurfaceCreateInfoKHR::builder().window(window.a_native_window); let surface_fn = khr::AndroidSurface::new(entry, instance); surface_fn.create_android_surface(&surface_desc, allocation_callbacks) } #[cfg(target_os = "macos")] - RawWindowHandle::AppKit(handle) => { + (RawDisplayHandle::AppKit(_), RawWindowHandle::AppKit(window)) => { use raw_window_metal::{appkit, Layer}; - let layer = match appkit::metal_layer_from_handle(handle) { + let layer = match appkit::metal_layer_from_handle(window) { Layer::Existing(layer) | Layer::Allocated(layer) => layer as *mut _, Layer::None => return Err(vk::Result::ERROR_INITIALIZATION_FAILED), }; @@ -79,10 +87,10 @@ pub unsafe fn create_surface( } #[cfg(target_os = "ios")] - RawWindowHandle::UiKit(handle) => { + (RawDisplayHandle::UiKit(_), RawWindowHandle::UiKit(window)) => { use raw_window_metal::{uikit, Layer}; - let layer = match uikit::metal_layer_from_handle(handle) { + let layer = match uikit::metal_layer_from_handle(window) { Layer::Existing(layer) | Layer::Allocated(layer) => layer as *mut _, Layer::None => return Err(vk::Result::ERROR_INITIALIZATION_FAILED), }; @@ -96,14 +104,18 @@ pub unsafe fn create_surface( } } -/// Query the required instance extensions for creating a surface from a window handle. +/// Query the required instance extensions for creating a surface from a display handle. +/// +/// This [`RawDisplayHandle`] can typically be acquired from a window, but is usually also +/// accessible earlier through an "event loop" concept to allow querying required instance +/// extensions and creation of a compatible Vulkan instance prior to creating a window. /// /// The returned extensions will include all extension dependencies. pub fn enumerate_required_extensions( - window_handle: &dyn HasRawWindowHandle, + display_handle: RawDisplayHandle, ) -> VkResult<&'static [*const c_char]> { - let extensions = match window_handle.raw_window_handle() { - RawWindowHandle::Win32(_) => { + let extensions = match display_handle { + RawDisplayHandle::Windows(_) => { const WINDOWS_EXTS: [*const c_char; 2] = [ khr::Surface::name().as_ptr(), khr::Win32Surface::name().as_ptr(), @@ -111,7 +123,7 @@ pub fn enumerate_required_extensions( &WINDOWS_EXTS } - RawWindowHandle::Wayland(_) => { + RawDisplayHandle::Wayland(_) => { const WAYLAND_EXTS: [*const c_char; 2] = [ khr::Surface::name().as_ptr(), khr::WaylandSurface::name().as_ptr(), @@ -119,7 +131,7 @@ pub fn enumerate_required_extensions( &WAYLAND_EXTS } - RawWindowHandle::Xlib(_) => { + RawDisplayHandle::Xlib(_) => { const XLIB_EXTS: [*const c_char; 2] = [ khr::Surface::name().as_ptr(), khr::XlibSurface::name().as_ptr(), @@ -127,7 +139,7 @@ pub fn enumerate_required_extensions( &XLIB_EXTS } - RawWindowHandle::Xcb(_) => { + RawDisplayHandle::Xcb(_) => { const XCB_EXTS: [*const c_char; 2] = [ khr::Surface::name().as_ptr(), khr::XcbSurface::name().as_ptr(), @@ -135,7 +147,7 @@ pub fn enumerate_required_extensions( &XCB_EXTS } - RawWindowHandle::AndroidNdk(_) => { + RawDisplayHandle::Android(_) => { const ANDROID_EXTS: [*const c_char; 2] = [ khr::Surface::name().as_ptr(), khr::AndroidSurface::name().as_ptr(), @@ -143,7 +155,7 @@ pub fn enumerate_required_extensions( &ANDROID_EXTS } - RawWindowHandle::AppKit(_) | RawWindowHandle::UiKit(_) => { + RawDisplayHandle::AppKit(_) | RawDisplayHandle::UiKit(_) => { const METAL_EXTS: [*const c_char; 2] = [ khr::Surface::name().as_ptr(), ext::MetalSurface::name().as_ptr(), diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 3615ed0..bbf21ec 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -5,8 +5,9 @@ authors = ["maik klein "] edition = "2018" [dependencies] -winit = "0.26" -image = "0.23" +image = "0.24" +raw-window-handle = "0.5" +winit = "0.27.1" # The examples require the validation layers, which means the SDK or # equivalent development packages should be present, so we can link # directly and benefit from the infallible `Entry` constructor. diff --git a/examples/src/lib.rs b/examples/src/lib.rs index 1e8a137..fc07a4d 100644 --- a/examples/src/lib.rs +++ b/examples/src/lib.rs @@ -5,9 +5,9 @@ use ash::extensions::{ ext::DebugUtils, khr::{Surface, Swapchain}, }; - use ash::{vk, Entry}; pub use ash::{Device, Instance}; +use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::borrow::Cow; use std::cell::RefCell; use std::default::Default; @@ -233,9 +233,10 @@ impl ExampleBase { .map(|raw_name| raw_name.as_ptr()) .collect(); - let mut extension_names = ash_window::enumerate_required_extensions(&window) - .unwrap() - .to_vec(); + let mut extension_names = + ash_window::enumerate_required_extensions(window.raw_display_handle()) + .unwrap() + .to_vec(); extension_names.push(DebugUtils::name().as_ptr()); #[cfg(any(target_os = "macos", target_os = "ios"))] @@ -285,7 +286,14 @@ impl ExampleBase { let debug_call_back = debug_utils_loader .create_debug_utils_messenger(&debug_info, None) .unwrap(); - let surface = ash_window::create_surface(&entry, &instance, &window, None).unwrap(); + let surface = ash_window::create_surface( + &entry, + &instance, + window.raw_display_handle(), + window.raw_window_handle(), + None, + ) + .unwrap(); let pdevices = instance .enumerate_physical_devices() .expect("Physical device error");