Last active
October 12, 2021 15:16
-
-
Save kulicuu/02585b191b91550f88a65720ed244ade to your computer and use it in GitHub Desktop.
ash-window example updated to newest version of winit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use winit::{ | |
event::{Event, KeyboardInput, WindowEvent}, | |
event_loop::{ControlFlow, EventLoop}, | |
window::WindowBuilder, | |
window::Window, | |
}; | |
use simple_logger::SimpleLogger; | |
use ash::util::*; | |
use ash::{prelude::*, vk, Entry, Instance, Device}; | |
use ash::extensions::{ | |
ext::DebugUtils, | |
khr::{Surface, Swapchain}, | |
}; | |
use ash::extensions::khr; | |
use std::borrow::Cow; | |
use std::cell::RefCell; | |
use std::default::Default; | |
use std::ffi::{CStr, CString}; | |
use std::ops::Drop; | |
use std::{thread, time}; | |
use cgmath::{Deg, Matrix4, Point3, Vector3}; | |
use std::io::Cursor; | |
use std::mem; | |
use std::mem::align_of; | |
use std::ptr; | |
use std::path::Path; | |
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; | |
const WAIT_TIME: time::Duration = time::Duration::from_millis(100); | |
const POLL_SLEEP_TIME: time::Duration = time::Duration::from_millis(100); | |
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | |
enum Mode { | |
Wait, | |
WaitUntil, | |
Poll, | |
} | |
fn vulkan_setup(window: &Window, event_loop: &EventLoop<()>) { | |
// At the moment, just instantiating various pieces, will assemble when they are all independently verified. | |
unsafe { | |
let entry = ash::Entry::new().unwrap(); | |
let surface_extensions = enumerate_required_extensions(window).unwrap(); | |
let instance_extensions = surface_extensions | |
.iter() | |
.map(|ext| ext.as_ptr()) | |
.collect::<Vec<_>>(); | |
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) | |
.enabled_extension_names(&instance_extensions); | |
let instance = entry.create_instance(&instance_desc, None).unwrap(); | |
// Create a surface from winit window. | |
let surface = create_surface(&entry, &instance, window, None).unwrap(); | |
let surface_fn = ash::extensions::khr::Surface::new(&entry, &instance); | |
// println!("surface: {:?}", surface); | |
surface_fn.destroy_surface(surface, None); | |
} | |
} | |
fn main() { | |
println!("ray-oct-12"); | |
let event_loop = winit::event_loop::EventLoop::new(); | |
let window = winit::window::WindowBuilder::new() | |
.build(&event_loop).unwrap(); | |
vulkan_setup(&window, &event_loop); | |
SimpleLogger::new().init().unwrap(); | |
let mut mode = Mode::Wait; | |
let mut request_redraw = false; | |
let mut wait_cancelled = false; | |
let mut close_requested = false; | |
event_loop.run(move |event, _, control_flow| { | |
use winit::event::{ElementState, StartCause, VirtualKeyCode}; | |
println!("{:?}", event); | |
match event { | |
Event::NewEvents(start_cause) => { | |
wait_cancelled = match start_cause { | |
StartCause::WaitCancelled { .. } => mode == Mode::WaitUntil, | |
_ => false, | |
} | |
} | |
Event::WindowEvent { event, .. } => match event { | |
WindowEvent::CloseRequested => { | |
close_requested = true; | |
} | |
WindowEvent::KeyboardInput { | |
input: | |
KeyboardInput { | |
virtual_keycode: Some(virtual_code), | |
state: ElementState::Pressed, | |
.. | |
}, | |
.. | |
} => match virtual_code { | |
VirtualKeyCode::Key1 => { | |
mode = Mode::Wait; | |
println!("\nmode: {:?}\n", mode); | |
} | |
VirtualKeyCode::Key2 => { | |
mode = Mode::WaitUntil; | |
println!("\nmode: {:?}\n", mode); | |
} | |
VirtualKeyCode::Key3 => { | |
mode = Mode::Poll; | |
println!("\nmode: {:?}\n", mode); | |
} | |
VirtualKeyCode::R => { | |
request_redraw = !request_redraw; | |
println!("\nrequest_redraw: {}\n", request_redraw); | |
} | |
VirtualKeyCode::Escape => { | |
close_requested = true; | |
} | |
_ => (), | |
}, | |
_ => (), | |
}, | |
Event::MainEventsCleared => { | |
if request_redraw && !wait_cancelled && !close_requested { | |
window.request_redraw(); | |
} | |
if close_requested { | |
*control_flow = ControlFlow::Exit; | |
} | |
} | |
Event::RedrawRequested(_window_id) => {} | |
Event::RedrawEventsCleared => { | |
*control_flow = match mode { | |
Mode::Wait => ControlFlow::Wait, | |
Mode::WaitUntil => { | |
if wait_cancelled { | |
*control_flow | |
} else { | |
ControlFlow::WaitUntil(time::Instant::now() + WAIT_TIME) | |
} | |
} | |
Mode::Poll => { | |
thread::sleep(POLL_SLEEP_TIME); | |
ControlFlow::Poll | |
} | |
}; | |
} | |
_ => (), | |
} | |
}); | |
} | |
pub unsafe fn create_surface( | |
entry: &Entry, | |
instance: &Instance, | |
window_handle: &dyn HasRawWindowHandle, | |
allocation_callbacks: Option<&vk::AllocationCallbacks>, | |
) -> VkResult<vk::SurfaceKHR> { | |
match window_handle.raw_window_handle() { | |
#[cfg(target_os = "windows")] | |
RawWindowHandle::Windows(handle) => { | |
let surface_desc = vk::Win32SurfaceCreateInfoKHR::builder() | |
.hinstance(handle.hinstance) | |
.hwnd(handle.hwnd); | |
let surface_fn = khr::Win32Surface::new(entry, instance); | |
surface_fn.create_win32_surface(&surface_desc, allocation_callbacks) | |
} | |
#[cfg(any( | |
target_os = "linux", | |
target_os = "dragonfly", | |
target_os = "freebsd", | |
target_os = "netbsd", | |
target_os = "openbsd" | |
))] | |
RawWindowHandle::Wayland(handle) => { | |
let surface_desc = vk::WaylandSurfaceCreateInfoKHR::builder() | |
.display(handle.display) | |
.surface(handle.surface); | |
let surface_fn = khr::WaylandSurface::new(entry, instance); | |
surface_fn.create_wayland_surface(&surface_desc, allocation_callbacks) | |
} | |
#[cfg(any( | |
target_os = "linux", | |
target_os = "dragonfly", | |
target_os = "freebsd", | |
target_os = "netbsd", | |
target_os = "openbsd" | |
))] | |
RawWindowHandle::Xlib(handle) => { | |
let surface_desc = vk::XlibSurfaceCreateInfoKHR::builder() | |
.dpy(handle.display as *mut _) | |
.window(handle.window); | |
let surface_fn = khr::XlibSurface::new(entry, instance); | |
surface_fn.create_xlib_surface(&surface_desc, allocation_callbacks) | |
} | |
#[cfg(any( | |
target_os = "linux", | |
target_os = "dragonfly", | |
target_os = "freebsd", | |
target_os = "netbsd", | |
target_os = "openbsd" | |
))] | |
RawWindowHandle::Xcb(handle) => { | |
let surface_desc = vk::XcbSurfaceCreateInfoKHR::builder() | |
.connection(handle.connection as *mut _) | |
.window(handle.window); | |
let surface_fn = khr::XcbSurface::new(entry, instance); | |
surface_fn.create_xcb_surface(&surface_desc, allocation_callbacks) | |
} | |
#[cfg(any(target_os = "android"))] | |
RawWindowHandle::Android(handle) => { | |
let surface_desc = | |
vk::AndroidSurfaceCreateInfoKHR::builder().window(handle.a_native_window as _); | |
let surface_fn = khr::AndroidSurface::new(entry, instance); | |
surface_fn.create_android_surface(&surface_desc, allocation_callbacks) | |
} | |
#[cfg(any(target_os = "macos"))] | |
RawWindowHandle::MacOS(handle) => { | |
use raw_window_metal::{macos, Layer}; | |
let layer = match macos::metal_layer_from_handle(handle) { | |
Layer::Existing(layer) | Layer::Allocated(layer) => layer as *mut _, | |
Layer::None => return Err(vk::Result::ERROR_INITIALIZATION_FAILED), | |
}; | |
let surface_desc = vk::MetalSurfaceCreateInfoEXT::builder().layer(&*layer); | |
let surface_fn = ext::MetalSurface::new(entry, instance); | |
surface_fn.create_metal_surface(&surface_desc, allocation_callbacks) | |
} | |
#[cfg(any(target_os = "ios"))] | |
RawWindowHandle::IOS(handle) => { | |
use raw_window_metal::{ios, Layer}; | |
let layer = match ios::metal_layer_from_handle(handle) { | |
Layer::Existing(layer) | Layer::Allocated(layer) => layer as *mut _, | |
Layer::None => return Err(vk::Result::ERROR_INITIALIZATION_FAILED), | |
}; | |
let surface_desc = vk::MetalSurfaceCreateInfoEXT::builder().layer(&*layer); | |
let surface_fn = ext::MetalSurface::new(entry, instance); | |
surface_fn.create_metal_surface(&surface_desc, allocation_callbacks) | |
} | |
_ => Err(vk::Result::ERROR_EXTENSION_NOT_PRESENT), // not supported | |
} | |
} | |
pub fn enumerate_required_extensions( | |
window_handle: &dyn HasRawWindowHandle, | |
) -> VkResult<Vec<&'static CStr>> { | |
let extensions = match window_handle.raw_window_handle() { | |
#[cfg(target_os = "windows")] | |
RawWindowHandle::Windows(_) => vec![khr::Surface::name(), khr::Win32Surface::name()], | |
#[cfg(any( | |
target_os = "linux", | |
target_os = "dragonfly", | |
target_os = "freebsd", | |
target_os = "netbsd", | |
target_os = "openbsd" | |
))] | |
RawWindowHandle::Wayland(_) => vec![khr::Surface::name(), khr::WaylandSurface::name()], | |
#[cfg(any( | |
target_os = "linux", | |
target_os = "dragonfly", | |
target_os = "freebsd", | |
target_os = "netbsd", | |
target_os = "openbsd" | |
))] | |
RawWindowHandle::Xlib(_) => vec![khr::Surface::name(), khr::XlibSurface::name()], | |
#[cfg(any( | |
target_os = "linux", | |
target_os = "dragonfly", | |
target_os = "freebsd", | |
target_os = "netbsd", | |
target_os = "openbsd" | |
))] | |
RawWindowHandle::Xcb(_) => vec![khr::Surface::name(), khr::XcbSurface::name()], | |
#[cfg(any(target_os = "android"))] | |
RawWindowHandle::Android(_) => vec![khr::Surface::name(), khr::AndroidSurface::name()], | |
#[cfg(any(target_os = "macos"))] | |
RawWindowHandle::MacOS(_) => vec![khr::Surface::name(), ext::MetalSurface::name()], | |
#[cfg(any(target_os = "ios"))] | |
RawWindowHandle::IOS(_) => vec![khr::Surface::name(), ext::MetalSurface::name()], | |
_ => return Err(vk::Result::ERROR_EXTENSION_NOT_PRESENT), | |
}; | |
Ok(extensions) | |
} | |
/*Cargo.toml | |
[package] | |
name = "ray-oct-12" | |
version = "0.1.0" | |
edition = "2021" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[dependencies] | |
winit = "0.25.0" | |
ash = "0.33.3" | |
raw-window-handle = "0.3.3" | |
serde = "1.0.130" | |
mint = "0.5.6" | |
num = "0.2" | |
cgmath = "0.17.0" | |
image = "0.22" | |
memoffset = "0.5.1" | |
tobj = "0.1.10" | |
simple_logger = "1.13.0" | |
[target.'cfg(target_os = "windows")'.dependencies] | |
winapi = { version = "0.3.9", features = ["windef", "libloaderapi"] } | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment