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.rs74
1 files changed, 62 insertions, 12 deletions
diff --git a/src/main.rs b/src/main.rs
index 5dea456..9beb151 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,8 @@
 #![deny(unsafe_code)]
 use crate::error::*;
-use crate::graphics_permanent::PermanentGraphicsState;
+use crate::graphics_permanent::{
+  PermanentGraphicsState, GraphicsStateForReinit
+};
 use crate::graphics_window_dressing::{
   WindowDressing, N_SIMULTANEOUS_FRAMES
 };
@@ -20,7 +22,9 @@ mod graphics_window_dressing;
 
 struct Surreality {
   permanent: RefCell<Option<PermanentGraphicsState>>,
+  for_reinit: RefCell<Option<GraphicsStateForReinit>>,
   window_dressing: RefCell<Option<WindowDressing>>,
+  is_reinit_queued: bool,
   frame_index: usize,
 }
 
@@ -28,28 +32,56 @@ impl Surreality {
   fn new() -> Self {
     Surreality {
       permanent: RefCell::new(None),
+      for_reinit: RefCell::new(None),
       window_dressing: RefCell::new(None),
+      is_reinit_queued: false,
       frame_index: 0,
     }
   }
 
   #[allow(unsafe_code)]
   fn init(&mut self, event_loop: &ActiveEventLoop) -> Result<()> {
-    let (permanent, physical_device, indices, enable_swapchain)
-            = PermanentGraphicsState::new(event_loop)?;
+    let (permanent, for_reinit, enable_swapchain)
+        = PermanentGraphicsState::new(event_loop)?;
 
     if enable_swapchain.0 {
       *self.window_dressing.get_mut()
-          = Some(WindowDressing::new(&permanent, physical_device, indices)?);
+          = Some(WindowDressing::new(&permanent, &for_reinit)?);
     }
 
     *self.permanent.get_mut() = Some(permanent);
+    *self.for_reinit.get_mut() = Some(for_reinit);
+
+    Ok(())
+  }
+
+  fn reinit(&mut self) -> Result<()> {
+    if let Some(permanent) = self.permanent.borrow().as_ref()
+       && let Some(for_reinit) = self.for_reinit.borrow().as_ref()
+       && let Some(window_dressing)
+              = self.window_dressing.borrow_mut().as_mut()
+    {
+      window_dressing.reinit(permanent, for_reinit)?;
+    }
+
+    Ok(())
+  }
+
+
+  fn do_frame(&mut self, window_id: WindowId) -> Result<()> {
+    if self.render(window_id)? || self.is_reinit_queued {
+      self.is_reinit_queued = false;
+
+      self.reinit()?;
+    }
 
     Ok(())
   }
 
+  //   This returns true if, and only if, the window dressing should be
+  // reinitialized.
   #[allow(unsafe_code)]
-  fn render(&mut self, window_id: WindowId) -> Result<()> {
+  fn render(&mut self, window_id: WindowId) -> Result<bool> {
     if let Some(permanent) = self.permanent.borrow().as_ref()
        && let Some(window_dressing)
               = self.window_dressing.borrow_mut().as_mut()
@@ -66,11 +98,15 @@ impl Surreality {
 
       unsafe { device.wait_for_fences(&[*frame_fence], true, u64::MAX) }?;
 
-      let image_index = unsafe {
+      let image_index = match unsafe {
         device.acquire_next_image_khr(window_dressing.swapchain.swapchain,
                                       u64::MAX, *image_available_semaphore,
                                       vk::Fence::null())
-      }?.0 as usize;
+      } {
+        Ok((image_index, _)) => image_index as usize,
+        Err(vk::ErrorCode::OUT_OF_DATE_KHR) => return Ok(true),
+        Err(e) => return Err(Error::from(e)),
+      };
 
       let image_fence = &concurrency.image_fences[image_index];
       if !image_fence.is_null() {
@@ -103,14 +139,19 @@ impl Surreality {
                              .swapchains(&swapchains)
                              .image_indices(&image_indices);
 
-      unsafe {
+      match unsafe {
         device.queue_present_khr(permanent.presentation_queue, &present_info)
-      }?;
+      } {
+        Ok(vk::SuccessCode::SUBOPTIMAL_KHR) => return Ok(true),
+        Err(vk::ErrorCode::OUT_OF_DATE_KHR) => return Ok(true),
+        Err(e) => return Err(Error::from(e)),
+        Ok(_) => (),
+      }
 
       self.frame_index = (frame_index + 1) % N_SIMULTANEOUS_FRAMES;
     }
 
-    Ok(())
+    Ok(false)
   }
 }
 
@@ -121,7 +162,7 @@ impl Drop for Surreality {
       unsafe { permanent.device.device_wait_idle() }.unwrap();
 
       if let Some(window_dressing) = self.window_dressing.replace(None) {
-        window_dressing.destroy(&permanent);
+        window_dressing.destroy(&permanent.device);
       }
 
       permanent.destroy();
@@ -145,14 +186,23 @@ impl ApplicationHandler for Surreality {
     match event {
       WindowEvent::RedrawRequested => {
         if !event_loop.exiting() {
-          if let Err(e) = self.render(window_id) {
+          if let Err(e) = self.do_frame(window_id) {
             eprintln!("Error: {}", e);
           }
         }
       }
+
       WindowEvent::CloseRequested => {
         event_loop.exit();
       }
+
+      WindowEvent::Resized(_) => {
+        self.is_reinit_queued = true;
+        if let Err(e) = self.do_frame(window_id) {
+          eprintln!("Error: {}", e);
+        }
+      }
+
       _ => { }
     }
   }