From f01b364072d4243fcc7dbd0f912f5e28280c77c5 Mon Sep 17 00:00:00 2001 From: JSDurand Date: Sat, 21 Jun 2025 14:39:40 +0800 Subject: Support redraw and resize now. --- src/renderer/vulkan.rs | 189 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file 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) { + // 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(); } _ => (), -- cgit v1.2.3-18-g5258