From fae3cf53db4ecd73f59dcd198c24a964407f92d5 Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Thu, 9 Jul 2026 14:12:08 -0700 Subject: move all the permanent graphics state init into the impl Force-Push: yes Change-Id: I09cbc3c2e1e20beba0cf64d346222e3dc2d680ea --- src/main.rs | 275 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 144 insertions(+), 131 deletions(-) (limited to 'src/main.rs') 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 + { + 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 { @@ -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 - { - 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 { 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)?; -- cgit 1.4.1