aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2026-06-25 03:47:20 +0300
committerValentin Popov <valentin@popov.link>2026-06-25 10:45:33 +0300
commitadc6c6149c290e8208837d365ba3df63ba7a5d38 (patch)
tree5e8cc264e5efe7c19b627bf31f0c122c90b3b44b
parent5950c62cec76f86578817b54e45c7bf5d52add67 (diff)
downloadfparkan-adc6c6149c290e8208837d365ba3df63ba7a5d38.tar.xz
fparkan-adc6c6149c290e8208837d365ba3df63ba7a5d38.zip
fix(vulkan-smoke): make teardown order explicit
-rw-r--r--adapters/fparkan-render-vulkan/src/lib.rs25
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> {