diff options
| author | Valentin Popov <valentin@popov.link> | 2026-06-25 03:47:20 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-06-25 10:45:33 +0300 |
| commit | adc6c6149c290e8208837d365ba3df63ba7a5d38 (patch) | |
| tree | 5e8cc264e5efe7c19b627bf31f0c122c90b3b44b | |
| parent | 5950c62cec76f86578817b54e45c7bf5d52add67 (diff) | |
| download | fparkan-adc6c6149c290e8208837d365ba3df63ba7a5d38.tar.xz fparkan-adc6c6149c290e8208837d365ba3df63ba7a5d38.zip | |
fix(vulkan-smoke): make teardown order explicit
| -rw-r--r-- | adapters/fparkan-render-vulkan/src/lib.rs | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/adapters/fparkan-render-vulkan/src/lib.rs b/adapters/fparkan-render-vulkan/src/lib.rs index 26e74e9..f829d4e 100644 --- a/adapters/fparkan-render-vulkan/src/lib.rs +++ b/adapters/fparkan-render-vulkan/src/lib.rs @@ -1621,36 +1621,39 @@ impl VulkanSmokeRenderer { if let Some(resources) = self.swapchain_resources.take() { destroy_swapchain_resources(device, self.command_pool, resources); } + self.images_in_flight.clear(); + self.current_frame = 0; } -} -impl Drop for VulkanSmokeRenderer { - fn drop(&mut self) { + fn teardown(&mut self) { + if let Some(device) = self.device.as_ref() { + // SAFETY: The logical device remains live until teardown finishes and idling prevents in-flight work from touching swapchain, buffers, sync objects or the command pool after destruction starts. + let _ = unsafe { device.device().device_wait_idle() }; + } self.destroy_swapchain_resources(); if let Some(device) = self.device.as_ref() { if let Some(buffer) = self.index_buffer.take() { - // SAFETY: Buffer and memory belong to this device and are destroyed once. + // SAFETY: Buffer and memory belong to this device and are destroyed once after the device has been idled and frame work has been torn down. unsafe { device.device().destroy_buffer(buffer.buffer, None); device.device().free_memory(buffer.memory, None); } } if let Some(buffer) = self.vertex_buffer.take() { - // SAFETY: Buffer and memory belong to this device and are destroyed once. + // SAFETY: Buffer and memory belong to this device and are destroyed once after the device has been idled and frame work has been torn down. unsafe { device.device().destroy_buffer(buffer.buffer, None); device.device().free_memory(buffer.memory, None); } } - // SAFETY: The command pool belongs to this device and is destroyed once after buffers are freed. + // SAFETY: The command pool belongs to this device and is destroyed once after the device is idle and all command buffers allocated from it were freed above. unsafe { device .device() .destroy_command_pool(self.command_pool, None); }; - // SAFETY: The logical device remains live until the renderer completes teardown. - let _ = unsafe { device.device().device_wait_idle() }; } + // Drop child Vulkan owners explicitly before their parents instead of relying on field order. self.swapchain.take(); self.device.take(); self.surface.take(); @@ -1659,6 +1662,12 @@ impl Drop for VulkanSmokeRenderer { } } +impl Drop for VulkanSmokeRenderer { + fn drop(&mut self) { + self.teardown(); + } +} + fn create_validation_messenger( instance: &VulkanInstanceProbe, ) -> Result<VulkanValidationMessenger, VulkanSmokeRendererError> { |
