#![deny(unsafe_code)] use std::cell::OnceCell; use vulkanalia::{ Entry, Instance }; use vulkanalia::loader::{ LibloadingLoader, LIBRARY }; use vulkanalia::vk::{ self, HasBuilder, ApplicationInfo, InstanceCreateInfo, DeviceV1_4, EntryV1_4, InstanceV1_4 }; use winit::dpi::LogicalSize; use winit::application::ApplicationHandler; use winit::event::WindowEvent; use winit::event_loop::{ ActiveEventLoop, EventLoop }; use winit::window::{ Window, WindowAttributes, WindowId }; #[derive(Debug)] struct Error { message: String, } type Result = std::result::Result; impl std::fmt::Display for Error { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { fmt.write_str(&self.message) } } impl From for Error { fn from(e: winit::error::EventLoopError) -> Self { match e { winit::error::EventLoopError::NotSupported(e) => Self::from(e), winit::error::EventLoopError::Os(e) => Self::from(e), winit::error::EventLoopError::RecreationAttempt => Error { message: "There may only ever be a single winit event loop.".to_string() }, winit::error::EventLoopError::ExitFailure(code) => Error { message: format!("Clean unhappy exit with code {} via winit event loop", code) } } } } impl From for Error { fn from(e: winit::error::NotSupportedError) -> Self { Error { message: format!("The winit backend does not support an operation: {}", e.to_string()) } } } impl From for Error { fn from(e: winit::error::OsError) -> Self { Error { message: format!("The OS told winit about an error: {}", e.to_string()) } } } impl From for Error { fn from(e: libloading::Error) -> Self { Error { message: format!("The dynamic object loader reported an error: {}", e.to_string()) } } } impl From> for Error { fn from(e: Box) -> Self { Error { message: format!("The Vulkan loader reported an error: {}", e.to_string()) } } } impl From for Error { fn from(e: vulkanalia::vk::ErrorCode) -> Self { Error { message: format!("Vulkan gave an error code: {}", e.to_string()) } } } fn ignore_errors(mut body: impl FnMut() -> Result<()>) -> () { if let Err(e) = body() { eprintln!("Error: {}", e); } } struct Surreality { entry: OnceCell, instance: OnceCell, window: OnceCell, } impl Surreality { fn new() -> Self { Surreality { entry: OnceCell::new(), instance: OnceCell::new(), window: OnceCell::new(), } } fn init_if_needed(&mut self, event_loop: &ActiveEventLoop) -> Result<()> { if self.window.get().is_none() { let window_attributes = WindowAttributes::default() .with_title("Love, Curiosity, Justice") .with_inner_size(LogicalSize::new(1024, 768)); let window: Window = event_loop.create_window(window_attributes)?; let _ = self.window.set(window); #[allow(unsafe_code)] let loader = unsafe { LibloadingLoader::new(LIBRARY)? }; #[allow(unsafe_code)] let entry = unsafe { Entry::new(loader)? }; let application_info = ApplicationInfo::builder() .application_name(b"Surreality\0") .application_version(vk::make_version(1, 0, 0)) .engine_name(b"Surreality\0") .engine_version(vk::make_version(1, 0, 0)) .api_version(vk::make_version(1, 0, 0)); let extensions = vulkanalia::window::get_required_instance_extensions( self.window.get().unwrap()) .iter().map(|item| item.as_ptr()).collect::>(); let instance_create_info = InstanceCreateInfo::builder() .application_info(&application_info) .enabled_extension_names(&extensions); #[allow(unsafe_code)] let instance = unsafe { entry.create_instance(&instance_create_info, None)? }; } Ok(()) } fn render(&mut self, window_id: WindowId) -> Result<()> { if let Some(window) = self.window.get() && window_id == window.id() { println!("render the window"); } else { println!("render something unknown"); } Ok(()) } } impl ApplicationHandler for Surreality { fn resumed(&mut self, event_loop: &ActiveEventLoop) { ignore_errors(move || { println!("resumed"); self.init_if_needed(event_loop)?; Ok(()) }); } fn window_event(&mut self, event_loop: &ActiveEventLoop, window_id: WindowId, event: WindowEvent) { println!("window event {:?}", event); match event { WindowEvent::RedrawRequested => { if !event_loop.exiting() { if let Err(e) = self.render(window_id) { eprintln!("Error: {}", e); } } } WindowEvent::CloseRequested => { event_loop.exit(); } _ => { } } } } fn main() -> std::process::ExitCode { let body: fn() -> Result<()> = || { let event_loop = EventLoop::new()?; let mut surreality = Surreality::new(); event_loop.run_app(&mut surreality)?; Ok(()) }; match body() { Ok(()) => std::process::ExitCode::SUCCESS, Err(e) => { eprintln!("Error: {}", e); std::process::ExitCode::from(1) } } }