summaryrefslogtreecommitdiff
path: root/src/renderer
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2025-06-21 14:39:40 +0800
committerJSDurand <mmemmew@gmail.com>2025-06-21 14:39:40 +0800
commitf01b364072d4243fcc7dbd0f912f5e28280c77c5 (patch)
treee0334e4e2a57dc755a43312785a71fbf84f2d722 /src/renderer
parent9b36d712e25fb1d209df848281b9913b61a6ec45 (diff)
Support redraw and resize now.
Diffstat (limited to 'src/renderer')
-rw-r--r--src/renderer/vulkan.rs189
1 files changed, 187 insertions, 2 deletions
diff --git a/src/renderer/vulkan.rs b/src/renderer/vulkan.rs
index a1451a3..10a9692 100644
--- a/src/renderer/vulkan.rs
+++ b/src/renderer/vulkan.rs
@@ -69,6 +69,184 @@ impl VulkanRenderer {
resumed,
}
}
+
+ unsafe fn recreate_swapchain(&mut self, window: &Window) -> Result<(), MainError> {
+ unsafe {
+ if let Some(device) = &self.device {
+ device.device_wait_idle()?;
+ }
+
+ self.destroy_swapchain();
+
+ if let (Some(device), Some(instance)) = (&self.device, &self.instance) {
+ create_swapchain(window, instance, device, &mut self.data)?;
+
+ create_swapchain_image_views(device, &mut self.data)?;
+
+ create_render_pass(instance, device, &mut self.data)?;
+
+ create_pipeline(device, &mut self.data)?;
+
+ create_framebuffers(device, &mut self.data)?;
+
+ create_command_buffers(device, &mut self.data)?;
+ }
+
+ self.data
+ .images_in_flight
+ .resize(self.data.swapchain_images.len(), vk::Fence::null());
+
+ Ok(())
+ }
+ }
+
+ unsafe fn destroy_swapchain(&mut self) {
+ unsafe {
+ if let Some(device) = &self.device {
+ for buffer in self.data.framebuffers.iter().copied() {
+ device.destroy_framebuffer(buffer, None);
+ }
+
+ device.free_command_buffers(self.data.command_pool, &self.data.command_buffers);
+
+ device.destroy_pipeline(self.data.pipeline, None);
+
+ device.destroy_pipeline_layout(self.data.pipeline_layout, None);
+
+ device.destroy_render_pass(self.data.render_pass, None);
+
+ for view in self.data.swapchain_image_views.iter() {
+ device.destroy_image_view(*view, None);
+ }
+
+ device.destroy_swapchain_khr(self.data.swapchain, None);
+ }
+ }
+ }
+
+ unsafe fn render(&mut self, window: &Window) -> Result<(), MainError> {
+ unsafe {
+ if let Some(device) = &self.device {
+ device.wait_for_fences(
+ &[self.data.in_flight_fences[self.frame]],
+ true,
+ u64::MAX,
+ )?;
+
+ let acquire_image_result = device.acquire_next_image_khr(
+ self.data.swapchain,
+ u64::MAX,
+ self.data.image_available_sp[self.frame],
+ vk::Fence::null(),
+ );
+
+ let image_index = match acquire_image_result {
+ Ok((image_index, _)) => image_index,
+ Err(vk::ErrorCode::OUT_OF_DATE_KHR) => return self.recreate_swapchain(window),
+ Err(code) => return Err(code.into()),
+ };
+
+ if !self.data.images_in_flight[image_index as usize].is_null() {
+ device.wait_for_fences(
+ &[self.data.images_in_flight[image_index as usize]],
+ true,
+ u64::MAX,
+ )?;
+ }
+
+ self.data.images_in_flight[image_index as usize] =
+ self.data.in_flight_fences[self.frame];
+
+ let waiting_sps = [self.data.image_available_sp[self.frame]];
+ let waiting_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
+
+ let command_buffer = [self.data.command_buffers[image_index as usize]];
+
+ let render_sps = [self.data.render_finished_sp[self.frame]];
+
+ let submit_info = vk::SubmitInfo::builder()
+ .wait_semaphores(&waiting_sps)
+ .wait_dst_stage_mask(&waiting_stages)
+ .command_buffers(&command_buffer)
+ .signal_semaphores(&render_sps);
+
+ device.reset_fences(&[self.data.in_flight_fences[self.frame]])?;
+
+ device.queue_submit(
+ self.data.gqueue,
+ &[submit_info],
+ self.data.in_flight_fences[self.frame],
+ )?;
+
+ let swapchains = [self.data.swapchain];
+
+ let image_indices = [image_index];
+
+ let presentation_info = vk::PresentInfoKHR::builder()
+ .wait_semaphores(&render_sps)
+ .swapchains(&swapchains)
+ .image_indices(&image_indices);
+
+ let present_result = device.queue_present_khr(self.data.pqueue, &presentation_info);
+
+ if self.resized
+ || matches!(
+ present_result,
+ Ok(vk::SuccessCode::SUBOPTIMAL_KHR) | Err(vk::ErrorCode::OUT_OF_DATE_KHR)
+ )
+ {
+ self.resized = false;
+
+ self.recreate_swapchain(window)?;
+ } else if let Err(e) = present_result {
+ return Err(e.into());
+ }
+
+ self.frame = (self.frame + 1).rem_euclid(MAX_FRAMES_IN_FLIGHT);
+ }
+
+ Ok(())
+ }
+ }
+
+ unsafe fn destroy(&mut self) {
+ unsafe {
+ self.destroy_swapchain();
+
+ if let (Some(device), Some(instance)) = (&self.device, &self.instance) {
+ for f in self.data.in_flight_fences.iter() {
+ device.destroy_fence(*f, None);
+ }
+
+ for s in self.data.image_available_sp.iter() {
+ device.destroy_semaphore(*s, None);
+ }
+
+ for s in self.data.render_finished_sp.iter() {
+ device.destroy_semaphore(*s, None);
+ }
+
+ device.destroy_command_pool(self.data.command_pool, None);
+
+ device.destroy_device(None);
+
+ instance.destroy_surface_khr(self.data.surface, None);
+
+ if VALIDATION_ENABLED {
+ instance.destroy_debug_utils_messenger_ext(self.data.messenger, None);
+ }
+
+ instance.destroy_instance(None);
+ }
+ }
+ }
+
+ fn handle_resize(&mut self, new_size: LogicalSize<u32>) {
+ // destroy old swapchain
+
+ // recreate swapchain and framebuffers
+ println!("Window resized to {:?}", new_size);
+ }
}
impl ApplicationHandler for VulkanRenderer {
@@ -136,7 +314,6 @@ impl ApplicationHandler for VulkanRenderer {
_window_id: WindowId,
event: WindowEvent,
) {
- dbg!(format!("{event:?}"));
let window = match self.window.as_ref() {
Some(window) => window,
_ => return,
@@ -145,7 +322,15 @@ impl ApplicationHandler for VulkanRenderer {
match event {
WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::RedrawRequested => {
- // to do
+ // self.clear();
+ // self.draw_text(&self.test_span); // store it in self maybe?
+ // self.present();
+
+ window.request_redraw();
+ }
+ WindowEvent::Resized(new_size) => {
+ // self.handle_resize(new_size);
+ dbg!(new_size);
window.request_redraw();
}
_ => (),