From 6fa0c3af0c1026e75610a67e2f7bf9d4d49bf549 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 20 Jan 2026 12:18:18 +0100 Subject: [PATCH] :bug: Fix some tiles disappear after fast zoom and pan --- render-wasm/src/main.rs | 1 + render-wasm/src/render.rs | 5 +++++ render-wasm/src/state.rs | 10 ++++++++++ 3 files changed, 16 insertions(+) diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 9d4ff41617..162732d551 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -284,6 +284,7 @@ pub extern "C" fn set_view_end() { performance::end_measure!("set_view_end::clear_tile_index"); performance::end_timed_log!("clear_tile_index", _clear_start); } + state.render_state.sync_cached_viewbox(); performance::end_measure!("set_view_end"); performance::end_timed_log!("set_view_end", _end_start); #[cfg(feature = "profile-macros")] diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 1d80780bb1..f0619a9e37 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -1136,6 +1136,7 @@ impl RenderState { ) -> Result<(), String> { let _start = performance::begin_timed_log!("start_render_loop"); let scale = self.get_scale(); + self.tile_viewbox.update(self.viewbox, scale); self.focus_mode.reset(); @@ -2292,6 +2293,10 @@ impl RenderState { (self.viewbox.zoom - self.cached_viewbox.zoom).abs() > f32::EPSILON } + pub fn sync_cached_viewbox(&mut self) { + self.cached_viewbox = self.viewbox; + } + pub fn mark_touched(&mut self, uuid: Uuid) { self.touched_ids.insert(uuid); } diff --git a/render-wasm/src/state.rs b/render-wasm/src/state.rs index 40b272007c..f178ed4477 100644 --- a/render-wasm/src/state.rs +++ b/render-wasm/src/state.rs @@ -100,6 +100,16 @@ impl<'a> State<'a> { } pub fn start_render_loop(&mut self, timestamp: i32) -> Result<(), String> { + // If zoom changed, we MUST rebuild the tile index before using it. + // Otherwise, the index will have tiles from the old zoom level, causing visible + // tiles to appear empty. This can happen if start_render_loop() is called before + // set_view_end() finishes rebuilding the index, or if set_view_end() hasn't been + // called yet. + let zoom_changed = self.render_state.zoom_changed(); + if zoom_changed { + self.rebuild_tiles_shallow(); + } + self.render_state .start_render_loop(None, &self.shapes, timestamp, false)?; Ok(())