summary refs log tree commit diff
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-07-09 14:12:08 -0700
committerIrene Knapp <ireneista@irenes.space>2026-07-09 14:12:08 -0700
commitfae3cf53db4ecd73f59dcd198c24a964407f92d5 (patch)
tree0a380be6537512b077e4a40a1bc8ace755281690
parentce60c460eb5d9cf43f2b980635b651f310b6cc90 (diff)
move all the permanent graphics state init into the impl
Force-Push: yes
Change-Id: I09cbc3c2e1e20beba0cf64d346222e3dc2d680ea
-rw-r--r--src/main.rs275
1 files changed, 144 insertions, 131 deletions
diff --git a/src/main.rs b/src/main.rs
index 5411bc9..8254424 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -206,6 +206,141 @@ impl Surreality {
 
   #[allow(unsafe_code)]
   fn init(&mut self, event_loop: &ActiveEventLoop) -> Result<()> {
+    let (permanent, physical_device, indices, enable_swapchain)
+            = PermanentGraphicsState::new(event_loop)?;
+
+    if enable_swapchain.0 {
+      *self.window_dressing.get_mut()
+          = Some(WindowDressing::new(&permanent, physical_device, indices)?);
+    }
+
+    *self.permanent.get_mut() = Some(permanent);
+
+    Ok(())
+  }
+
+  #[allow(unsafe_code)]
+  fn load_spirv_shader_module(device: &Device, binary: &[u8])
+      -> Result<vk::ShaderModule>
+  {
+    let bytecode = Bytecode::new(binary)?;
+
+    let module_info = vk::ShaderModuleCreateInfo::builder()
+                          .code(bytecode.code())
+                          .code_size(bytecode.code_size());
+
+    let module = unsafe {
+      device.create_shader_module(&module_info, None)
+    }?;
+
+    Ok(module)
+  }
+
+  #[allow(unsafe_code)]
+  fn render(&mut self, window_id: WindowId) -> Result<()> {
+    if let Some(permanent) = self.permanent.borrow().as_ref()
+       && let Some(window_dressing)
+              = self.window_dressing.borrow_mut().as_mut()
+       && window_id == permanent.window.id()
+    {
+      let device = &permanent.device;
+      let frame_index = self.frame_index;
+      let concurrency = &mut window_dressing.concurrency;
+      let image_available_semaphore
+              = &concurrency.image_available_semaphores[frame_index];
+      let rendering_finished_semaphore
+              = &concurrency.rendering_finished_semaphores[frame_index];
+      let frame_fence = &concurrency.frame_fences[frame_index];
+
+      unsafe { device.wait_for_fences(&[*frame_fence], true, u64::MAX) }?;
+
+      let image_index = unsafe {
+        device.acquire_next_image_khr(window_dressing.swapchain.swapchain,
+                                      u64::MAX, *image_available_semaphore,
+                                      vk::Fence::null())
+      }?.0 as usize;
+
+      let image_fence = &concurrency.image_fences[image_index];
+      if !image_fence.is_null() {
+        unsafe { device.wait_for_fences(&[*image_fence], true, u64::MAX) }?;
+      }
+
+      concurrency.image_fences[image_index] = *frame_fence;
+
+      let first_semaphores = [*image_available_semaphore];
+      let second_semaphores = [*rendering_finished_semaphore];
+
+      let wait_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
+      let command_buffers = [window_dressing.command_buffers[image_index]];
+      let submit_info = vk::SubmitInfo::builder()
+                            .wait_semaphores(&first_semaphores)
+                            .wait_dst_stage_mask(&wait_stages)
+                            .command_buffers(&command_buffers)
+                            .signal_semaphores(&second_semaphores);
+      unsafe { device.reset_fences(&[*frame_fence]) }?;
+      unsafe {
+        device.queue_submit(permanent.graphics_queue,
+                            &[submit_info],
+                            *frame_fence)
+      }?;
+
+      let swapchains = [window_dressing.swapchain.swapchain];
+      let image_indices = [image_index as u32];
+      let present_info = vk::PresentInfoKHR::builder()
+                             .wait_semaphores(&second_semaphores)
+                             .swapchains(&swapchains)
+                             .image_indices(&image_indices);
+
+      unsafe {
+        device.queue_present_khr(permanent.presentation_queue, &present_info)
+      }?;
+
+      self.frame_index = (frame_index + 1) % N_SIMULTANEOUS_FRAMES;
+    }
+
+    Ok(())
+  }
+}
+
+impl Drop for Surreality {
+  #[allow(unsafe_code)]
+  fn drop(&mut self) {
+    if let Some(permanent) = self.permanent.replace(None) {
+      unsafe { permanent.device.device_wait_idle() }.unwrap();
+
+      if let Some(window_dressing) = self.window_dressing.replace(None) {
+        window_dressing.destroy(&permanent);
+      }
+
+      let device = permanent.device;
+      let instance = permanent.instance;
+
+      unsafe { device.destroy_device(None) };
+
+      unsafe { instance.destroy_surface_khr(permanent.surface, None) };
+
+      //   Everything but the instance itself should already be destroyed,
+      // before we destroy the debug messager. The special hook to get debug
+      // messages while destroying the instance itself only applies to the
+      // instance and the messager, so if we were to destroy anything we
+      // shouldn't after this point, we'd miss out on diagnostics.
+      if let Some(debug_messager) = permanent.debug_messager {
+        unsafe {
+          instance.destroy_debug_utils_messenger_ext(debug_messager, None);
+        }
+      }
+
+      unsafe { instance.destroy_instance(None) };
+    }
+  }
+}
+
+impl PermanentGraphicsState {
+  #[allow(unsafe_code)]
+  fn new(event_loop: &ActiveEventLoop)
+      -> Result<(Self, vk::PhysicalDevice, QueueFamilyIndices,
+                 EnableSwapchain)>
+  {
     let window = Self::init_window(event_loop)?;
 
     //   There are a few Vulkan features (in the informal sense of
@@ -237,19 +372,10 @@ impl Surreality {
         = Self::init_vulkan_device(&instance, &surface,
                                    enable_validation, enable_portability)?;
 
-    let permanent = PermanentGraphicsState {
+    Ok((PermanentGraphicsState {
       window, entry, instance, debug_messager, surface, device,
       graphics_queue, presentation_queue,
-    };
-
-    if enable_swapchain.0 {
-      *self.window_dressing.get_mut()
-          = Some(WindowDressing::new(&permanent, physical_device, indices)?);
-    }
-
-    *self.permanent.get_mut() = Some(permanent);
-
-    Ok(())
+    }, physical_device, indices, enable_swapchain))
   }
 
   fn init_window(event_loop: &ActiveEventLoop) -> Result<Window> {
@@ -489,8 +615,9 @@ impl Surreality {
       //   We've done this check once already, in scoring, and now here
       // we are discarding its results a second time. We'll do it for the
       // third and last time in swapchain creation.
-      if let Acceptable::Accepted(_) = Self::find_device_swapchain_features(
-                 &instance, &surface, &physical_device)?
+      if let Acceptable::Accepted(_)
+             = PermanentGraphicsState::find_device_swapchain_features(
+                   &instance, &surface, &physical_device)?
       {
         extensions.push(swapchain_extension_name.as_ptr());
 
@@ -679,8 +806,9 @@ impl Surreality {
       //
       //   With that said, however, it only counts if we're able to actually
       // use it on the surface we have. Let's find out...
-      if let Acceptable::Accepted(_) = Self::find_device_swapchain_features(
-                 instance, surface, physical_device)?
+      if let Acceptable::Accepted(_)
+             = PermanentGraphicsState::find_device_swapchain_features(
+                   instance, surface, physical_device)?
       {
         //   We don't count it for enough points to override a device type
         // bracket, but it's good for a lot within the bracket.
@@ -769,121 +897,6 @@ impl Surreality {
       Ok(Acceptable::Accepted((capabilities, formats, presentation_modes)))
     }
   }
-
-  #[allow(unsafe_code)]
-  fn load_spirv_shader_module(device: &Device, binary: &[u8])
-      -> Result<vk::ShaderModule>
-  {
-    let bytecode = Bytecode::new(binary)?;
-
-    let module_info = vk::ShaderModuleCreateInfo::builder()
-                          .code(bytecode.code())
-                          .code_size(bytecode.code_size());
-
-    let module = unsafe {
-      device.create_shader_module(&module_info, None)
-    }?;
-
-    Ok(module)
-  }
-
-  #[allow(unsafe_code)]
-  fn render(&mut self, window_id: WindowId) -> Result<()> {
-    if let Some(permanent) = self.permanent.borrow().as_ref()
-       && let Some(window_dressing)
-              = self.window_dressing.borrow_mut().as_mut()
-       && window_id == permanent.window.id()
-    {
-      let device = &permanent.device;
-      let frame_index = self.frame_index;
-      let concurrency = &mut window_dressing.concurrency;
-      let image_available_semaphore
-              = &concurrency.image_available_semaphores[frame_index];
-      let rendering_finished_semaphore
-              = &concurrency.rendering_finished_semaphores[frame_index];
-      let frame_fence = &concurrency.frame_fences[frame_index];
-
-      unsafe { device.wait_for_fences(&[*frame_fence], true, u64::MAX) }?;
-
-      let image_index = unsafe {
-        device.acquire_next_image_khr(window_dressing.swapchain.swapchain,
-                                      u64::MAX, *image_available_semaphore,
-                                      vk::Fence::null())
-      }?.0 as usize;
-
-      let image_fence = &concurrency.image_fences[image_index];
-      if !image_fence.is_null() {
-        unsafe { device.wait_for_fences(&[*image_fence], true, u64::MAX) }?;
-      }
-
-      concurrency.image_fences[image_index] = *frame_fence;
-
-      let first_semaphores = [*image_available_semaphore];
-      let second_semaphores = [*rendering_finished_semaphore];
-
-      let wait_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
-      let command_buffers = [window_dressing.command_buffers[image_index]];
-      let submit_info = vk::SubmitInfo::builder()
-                            .wait_semaphores(&first_semaphores)
-                            .wait_dst_stage_mask(&wait_stages)
-                            .command_buffers(&command_buffers)
-                            .signal_semaphores(&second_semaphores);
-      unsafe { device.reset_fences(&[*frame_fence]) }?;
-      unsafe {
-        device.queue_submit(permanent.graphics_queue,
-                            &[submit_info],
-                            *frame_fence)
-      }?;
-
-      let swapchains = [window_dressing.swapchain.swapchain];
-      let image_indices = [image_index as u32];
-      let present_info = vk::PresentInfoKHR::builder()
-                             .wait_semaphores(&second_semaphores)
-                             .swapchains(&swapchains)
-                             .image_indices(&image_indices);
-
-      unsafe {
-        device.queue_present_khr(permanent.presentation_queue, &present_info)
-      }?;
-
-      self.frame_index = (frame_index + 1) % N_SIMULTANEOUS_FRAMES;
-    }
-
-    Ok(())
-  }
-}
-
-impl Drop for Surreality {
-  #[allow(unsafe_code)]
-  fn drop(&mut self) {
-    if let Some(permanent) = self.permanent.replace(None) {
-      unsafe { permanent.device.device_wait_idle() }.unwrap();
-
-      if let Some(window_dressing) = self.window_dressing.replace(None) {
-        window_dressing.destroy(&permanent);
-      }
-
-      let device = permanent.device;
-      let instance = permanent.instance;
-
-      unsafe { device.destroy_device(None) };
-
-      unsafe { instance.destroy_surface_khr(permanent.surface, None) };
-
-      //   Everything but the instance itself should already be destroyed,
-      // before we destroy the debug messager. The special hook to get debug
-      // messages while destroying the instance itself only applies to the
-      // instance and the messager, so if we were to destroy anything we
-      // shouldn't after this point, we'd miss out on diagnostics.
-      if let Some(debug_messager) = permanent.debug_messager {
-        unsafe {
-          instance.destroy_debug_utils_messenger_ext(debug_messager, None);
-        }
-      }
-
-      unsafe { instance.destroy_instance(None) };
-    }
-  }
 }
 
 impl WindowDressing {
@@ -967,7 +980,7 @@ impl WindowDressing {
       -> Result<Swapchain>
   {
     let (capabilities, formats, presentation_modes)
-            = Surreality::find_device_swapchain_features(
+            = PermanentGraphicsState::find_device_swapchain_features(
                   instance, surface, physical_device)?.require()?;
 
     let format = Self::pick_surface_format(&formats)?;