forked from 1b-agent/opencadstudio-upstream
perf(text): cache SDF text vertices across frames
The SDF text collector re-laid out every glyph of every text entity on each frame (pan/zoom included). Cache the vertex list on the Scene keyed by (geometry_epoch, annotation-scale bits) — it only changes when geometry or the scale changes — so pan/zoom reuses it. Glyph baking happens on the cache-miss path only; the atlas is a persistent global and the texture upload is already gated on the geometry epoch, so cache hits skip both the layout and any re-upload. No behaviour change. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
75ddab6da7
commit
fd0b8fc1d4
2 files changed
+32
-3
No files matched your search
@@ -710,6 +710,11 @@ pub struct Scene {
|
||||
pub(crate) model_tiles: RefCell<Vec<ModelTile>>,
|
||||
/// Index of the active model tile (camera input + overlays target it).
|
||||
pub(crate) active_model_tile: std::cell::Cell<usize>,
|
||||
/// Cache of the SDF text vertex list, keyed on `(geometry_epoch,
|
||||
/// anno_scale.to_bits())`, so the per-frame collector is not re-laid-out on
|
||||
/// pan / zoom. See [`Scene::sdf_text_vertices`].
|
||||
sdf_text_cache:
|
||||
RefCell<Option<(u64, u32, std::sync::Arc<Vec<crate::scene::pipeline::text_gpu::TextVertex>>)>>,
|
||||
/// pane_grid layout tree for the Model tab — the source of truth for the
|
||||
/// tile split layout, resize and focus. `model_tiles` (the renderer's
|
||||
/// per-pane data: camera / render-mode / grid) is kept in lock-step with
|
||||
@@ -959,6 +964,7 @@ impl Scene {
|
||||
snap_on: false,
|
||||
}]),
|
||||
active_model_tile: std::cell::Cell::new(0),
|
||||
sdf_text_cache: RefCell::new(None),
|
||||
// One pane mapped to tile 0 — matches the single default tile above.
|
||||
model_panes: iced::widget::pane_grid::State::new(0).0,
|
||||
selection: Rc::new(RefCell::new(SelectionState::default())),
|
||||
|
||||
@@ -783,8 +783,31 @@ impl Scene {
|
||||
#[allow(dead_code)] // consumed by the text render pass in the GPU integration step
|
||||
pub(in crate::scene) fn sdf_text_vertices(
|
||||
&self,
|
||||
) -> Vec<crate::scene::pipeline::text_gpu::TextVertex> {
|
||||
self.sdf_text_vertices_enabled(crate::scene::text::sdf_atlas::sdf_text_enabled())
|
||||
) -> std::sync::Arc<Vec<crate::scene::pipeline::text_gpu::TextVertex>> {
|
||||
use std::sync::Arc;
|
||||
if !crate::scene::text::sdf_atlas::sdf_text_enabled() {
|
||||
return Arc::new(Vec::new());
|
||||
}
|
||||
// Cache keyed on (geometry_epoch, annotation scale): the run layout only
|
||||
// changes when geometry or the scale changes, so pan / zoom reuses it
|
||||
// instead of re-laying-out every glyph each frame.
|
||||
let anno = if self.current_layout == "Model" {
|
||||
self.annotation_scale
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
let key = (self.geometry_epoch, anno.to_bits());
|
||||
{
|
||||
let cache = self.sdf_text_cache.borrow();
|
||||
if let Some((epoch, anno_bits, verts)) = cache.as_ref() {
|
||||
if *epoch == key.0 && *anno_bits == key.1 {
|
||||
return verts.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
let verts = Arc::new(self.sdf_text_vertices_enabled(true));
|
||||
*self.sdf_text_cache.borrow_mut() = Some((key.0, key.1, verts.clone()));
|
||||
verts
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -1152,7 +1175,7 @@ impl Scene {
|
||||
let text_verts = if inst.paper_sheet {
|
||||
Arc::new(Vec::new())
|
||||
} else {
|
||||
Arc::new(self.sdf_text_vertices())
|
||||
self.sdf_text_vertices()
|
||||
};
|
||||
Some(ViewportData {
|
||||
wires: all_wires,
|
||||
|
||||
Reference in new issue
Block a user