perf(scene): skip re-tessellation on hover of selected entity
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 <noreply@anthropic.com>
This commit is contained in:
parent
16050909f9
commit
7111922852
2 changed files with 22 additions and 2 deletions
|
|
@ -162,6 +162,14 @@ geometry is camera-invariant.
|
||||||
changed),
|
changed),
|
||||||
- `frame_visible[handle] → bool` (recomputed per `camera_generation`).
|
- `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
|
### 3.2 Persistent GPU buffer pool — diff upload
|
||||||
|
|
||||||
Today every wire GPU buffer is re-uploaded when
|
Today every wire GPU buffer is re-uploaded when
|
||||||
|
|
|
||||||
|
|
@ -1367,8 +1367,20 @@ impl Scene {
|
||||||
/// Set (or clear) the previewed entity that renders with the selection
|
/// Set (or clear) the previewed entity that renders with the selection
|
||||||
/// highlight without joining the real selection. Re-tessellates on change.
|
/// highlight without joining the real selection. Re-tessellates on change.
|
||||||
pub fn set_hover_highlight(&mut self, handle: Option<Handle>) {
|
pub fn set_hover_highlight(&mut self, handle: Option<Handle>) {
|
||||||
if 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<Handle>| h.filter(|h| !self.selected.contains(h));
|
||||||
|
let changed = contribution(self.hover_highlight) != contribution(handle);
|
||||||
self.hover_highlight = handle;
|
self.hover_highlight = handle;
|
||||||
|
if changed {
|
||||||
self.bump_geometry();
|
self.bump_geometry();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue