diff options
| author | Valentin Popov <valentin@popov.link> | 2026-06-25 12:07:40 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-06-25 12:07:40 +0300 |
| commit | 7c3b3a53f51a87e7d6f28ed26173aa4c8e5b6957 (patch) | |
| tree | d492e95a00bef4a9252946edf7bc52f68e2b3398 | |
| parent | 0b8776b850ad76ca0d08ff52733225044272eb3a (diff) | |
| download | fparkan-7c3b3a53f51a87e7d6f28ed26173aa4c8e5b6957.tar.xz fparkan-7c3b3a53f51a87e7d6f28ed26173aa4c8e5b6957.zip | |
fix(smoke): drop renderer before window teardown
| -rw-r--r-- | apps/fparkan-vulkan-smoke/src/main.rs | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/apps/fparkan-vulkan-smoke/src/main.rs b/apps/fparkan-vulkan-smoke/src/main.rs index 6339352..8e12ac5 100644 --- a/apps/fparkan-vulkan-smoke/src/main.rs +++ b/apps/fparkan-vulkan-smoke/src/main.rs @@ -185,6 +185,14 @@ struct SmokeApp { started_at: Instant, } +fn drop_renderer_before_window<Renderer, WindowLike>( + renderer: &mut Option<Renderer>, + window: &mut Option<WindowLike>, +) { + drop(renderer.take()); + drop(window.take()); +} + impl SmokeApp { fn new( options: SmokeOptions, @@ -408,6 +416,14 @@ impl SmokeApp { } } +impl Drop for SmokeApp { + fn drop(&mut self) { + // Keep the native window alive until the Vulkan renderer finishes + // destroying swapchain and surface state that still references it. + drop_renderer_before_window(&mut self.renderer, &mut self.window); + } +} + fn render_timeout_failure_report( options: &SmokeOptions, failure_reason: &str, @@ -859,6 +875,32 @@ fn parse_bool_env(value: &str) -> Option<bool> { #[cfg(test)] mod tests { use super::*; + use std::cell::RefCell; + use std::rc::Rc; + + #[derive(Clone, Copy, Debug, Eq, PartialEq)] + enum DropStep { + Renderer, + Window, + } + + struct DropTracker { + step: DropStep, + log: Rc<RefCell<Vec<DropStep>>>, + } + + impl Drop for DropTracker { + fn drop(&mut self) { + self.log.borrow_mut().push(self.step); + } + } + + fn tracker(step: DropStep, log: &Rc<RefCell<Vec<DropStep>>>) -> DropTracker { + DropTracker { + step, + log: Rc::clone(log), + } + } #[test] fn parses_required_args() { @@ -1058,4 +1100,20 @@ mod tests { std::fs::remove_file(out).expect("cleanup report"); std::fs::remove_dir(root).expect("cleanup dir"); } + + #[test] + fn renderer_is_dropped_before_window() { + let log = Rc::new(RefCell::new(Vec::new())); + let mut renderer = Some(tracker(DropStep::Renderer, &log)); + let mut window = Some(tracker(DropStep::Window, &log)); + + drop_renderer_before_window(&mut renderer, &mut window); + + assert!(renderer.is_none()); + assert!(window.is_none()); + assert_eq!( + Rc::into_inner(log).expect("trackers released").into_inner(), + vec![DropStep::Renderer, DropStep::Window] + ); + } } |
