From 15bddb2f58f674475e71079b99a7c71daafd5872 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Fri, 15 May 2026 23:53:26 +0300 Subject: [PATCH] chore(scene): drop INSERT_SUB_LIMIT guard from fallback explode path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 5,000 sub-entity guard was added when an xref block with ~74k subs froze the UI on first render. The block_cache primary path (def72e4) made that path unreachable for typical Inserts — the guard now only gated the rare legacy-explode fallback, where it hid otherwise-renderable geometry as an insertion marker. Remove the constant and its early-return; the fallback path now matches the primary path's "render everything" behaviour. Also drop the RENDERING_OPTIMIZATION.md "TEMPORARY" section that tracked this guard. Co-Authored-By: Claude Opus 4.7 --- RENDERING_OPTIMIZATION.md | 40 --------------------------------------- src/scene/mod.rs | 11 +++-------- 2 files changed, 3 insertions(+), 48 deletions(-) diff --git a/RENDERING_OPTIMIZATION.md b/RENDERING_OPTIMIZATION.md index 2dec2df56..695294418 100644 --- a/RENDERING_OPTIMIZATION.md +++ b/RENDERING_OPTIMIZATION.md @@ -112,43 +112,3 @@ Phase 4.2 Hi-Z occlusion high complexity, 3D only, last - **Phase 2 target:** Pan/zoom frame cost O(visible) not O(total). - **Phase 4 target:** GPU-cull overhead < 0.5 ms for 1M entity scene. ---- - -## TEMPORARY: Insert sub-entity count limit (revert when better fix lands) - -`tessellate_entity` in `src/scene/mod.rs` has a guard that short-circuits any -Insert whose referenced block contains more than `INSERT_SUB_LIMIT` (currently -5,000) sub-entities. The Insert is rendered as an insertion marker only — no -explode, no sub tessellation. - -**Why this exists:** A real-world DWG was found where an xref block contained -~74k sub-entities. Opening the file froze the UI on the first render because -`tessellate_entity` exploded the block and serially style-resolved every -sub-entity (and any single bad sub could hang tessellation forever). The guard -made the file openable. - -**Why it should go away:** The limit hides legitimate geometry. Large xrefs are -common in civil/infrastructure drawings — the user shouldn't have to see them -as crosses. - -**Proper fixes that would let us drop this guard:** -1. ~~Per-block tessellation cache~~ — **LANDED** (`def72e4`): block defns are - tessellated once and per-Insert reuses the cached wires via - `block_cache::expand_insert`. The guard now only fires on the legacy - fallback path; consider lowering or removing it. -2. Lazy / background Insert tessellation — show marker first, fill in detail - on a background thread, redraw when ready. -3. Per-sub-entity hardening — find why a single sub can hang tessellation - (likely Spline NURBS evaluation or malformed boundary edge) and fix the - root cause; combine with sub-count budget per frame instead of a hard cap. -4. xref attach metadata respected — DWG carries an "unloaded" state for xref - blocks; honour it instead of always inlining xref content on open. - (Attempted in `e88a946`, reverted in `0996b75` — the on-disk bit was - unreliable as a Loaded/Unloaded signal.) - -When any of (2)–(3) lands, delete the `INSERT_SUB_LIMIT` block in -`tessellate_entity` (search for `INSERT_SUB_LIMIT`). - -Related companion fix in `src/app/update.rs`: after `resolve_xrefs`, a second -`purge_corrupt_entities` pass runs against the newly inlined xref content. -That one is not a hack — it should stay even after the Insert guard goes. diff --git a/src/scene/mod.rs b/src/scene/mod.rs index 25d8eeb4a..b04b88e09 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -4344,18 +4344,13 @@ fn tessellate_entity( } } - // Cache miss / unavailable: fall back to the original explode path, - // but keep the safety bail-out for pathologically large blocks so - // the UI doesn't hang on broken or unbounded sub-entity counts. - const INSERT_SUB_LIMIT: usize = 5_000; + // Cache miss / unavailable: fall back to the original explode path. + // The block_cache primary path covers all typical Inserts; this + // branch only fires for pathological cache failures. let br = document.block_records.get(&ins.block_name); - let sub_count = br.map(|br| br.entity_handles.len()).unwrap_or(0); let is_xref = br .map(|br| br.flags.is_xref || br.flags.is_xref_overlay) .unwrap_or(false); - if sub_count > INSERT_SUB_LIMIT { - return vec![marker]; - } let mut wires: Vec = ins .explode_from_document(document) .iter()