summary refs log tree commit diff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs166
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) => {