Skip to content

Commit

Permalink
ash-window: Upgrade to raw-window-handle 0.6.0
Browse files Browse the repository at this point in the history
This is the successor to #795.  While it doesn't tackle things like
backwards-compatibility nor use of the new lifetimed handles (if we _can_
even come up with a safe abstraction for them - it's very likely out of
scope!), it includes the following improvements:

- Upgrade `raw-window-metal` via [#8] (Mac/iOS wasn't tested in our CI);
- Fix Windows platform types (in the `ash` crate) to be `isize` instead
  of `*const c_void`, matching the usptream definition;
- Update example code (impossible until `winit` with `raw-window-handle
  0.6` becomes available).

[#8]: rust-windowing/raw-window-metal#8
  • Loading branch information
MarijnS95 committed Oct 18, 2023
1 parent d0d5ea1 commit 5fcf4da
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 76 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[workspace]
resolver = "2"
members = [
"examples",
"ash",
Expand All @@ -8,3 +9,7 @@ members = [
"generator",
"generator-rewrite",
]

[patch.crates-io]
raw-window-metal = { git = "https://github.com/MarijnS95/raw-window-metal", rev = "517317cb27bacd82dd60b166bd5c1e12c90ba06d" }
winit = { git = "https://github.com/rust-windowing/winit/", rev = "880238a24f3ff7ba612764dfde020c418629c1de" }
4 changes: 2 additions & 2 deletions ash-window/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ rust-version = "1.64.0"

[dependencies]
ash = { path = "../ash", version = "0.37", default-features = false }
raw-window-handle = "0.5"
raw-window-handle = "0.6"

[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
raw-window-metal = "0.3"

[dev-dependencies]
winit = "0.28.0"
winit = { version = "0.29.1-beta", features = ["rwh_06"] }
ash = { path = "../ash", version = "0.37", default-features = false, features = ["linked"] }

[[example]]
Expand Down
3 changes: 2 additions & 1 deletion ash-window/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

## [Unreleased] - ReleaseDate

- Bumped MSRV from 1.59 to 1.64 for `winit 0.28` and `raw-window-handle 0.5.1`. (#709, #716)
- Bumped MSRV from 1.59 to 1.64 for `winit 0.28` and `raw-window-handle 0.5.1` (#709, #716)
- Bumped `raw-window-handle` to `0.6.0` (#799)

## [0.12.0] - 2022-09-23

Expand Down
58 changes: 31 additions & 27 deletions ash-window/examples/winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,23 @@
//! 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,
event::{Event, VirtualKeyCode, WindowEvent},
event_loop::{ControlFlow, EventLoop},
event::{Event, KeyEvent, WindowEvent},
event_loop::EventLoop,
keyboard::Key,
raw_window_handle::{HasDisplayHandle, HasWindowHandle},
window::WindowBuilder,
};

fn main() -> Result<(), Box<dyn Error>> {
let event_loop = EventLoop::new();
let event_loop = EventLoop::new()?;

unsafe {
let entry = ash::Entry::linked();
let surface_extensions =
ash_window::enumerate_required_extensions(event_loop.raw_display_handle())?;
ash_window::enumerate_required_extensions(event_loop.display_handle()?)?;
let app_desc = vk::ApplicationInfo::default().api_version(vk::make_api_version(0, 1, 0, 0));
let instance_desc = vk::InstanceCreateInfo::default()
.application_info(&app_desc)
Expand All @@ -37,33 +38,36 @@ fn main() -> Result<(), Box<dyn Error>> {
let surface = ash_window::create_surface(
&entry,
&instance,
window.raw_display_handle(),
window.raw_window_handle(),
window.display_handle()?,
window.window_handle()?,
None,
)?;
let surface_fn = ash::extensions::khr::Surface::new(&entry, &instance);
println!("surface: {surface:?}");

event_loop.run(move |event, _, control_flow| match event {
winit::event::Event::WindowEvent {
event:
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
input:
winit::event::KeyboardInput {
virtual_keycode: Some(VirtualKeyCode::Escape),
..
},
..
},
window_id: _,
} => {
*control_flow = ControlFlow::Exit;
let _ = event_loop.run(move |event, _| {
match event {
winit::event::Event::WindowEvent {
event:
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
event:
KeyEvent {
logical_key: Key::Escape,
..
},
..
},
window_id: _,
} => {
// *control_flow = ControlFlow::Exit;
}
Event::LoopExiting => {
surface_fn.destroy_surface(surface, None);
}
_ => {}
}
Event::LoopDestroyed => {
surface_fn.destroy_surface(surface, None);
}
_ => {}
})
});
Ok(())
}
}
93 changes: 81 additions & 12 deletions ash-window/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use ash::{
prelude::*,
vk, Entry, Instance,
};
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
use raw_window_handle::{DisplayHandle, RawDisplayHandle, RawWindowHandle, WindowHandle};

/// Create a surface from a raw surface handle.
/// Create a surface from display and window handle.
///
/// `instance` must have created with platform specific surface extensions enabled, acquired
/// through [`enumerate_required_extensions()`].
Expand All @@ -33,6 +33,47 @@ use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
///
/// [parent/child relation]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#fundamentals-objectmodel-lifetime
pub unsafe fn create_surface(
entry: &Entry,
instance: &Instance,
display_handle: DisplayHandle<'_>,
window_handle: WindowHandle<'_>,
allocation_callbacks: Option<&vk::AllocationCallbacks>,
) -> VkResult<vk::SurfaceKHR> {
#[allow(deprecated)]
create_surface_raw(
entry,
instance,
display_handle.as_raw(),
window_handle.as_raw(),
allocation_callbacks,
)
}

/// Create a surface from a raw surface handle.
///
/// `instance` must have created with platform specific surface extensions enabled, acquired
/// through [`enumerate_required_extensions()`].
///
/// # Safety
///
/// There is a [parent/child relation] between [`Instance`] and [`Entry`], and the resulting
/// [`vk::SurfaceKHR`]. The application must not [destroy][Instance::destroy_instance()] these
/// parent objects before first [destroying][khr::Surface::destroy_surface()] the returned
/// [`vk::SurfaceKHR`] child object. [`vk::SurfaceKHR`] does _not_ implement [drop][drop()]
/// semantics and can only be destroyed via [`destroy_surface()`][khr::Surface::destroy_surface()].
///
/// See the [`Entry::create_instance()`] documentation for more destruction ordering rules on
/// [`Instance`].
///
/// 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`].
///
/// [parent/child relation]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#fundamentals-objectmodel-lifetime
#[deprecated = "Direct use of raw window handles is deprecated"]
pub unsafe fn create_surface_raw(
entry: &Entry,
instance: &Instance,
display_handle: RawDisplayHandle,
Expand All @@ -42,39 +83,54 @@ pub unsafe fn create_surface(
match (display_handle, window_handle) {
(RawDisplayHandle::Windows(_), RawWindowHandle::Win32(window)) => {
let surface_desc = vk::Win32SurfaceCreateInfoKHR::default()
.hinstance(window.hinstance as isize)
.hwnd(window.hwnd as isize);
.hwnd(window.hwnd.get())
.hinstance(
window
.hinstance
.ok_or(vk::Result::ERROR_INITIALIZATION_FAILED)?
.get(),
);
let surface_fn = khr::Win32Surface::new(entry, instance);
surface_fn.create_win32_surface(&surface_desc, allocation_callbacks)
}

(RawDisplayHandle::Wayland(display), RawWindowHandle::Wayland(window)) => {
let surface_desc = vk::WaylandSurfaceCreateInfoKHR::default()
.display(display.display)
.surface(window.surface);
.display(display.display.as_ptr())
.surface(window.surface.as_ptr());
let surface_fn = khr::WaylandSurface::new(entry, instance);
surface_fn.create_wayland_surface(&surface_desc, allocation_callbacks)
}

(RawDisplayHandle::Xlib(display), RawWindowHandle::Xlib(window)) => {
let surface_desc = vk::XlibSurfaceCreateInfoKHR::default()
.dpy(display.display.cast())
.dpy(
display
.display
.ok_or(vk::Result::ERROR_INITIALIZATION_FAILED)?
.as_ptr(),
)
.window(window.window);
let surface_fn = khr::XlibSurface::new(entry, instance);
surface_fn.create_xlib_surface(&surface_desc, allocation_callbacks)
}

(RawDisplayHandle::Xcb(display), RawWindowHandle::Xcb(window)) => {
let surface_desc = vk::XcbSurfaceCreateInfoKHR::default()
.connection(display.connection)
.window(window.window);
.connection(
display
.connection
.ok_or(vk::Result::ERROR_INITIALIZATION_FAILED)?
.as_ptr(),
)
.window(window.window.get());
let surface_fn = khr::XcbSurface::new(entry, instance);
surface_fn.create_xcb_surface(&surface_desc, allocation_callbacks)
}

(RawDisplayHandle::Android(_), RawWindowHandle::AndroidNdk(window)) => {
let surface_desc =
vk::AndroidSurfaceCreateInfoKHR::default().window(window.a_native_window);
vk::AndroidSurfaceCreateInfoKHR::default().window(window.a_native_window.as_ptr());
let surface_fn = khr::AndroidSurface::new(entry, instance);
surface_fn.create_android_surface(&surface_desc, allocation_callbacks)
}
Expand All @@ -85,7 +141,6 @@ pub unsafe fn create_surface(

let layer = match appkit::metal_layer_from_handle(window) {
Layer::Existing(layer) | Layer::Allocated(layer) => layer.cast(),
Layer::None => return Err(vk::Result::ERROR_INITIALIZATION_FAILED),
};

let surface_desc = vk::MetalSurfaceCreateInfoEXT::default().layer(&*layer);
Expand All @@ -99,7 +154,6 @@ pub unsafe fn create_surface(

let layer = match uikit::metal_layer_from_handle(window) {
Layer::Existing(layer) | Layer::Allocated(layer) => layer.cast(),
Layer::None => return Err(vk::Result::ERROR_INITIALIZATION_FAILED),
};

let surface_desc = vk::MetalSurfaceCreateInfoEXT::default().layer(&*layer);
Expand All @@ -119,6 +173,21 @@ pub unsafe fn create_surface(
///
/// The returned extensions will include all extension dependencies.
pub fn enumerate_required_extensions(
display_handle: DisplayHandle<'_>,
) -> VkResult<&'static [*const c_char]> {
#[allow(deprecated)]
enumerate_required_extensions_raw(display_handle.as_raw())
}

/// 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.
#[deprecated = "Direct use of raw display handles is deprecated"]
pub fn enumerate_required_extensions_raw(
display_handle: RawDisplayHandle,
) -> VkResult<&'static [*const c_char]> {
let extensions = match display_handle {
Expand Down
3 changes: 1 addition & 2 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ edition = "2021"

[dependencies]
image = "0.24"
raw-window-handle = "0.5"
winit = "0.28.0"
winit = { version = "0.29.1-beta", features = ["rwh_06"] }
# 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.
Expand Down
Loading

0 comments on commit 5fcf4da

Please sign in to comment.