fix(vulkan-smoke): make teardown order explicit

This commit is contained in:
2026-06-25 04:47:20 +04:00
parent 5950c62cec
commit adc6c6149c
+17 -8
View File
@@ -1621,36 +1621,39 @@ impl VulkanSmokeRenderer {
if let Some(resources) = self.swapchain_resources.take() { if let Some(resources) = self.swapchain_resources.take() {
destroy_swapchain_resources(device, self.command_pool, resources); destroy_swapchain_resources(device, self.command_pool, resources);
} }
} self.images_in_flight.clear();
self.current_frame = 0;
} }
impl Drop for VulkanSmokeRenderer { fn teardown(&mut self) {
fn drop(&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(); self.destroy_swapchain_resources();
if let Some(device) = self.device.as_ref() { if let Some(device) = self.device.as_ref() {
if let Some(buffer) = self.index_buffer.take() { 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 { unsafe {
device.device().destroy_buffer(buffer.buffer, None); device.device().destroy_buffer(buffer.buffer, None);
device.device().free_memory(buffer.memory, None); device.device().free_memory(buffer.memory, None);
} }
} }
if let Some(buffer) = self.vertex_buffer.take() { 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 { unsafe {
device.device().destroy_buffer(buffer.buffer, None); device.device().destroy_buffer(buffer.buffer, None);
device.device().free_memory(buffer.memory, 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 { unsafe {
device device
.device() .device()
.destroy_command_pool(self.command_pool, None); .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.swapchain.take();
self.device.take(); self.device.take();
self.surface.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( fn create_validation_messenger(
instance: &VulkanInstanceProbe, instance: &VulkanInstanceProbe,
) -> Result<VulkanValidationMessenger, VulkanSmokeRendererError> { ) -> Result<VulkanValidationMessenger, VulkanSmokeRendererError> {