From f12100d783b60423de725e5c64b0857c0916fa47 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Wed, 15 Jul 2026 09:51:03 +0300 Subject: [PATCH] perf(scene): keep draw_depth_map warm across move/edit (phase 5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit draw_depth_map rebuilt on every geometry_epoch bump — an O(document) walk (all objects for SortEntitiesTable, all entities grouped-by-block and ranked), ~45ms per edit on a 788k-entity drawing, and it runs on every viewport snapshot. But draw order depends only on each block`s entity COUNT (the rank denominator), the entities` handles, and the SortEntitiesTable — none of which a Modify (move / rotate / scale / colour / hide) changes (owner and type are preserved, and the map ignores visibility). Gate the cache on the journal: an all-Modified edit keeps the map; only Add / Remove (count change) or a table change (a `full` delta) rebuilds it. So the common move/edit now skips the walk entirely. Co-Authored-By: Claude Opus 4.8 --- src/scene/mod.rs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/scene/mod.rs b/src/scene/mod.rs index 1b353b18d..bf5a68a1d 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -2976,11 +2976,31 @@ impl Scene { /// entities of different types order correctly against each other. pub(super) fn draw_depth_map(&self) -> Arc> { { - let cache = self.draw_depth_cache.borrow(); - if let Some((epoch, ref arc)) = *cache { - if epoch == self.geometry_epoch { - return Arc::clone(arc); + // Draw order depends on each block's entity COUNT (the rank + // denominator) and the entities' handles / SortEntitiesTable — none of + // which a Modify (move / rotate / scale / colour / hide) touches. So an + // all-Modified edit keeps the map; only Add / Remove (count change) or + // a table change (which arrives as a `full` delta) rebuilds it. + let reuse = { + let cache = self.draw_depth_cache.borrow(); + match *cache { + Some((epoch, ref arc)) + if epoch == self.geometry_epoch + || matches!( + self.replay_since(epoch), + Some(ref d) if d.iter().all(|&(_, k)| k == ChangeKind::Modified) + ) => + { + Some(Arc::clone(arc)) + } + _ => None, } + }; + if let Some(arc) = reuse { + if let Some((ref mut e, _)) = *self.draw_depth_cache.borrow_mut() { + *e = self.geometry_epoch; + } + return arc; } } use acadrust::objects::ObjectType;