Skip to content

Instantly share code, notes, and snippets.

@kulicuu
Last active October 12, 2021 15:16
Show Gist options
  • Save kulicuu/02585b191b91550f88a65720ed244ade to your computer and use it in GitHub Desktop.
Save kulicuu/02585b191b91550f88a65720ed244ade to your computer and use it in GitHub Desktop.
ash-window example updated to newest version of winit
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