forked from 1b-agent/opencadstudio-upstream
perf: let one tessellation serve every background
Switching to a Layout re-tessellated the whole model — `memo_miss=186455`, 2034 ms — to arrive at geometry identical to what was already in the memo. The only thing that differed was colour. `local_wires_for` already knows this: it stores the raw colour and drops its background argument with `let _ = bg_color;`, noting that `Batches::finalize` applies `adapt_to_bg` last, "so the cache no longer has to rebuild on BACKGROUND / layout-switch". The tessellation memo's guard had not been told, and still mixed the background in, so every entry was discarded on a switch. `finalize` now records what its colour resolution consumed — the raw colour, the raw glyph colours, and the three flags it branches on — as `WireModel::bg_adapt`, and `resolve_colors_for_bg` replays it for another background. The guard drops the background, so a memo entry serves any layout. The resolution recomputes from the recorded raw colour rather than from the resolved one, which makes it idempotent and therefore safe over a set that mixes memo hits with freshly tessellated misses. Re-adapting the resolved colour would not be safe: `adapt_to_bg` snaps a near-white colour to pure black on a light background, and pure black comes back pure *white* on a dark one, losing the tint. A test pins that asymmetry so the raw colour is not optimised away later. The contract is tested against the real `finalize` rather than a copy of its logic: for every background pair, building under one and resolving for the other lands exactly where building under the other would have. `bg_adapt` is `None` for wires built anywhere else, and the resolution skips them, so nothing outside the block cache changes colour. It is also `None` when the resolution would be a no-op — a preserved colour with no canvas fill looks the same under every background — which keeps the common case at no cost. Ordering is unchanged: the pass runs inside the builder, before `append_scene_markers` and `apply_refedit_fade`, both of which have their own separate background dependency. `wires-build` gains `colors=` so the pass has a number of its own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0e4f755e6f
commit
391a74a615
40 files changed
+308
-9
No files matched your search
@@ -3145,6 +3145,43 @@ pub(crate) fn adapt_to_bg(color: [f32; 4], bg: [f32; 4]) -> [f32; 4] {
|
||||
}
|
||||
}
|
||||
|
||||
/// Re-resolve display colours for `bg`, for wires that recorded what their
|
||||
/// resolution consumed.
|
||||
///
|
||||
/// This is what lets a set tessellated under one background be shown under
|
||||
/// another without rebuilding it: the geometry never depended on the
|
||||
/// background, only the colours did — see the `let _ = bg_color;` in
|
||||
/// `block_cache::local_wires_for`.
|
||||
///
|
||||
/// Every colour is recomputed from `raw_color`, never from the current
|
||||
/// `color`, so the pass is idempotent and safe over a set that mixes memoized
|
||||
/// wires with freshly tessellated ones. Recomputing from `color` would not be:
|
||||
/// `adapt_to_bg` maps a near-white colour to pure black, and pure black back
|
||||
/// to pure *white*, so a second application loses the original tint.
|
||||
///
|
||||
/// Wires with `bg_adapt: None` — everything not built by `Batches::finalize` —
|
||||
/// are left alone.
|
||||
pub(crate) fn resolve_colors_for_bg(wires: &mut [WireModel], bg: [f32; 4]) {
|
||||
for wire in wires {
|
||||
let Some(adapt) = wire.bg_adapt.as_deref() else {
|
||||
continue;
|
||||
};
|
||||
let contrast = adapt.contrast_bg.unwrap_or(bg);
|
||||
wire.color = if adapt.canvas_color {
|
||||
bg
|
||||
} else if adapt.preserve_color {
|
||||
adapt.raw_color
|
||||
} else {
|
||||
adapt_to_bg(adapt.raw_color, contrast)
|
||||
};
|
||||
if !adapt.preserve_color {
|
||||
for (vertex, raw) in wire.text_verts.iter_mut().zip(&adapt.text_raw_colors) {
|
||||
vertex.color = adapt_to_bg(*raw, contrast);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Primitive builder helpers (called by ViewportPane's shader::Program impl) ──
|
||||
|
||||
impl Scene {
|
||||
|
||||
Reference in new issue
Block a user