Skip to content

Commit

Permalink
ash-window: Upgrade to raw-window-handle 0.6.0 (#799)
Browse files Browse the repository at this point in the history
* ash-window: Upgrade to raw-window-handle 0.6.0

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

* ash-window/examples/winit: Demonstrate proper surface lifetime with `Suspended`/`Resumed` events
  • Loading branch information
MarijnS95 authored Mar 24, 2024
1 parent bd63892 commit 9d225c5
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 87 deletions.
3 changes: 1 addition & 2 deletions ash-examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ publish = false

[dependencies]
image = "0.24"
raw-window-handle = "0.5"
winit = "0.28.0"
winit = { version = "0.29", 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
9 changes: 6 additions & 3 deletions ash-examples/src/bin/texture.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![warn(unused_qualifications)]

use std::default::Default;
use std::error::Error;
use std::ffi::CStr;
use std::io::Cursor;
use std::mem;
Expand All @@ -24,9 +25,9 @@ pub struct Vector3 {
pub _pad: f32,
}

fn main() {
fn main() -> Result<(), Box<dyn Error>> {
unsafe {
let base = ExampleBase::new(1920, 1080);
let base = ExampleBase::new(1920, 1080)?;

let renderpass_attachments = [
vk::AttachmentDescription {
Expand Down Expand Up @@ -686,7 +687,7 @@ fn main() {

let graphic_pipeline = graphics_pipelines[0];

base.render_loop(|| {
let _ = base.render_loop(|| {
let (present_index, _) = base
.swapchain_loader
.acquire_next_image(
Expand Down Expand Up @@ -813,5 +814,7 @@ fn main() {
base.device.destroy_framebuffer(framebuffer, None);
}
base.device.destroy_render_pass(renderpass, None);

Ok(())
}
}
9 changes: 6 additions & 3 deletions ash-examples/src/bin/triangle.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![warn(unused_qualifications)]

use std::default::Default;
use std::error::Error;
use std::ffi::CStr;
use std::io::Cursor;
use std::mem;
Expand All @@ -15,9 +16,9 @@ struct Vertex {
color: [f32; 4],
}

fn main() {
fn main() -> Result<(), Box<dyn Error>> {
unsafe {
let base = ExampleBase::new(1920, 1080);
let base = ExampleBase::new(1920, 1080)?;
let renderpass_attachments = [
vk::AttachmentDescription {
format: base.surface_format.format,
Expand Down Expand Up @@ -348,7 +349,7 @@ fn main() {

let graphic_pipeline = graphics_pipelines[0];

base.render_loop(|| {
let _ = base.render_loop(|| {
let (present_index, _) = base
.swapchain_loader
.acquire_next_image(
Expand Down Expand Up @@ -455,4 +456,6 @@ fn main() {
}
base.device.destroy_render_pass(renderpass, None);
}

Ok(())
}
83 changes: 40 additions & 43 deletions ash-examples/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,24 @@
unused_qualifications
)]

use std::{
borrow::Cow, cell::RefCell, default::Default, error::Error, ffi::CStr, ops::Drop,
os::raw::c_char,
};

use ash::extensions::{
ext::debug_utils,
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;
use std::ffi::CStr;
use std::ops::Drop;
use std::os::raw::c_char;

#[cfg(any(target_os = "macos", target_os = "ios"))]
use ash::vk::khr;

use ash::{vk, Device, Entry, Instance};
use winit::{
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
platform::run_return::EventLoopExtRunReturn,
keyboard::{Key, NamedKey},
platform::run_on_demand::EventLoopExtRunOnDemand,
raw_window_handle::{HasDisplayHandle, HasWindowHandle},
window::WindowBuilder,
};

Expand Down Expand Up @@ -180,35 +177,35 @@ pub struct ExampleBase {
}

impl ExampleBase {
pub fn render_loop<F: Fn()>(&self, f: F) {
self.event_loop
.borrow_mut()
.run_return(|event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
Event::WindowEvent {
event:
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::Escape),
..
},
..
},
..
} => *control_flow = ControlFlow::Exit,
Event::MainEventsCleared => f(),
_ => (),
pub fn render_loop<F: Fn()>(&self, f: F) -> Result<(), impl Error> {
self.event_loop.borrow_mut().run_on_demand(|event, elwp| {
elwp.set_control_flow(ControlFlow::Poll);
match event {
Event::WindowEvent {
event:
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
event:
KeyEvent {
state: ElementState::Pressed,
logical_key: Key::Named(NamedKey::Escape),
..
},
..
},
..
} => {
elwp.exit();
}
});
Event::AboutToWait => f(),
_ => (),
}
})
}

pub fn new(window_width: u32, window_height: u32) -> Self {
pub fn new(window_width: u32, window_height: u32) -> Result<Self, Box<dyn Error>> {
unsafe {
let event_loop = EventLoop::new();
let event_loop = EventLoop::new()?;
let window = WindowBuilder::new()
.with_title("Ash - Example")
.with_inner_size(winit::dpi::LogicalSize::new(
Expand All @@ -229,7 +226,7 @@ impl ExampleBase {
.collect();

let mut extension_names =
ash_window::enumerate_required_extensions(window.raw_display_handle())
ash_window::enumerate_required_extensions(window.display_handle()?.as_raw())
.unwrap()
.to_vec();
extension_names.push(debug_utils::NAME.as_ptr());
Expand Down Expand Up @@ -284,8 +281,8 @@ impl ExampleBase {
let surface = ash_window::create_surface(
&entry,
&instance,
window.raw_display_handle(),
window.raw_window_handle(),
window.display_handle()?.as_raw(),
window.window_handle()?.as_raw(),
None,
)
.unwrap();
Expand Down Expand Up @@ -545,7 +542,7 @@ impl ExampleBase {
.create_semaphore(&semaphore_create_info, None)
.unwrap();

Self {
Ok(Self {
event_loop: RefCell::new(event_loop),
entry,
instance,
Expand Down Expand Up @@ -575,7 +572,7 @@ impl ExampleBase {
debug_call_back,
debug_utils_loader,
depth_image_memory,
}
})
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions ash-window/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ rust-version = "1.69.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"
raw-window-metal = "0.4"

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

[[example]]
Expand Down
1 change: 1 addition & 0 deletions ash-window/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## [Unreleased] - ReleaseDate

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

## [0.12.0] - 2022-09-23

Expand Down
64 changes: 43 additions & 21 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, NamedKey},
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()?.as_raw())?;
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 @@ -33,37 +34,58 @@ fn main() -> Result<(), Box<dyn Error>> {
.with_inner_size(PhysicalSize::<u32>::from((800, 600)))
.build(&event_loop)?;

// Create a surface from winit window.
let surface = ash_window::create_surface(
&entry,
&instance,
window.raw_display_handle(),
window.raw_window_handle(),
None,
)?;
// Load the surface extensions
let surface_fn = ash::extensions::khr::surface::Instance::new(&entry, &instance);
println!("surface: {surface:?}");
let mut surface = None;

event_loop.run(move |event, _, control_flow| match event {
let _ = event_loop.run(move |event, elwp| match event {
winit::event::Event::WindowEvent {
event:
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
input:
winit::event::KeyboardInput {
virtual_keycode: Some(VirtualKeyCode::Escape),
event:
KeyEvent {
logical_key: Key::Named(NamedKey::Escape),
..
},
..
},
window_id: _,
} => {
*control_flow = ControlFlow::Exit;
elwp.exit();
}
Event::LoopDestroyed => {
Event::LoopExiting => {
// This will be the last event before the loop terminates.
// TODO: How does this play with Suspended?
// https://github.com/rust-windowing/winit/issues/3206
if let Some(surface) = surface.take() {
surface_fn.destroy_surface(surface, None);
}
}
Event::Resumed => {
// Create a surface from winit window.
let s = ash_window::create_surface(
&entry,
&instance,
window.display_handle().unwrap().as_raw(),
window.window_handle().unwrap().as_raw(),
None,
)
.unwrap();
println!("surface: {s:?}");
assert!(
surface.replace(s).is_none(),
"Surface must not yet exist when Resumed is called"
);
}
Event::Suspended => {
let surface = surface
.take()
.expect("Surface must have been created in Resumed");
surface_fn.destroy_surface(surface, None);
}
_ => {}
})
});
Ok(())
}
}
Loading

0 comments on commit 9d225c5

Please sign in to comment.