From 71119228523fb05a2ca09c732b615cf8257e55d2 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Fri, 5 Jun 2026 00:58:35 +0300 Subject: [PATCH] perf(scene): skip re-tessellation on hover of selected entity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 3.1 (partial). set_hover_highlight bumped the geometry epoch on every hover-target change, forcing a full model re-tessellation. The hover handle is folded into the tessellation highlight set as selected ∪ {hover}, so hovering an already-selected entity contributes nothing — the effective set and every resulting WireModel are identical. Guard the bump on the effective highlight contribution actually changing; hovering over or between selected entities is now free. The field is still updated so hit-test / UI state stays current. The full camera/selection-from-tessellation cache split (3.1 / 2.2) is left open: highlight colour is baked into WireModel.color across several tessellation sites, so decoupling it needs running-app verification. Co-Authored-By: Claude Opus 4.8 --- ROADMAP.md | 8 ++++++++ src/scene/mod.rs | 16 ++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index dc9a2dcf2..e62ae9618 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -162,6 +162,14 @@ geometry is camera-invariant. changed), - `frame_visible[handle] → bool` (recomputed per `camera_generation`). +**Partial (landed):** `set_hover_highlight` no longer bumps the geometry +epoch (a full re-tessellation) when the hovered entity is already selected — +the effective highlight set `selected ∪ {hover}` is then unchanged, so the +tessellation output is identical. Hovering over / between selected entities +is now free. The full camera/selection-from-tessellation split is still open +and needs running-app verification (highlight colour is baked into +`WireModel.color` across several tessellation sites). + ### 3.2 Persistent GPU buffer pool — diff upload Today every wire GPU buffer is re-uploaded when diff --git a/src/scene/mod.rs b/src/scene/mod.rs index b4e3b1a40..130381afb 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -1367,8 +1367,20 @@ impl Scene { /// Set (or clear) the previewed entity that renders with the selection /// highlight without joining the real selection. Re-tessellates on change. pub fn set_hover_highlight(&mut self, handle: Option) { - if self.hover_highlight != handle { - self.hover_highlight = handle; + if self.hover_highlight == handle { + return; + } + // The hover entity is folded into the tessellation highlight set + // (selected ∪ {hover}); see `wires_for_block_culled`. A hover handle + // that's already selected contributes nothing, so the effective set — + // and thus every WireModel — is identical. Only re-tessellate when the + // effective highlight contribution actually changes; hovering over (or + // between) already-selected entities then costs nothing. The field is + // still updated so hit-test / UI state stays current. + let contribution = |h: Option| h.filter(|h| !self.selected.contains(h)); + let changed = contribution(self.hover_highlight) != contribution(handle); + self.hover_highlight = handle; + if changed { self.bump_geometry(); } }