perf(glyphs): memoize constraint-glyph placements behind constraints_epoch

Placements (entity lookups, intersections, String labels, projections)
recomputed per view() and per mouse-move hit-test, with overlay re-clones
and 2-3x offset recomputes. New constraints_epoch bumped on every set
mutation/visibility/undo/DWG-load (plus new set_constraint_enabled API);
single-slot Arc<[GlyphEntry]> memo on an 11-field key (hover/selection
excluded); overlay de-cloned/de-duped to the single geometry source;
hit paths reuse the cache.

Tests:
- cached_glyph_placements_hit_returns_same_arc: same-key Arc identity
- cached_glyph_placements_invalidated_by_metadata_edit: edit + selection change yield new Arc
- glyph_hit_test_entries_matches_precomputed_boxes: shared hit-test helper

Bench (cargo bench glyph, 60 constraints): 8.18us -> 0.05-0.15us (~55x).
A/B reference deleted.
This commit is contained in:
Karim Jerbi committed 2026-09-21 22:52:47 +01:00
1 parent 2d49204c50
commit 4432f633e7
12 files changed
+767 -239

No files matched your search

+12
View File
@@ -1409,6 +1409,7 @@ impl OpenCADStudio {
dimension.into_iter().collect(),
parameter.into_iter().collect(),
);
self.tabs[i].scene.bump_constraints_epoch();
if self.tabs[i].scene.selected_constraint == Some(id) {
self.tabs[i].scene.selected_constraint = None;
}
@@ -1720,6 +1721,9 @@ impl OpenCADStudio {
self.tabs[i]
.scene
.record_undo_parametric_constraints_before(scope, before);
// A parameter rename rewrites the `Named` driving references
// pointing at it — the glyph labels change with them.
let mut renamed = false;
for constraint in
&mut self.tabs[i].scene.parametric_constraints[set_index].constraints
{
@@ -1728,9 +1732,13 @@ impl OpenCADStudio {
{
if name == &current.name {
*name = typed.clone();
renamed = true;
}
}
}
if renamed {
self.tabs[i].scene.bump_constraints_epoch();
}
}
}
self.resolve_named_parameter_edit(i, &resolve_name);
@@ -1866,6 +1874,10 @@ impl OpenCADStudio {
if let Some(constraint) = set.constraints.iter_mut().find(|c| c.id == id) {
constraint.enabled = !reference;
}
// Toggling `enabled` changes the glyph placement set (and the
// dynamic pills), so the memoised placements must miss next
// frame — same guarantee `set_constraint_enabled` gives.
self.tabs[i].scene.bump_constraints_epoch();
self.tabs[i].scene.refresh_dynamic_dimension_texts();
self.tabs[i].scene.sync_native_parametric_graph();
self.tabs[i].dirty = true;