diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 166 |
1 files changed, 145 insertions, 21 deletions
diff --git a/src/main.rs b/src/main.rs index 2ebdd28..c7e12a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,10 @@ -#![forbid(unsafe_code)] -// use vulkanalia::vk::{ DeviceV1_4, EntryV1_4, InstanceV1_4 }; +#![deny(unsafe_code)] +use std::cell::OnceCell; +use vulkanalia::{ Entry, Instance, Version }; +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; @@ -56,20 +61,141 @@ impl From<winit::error::OsError> for Error { } } +impl From<libloading::Error> for Error { + fn from(e: libloading::Error) -> Self { + Error { + message: format!("The dynamic object loader reported an error: {}", + e.to_string()) + } + } +} + +impl From<Box<dyn vulkanalia::loader::LoaderError>> for Error { + fn from(e: Box<dyn vulkanalia::loader::LoaderError>) -> Self { + Error { + message: format!("The Vulkan loader reported an error: {}", + e.to_string()) + } + } +} + +impl From<vulkanalia::vk::ErrorCode> 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); + } +} + + +const VULKAN_FIRST_PORTABILITY_VERSION: Version = Version::new(1, 3, 216); + struct Surreality { - window: Window + window: OnceCell<Window>, + entry: OnceCell<Entry>, + instance: OnceCell<Instance>, } impl Surreality { - fn new(window: Window) -> Result<Self> { - Ok(Surreality { - window - }) + fn new() -> Self { + Surreality { + window: OnceCell::new(), + entry: OnceCell::new(), + instance: OnceCell::new(), + } + } + + fn init(&mut self, event_loop: &ActiveEventLoop) -> Result<()> { + if self.window.get().is_none() { + self.init_window(event_loop)?; + } + + if self.entry.get().is_none() { + self.init_entry()?; + } + + if self.instance.get().is_none() { + self.init_instance()?; + } + + Ok(()) + } + + fn init_window(&mut self, event_loop: &ActiveEventLoop) -> Result<()> { + 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); + + Ok(()) + } + + fn init_entry(&mut self) -> Result<()> { + #[allow(unsafe_code)] + let loader = unsafe { LibloadingLoader::new(LIBRARY)? }; + #[allow(unsafe_code)] + let entry = unsafe { Entry::new(loader)? }; + + let _ = self.entry.set(entry); + + Ok(()) + } + + fn init_instance(&mut self) -> Result<()> { + let entry = self.entry.get().unwrap(); + + 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 mut extensions = vulkanalia::window::get_required_instance_extensions( + self.window.get().unwrap()) + .iter().map(|item| item.as_ptr()).collect::<Vec<_>>(); + + let mut flags = vk::InstanceCreateFlags::empty(); + if entry.version()? >= VULKAN_FIRST_PORTABILITY_VERSION { + if cfg!(target_os = "macos") { + // Vulkan on the Mac is not fully conforming. + extensions.push( + vk::KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_EXTENSION.name.as_ptr()); + extensions.push( + vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name.as_ptr()); + flags.insert(vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR); + } + } + + let instance_create_info = InstanceCreateInfo::builder() + .application_info(&application_info) + .enabled_extension_names(&extensions) + .flags(flags); + + #[allow(unsafe_code)] + let instance = unsafe { + entry.create_instance(&instance_create_info, None)? + }; + + let _ = self.instance.set(instance); + + Ok(()) } fn render(&mut self, window_id: WindowId) -> Result<()> { - if window_id == self.window.id() { + if let Some(window) = self.window.get() + && window_id == window.id() + { println!("render the window"); } else { println!("render something unknown"); @@ -81,7 +207,12 @@ impl Surreality { impl ApplicationHandler for Surreality { fn resumed(&mut self, event_loop: &ActiveEventLoop) { - println!("resumed"); + ignore_errors(move || { + println!("resumed"); + self.init(event_loop)?; + + Ok(()) + }); } fn window_event(&mut self, event_loop: &ActiveEventLoop, @@ -92,7 +223,9 @@ impl ApplicationHandler for Surreality { match event { WindowEvent::RedrawRequested => { if !event_loop.exiting() { - self.render(window_id).unwrap(); // TODO + if let Err(e) = self.render(window_id) { + eprintln!("Error: {}", e); + } } } WindowEvent::CloseRequested => { @@ -105,22 +238,13 @@ impl ApplicationHandler for Surreality { fn main() -> std::process::ExitCode { - let body: fn() -> Result<()> = || { + let body: fn() -> Result<()> = || { let event_loop = EventLoop::new()?; - - let window_attributes = WindowAttributes::default() - .with_title("Love, Curiosity, Justice") - .with_inner_size(LogicalSize::new(1024, 768)); - let window = event_loop.create_window(window_attributes)?; - - let mut surreality = Surreality::new(window)?; - + let mut surreality = Surreality::new(); event_loop.run_app(&mut surreality)?; - Ok(()) }; - println!("Hello!"); match body() { Ok(()) => std::process::ExitCode::SUCCESS, Err(e) => { |