- Changed default VISION_BACKEND from CPU to GPU for better performance. - Made `map_brush_style` public to allow external access. - Updated `Engine` struct to use pooled buffers for stroke snapshots, reducing memory allocations during brush strokes. - Introduced `CompositeSnapshot` for efficient background compositing without blocking the UI thread. - Implemented `SendPtr` for safe raw pointer handling across threads. - Enhanced `commit_pending_history` to recycle buffers and improve performance. - Fixed cursor preview issues for procedural brushes by removing unnecessary preset synchronization. - Added tests and documentation for new features and performance improvements.
3.2 KiB
Brush Stroke End Freeze Fix + Cursor Preview Fix
Issue 1: Stroke End Freeze (Partially Fixed)
Current State
- During drawing: canvas updates correctly (synchronous composite)
- After stroke end: still freezes due to
create_composite_snapshot()being expensive
Root Cause
create_composite_snapshot() in partial_composite.rs:354 clones ALL layers (33MB per layer on 4K) and ALL tile layers. For a 10-layer 4K document, this is ~330MB of cloning on the UI thread.
Fix: Skip background composite for brush strokes, use synchronous composite
File: hcie-egui-app/crates/hcie-gui-egui/src/canvas/render.rs
In render_composition(), the after-stroke-end path currently spawns a background thread. Instead:
- Do the synchronous composite directly (like during drawing)
- Only use background thread for very expensive operations (filters, fills)
- This eliminates the freeze for brush strokes
// After stroke end: do synchronous composite (not background)
// Background thread is too expensive due to create_composite_snapshot()
let (region, buf_ptr, buf_size) = doc.engine.render_composite_region();
// ... upload to texture ...
doc.engine.clear_dirty_flags();
Issue 2: Brush Cursor Preview Shows Wrong Shape
Current State
- ABR (bitmap) brushes: correct preview
- Procedural brushes (Round, Square, Star, etc.): shows as small circle
- After using ABR brush: preview gets stuck on ABR shape
Root Cause
The brushes_panel.rs changes (from other AI) added active_brush_preset_id sync that overrides the brush style. When a procedural style cell is clicked:
state.tool_configs.brush.styleis set correctly- But then
active_brush_preset_idis synced to a preset matching that style - If no matching preset exists, or if the preset has a different style, the preview gets confused
Fix: Remove the active_brush_preset_id sync
File: hcie-egui-app/crates/hcie-gui-egui/src/app/tools/brushes_panel.rs
Remove the 7-line block that was added:
// Sync active_brush_preset_id to a preset matching this style
// so the cursor preview shows the correct brush tip.
if let Some(matching) = state.brush_presets.iter().find(|p| {
to_tools_style(map_brush_style(p.tip.style)) == style
}) {
state.active_brush_preset_id = matching.id.clone();
}
The cursor preview already uses state.tool_configs.brush.style directly, not the preset. This sync is unnecessary and causes the preview to get stuck.
Files to Modify
| File | Change |
|---|---|
hcie-egui-app/crates/hcie-gui-egui/src/canvas/render.rs |
Use synchronous composite after stroke end |
hcie-egui-app/crates/hcie-gui-egui/src/app/tools/brushes_panel.rs |
Remove active_brush_preset_id sync |
Verification
- Stroke freeze test: Draw rapid brush strokes — no visible freeze on stroke end
- Cursor preview test: Switch between procedural brushes (Round, Square, Star) — preview should show correct shape
- ABR transition test: Use ABR brush, then switch to procedural — preview should update correctly
- Visual regression:
cargo test -p hcie-engine-api --test visual_regression - Performance test:
cargo test -p hcie-engine-api --test performance_stroke_4k -- --nocapture