fix: optimize brush stroke handling and improve cursor preview
- 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.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# Snapshot Freeze Analysis — Çizim Bitimindeki Takılma
|
||||
|
||||
## Problem
|
||||
|
||||
Fırça darbesi bittiğinde (pen-up), UI thread kısa süreli donuyor. Bu takılma snapshot (geri alım) mekanizmasının UI thread'de yaptığı büyük bellek tahsislerinden kaynaklanıyor.
|
||||
|
||||
## Kök Neden
|
||||
|
||||
`end_stroke()` ve `begin_stroke()` fonksiyonları UI thread'de çalışır ve her biri ~33MB'lik `layer.pixels.clone()` çağrısı yapar. 4K canvas'ta (3840×2160×4 = ~33MB) bu kopyalamalar allocate+copy gerektirir.
|
||||
|
||||
## Suçlu İşlemler
|
||||
|
||||
| # | İşlem | Dosya:Satır | Boyut | Etki |
|
||||
|---|-------|-------------|-------|------|
|
||||
| 1 | `layer.pixels.clone()` — before snapshot | `stroke_cache.rs:125` | ~33MB alloc+copy | Yüksek |
|
||||
| 2 | `layer.pixels.clone()` — after snapshot | `stroke_cache.rs:159` | ~33MB alloc+copy | **En yüksek** |
|
||||
| 3 | `active_stroke_mask.fill(0)` | `stroke_cache.rs:224` | ~8MB sıfırlama | Orta |
|
||||
| 4 | `raw_pixel_backup.remove()` — drop | `stroke_cache.rs:219` | ~33MB deallocation | Orta |
|
||||
| 5 | `apply_effects_and_sync_tiles()` | `partial_composite.rs:206-268` | ~99MB+ (efektli katmanlarda) | Yüksek |
|
||||
|
||||
## Akış Diyagramı
|
||||
|
||||
```
|
||||
begin_stroke() end_stroke()
|
||||
───────────── ─────────────
|
||||
1. mask.fill(0) [pooled, ~8MB] 1. before = stroke_before.take()
|
||||
2. before = layer.pixels.clone() [33MB] 2. after = layer.pixels.clone() [33MB] ← DONMA
|
||||
3. stroke_before = Some(before) 3. thread::spawn(move || { ... })
|
||||
4. rebuild_below_cache() 4. mask.fill(0) [pooled]
|
||||
5. raw_pixel_backup.remove()
|
||||
6. cached_selection_mask = None
|
||||
```
|
||||
|
||||
## Mevcut Havuz Mekanizmaları (İyi)
|
||||
|
||||
| Buffer | Boyut | Havuzda mı? | Not |
|
||||
|--------|-------|-------------|-----|
|
||||
| `active_stroke_mask` | ~8MB | Evet | `begin_stroke`'da fill(0), stroke arası korunur |
|
||||
| `composite_scratch` | ~33MB | Evet | Render sırasında kullanılır, serbest bırakılmaz |
|
||||
| `below_cache` | ~33MB | Evet | Stroke arası korunur, `below_cache_dirty` ile yönetilir |
|
||||
|
||||
## Havuzlanmayan Buffer'lar (Kötü)
|
||||
|
||||
| Buffer | Boyut | Neden havuzlanmıyor? |
|
||||
|--------|-------|----------------------|
|
||||
| `stroke_before` (before snapshot) | ~33MB | Her `begin_stroke`'da `clone()`, her `end_stroke`'da consume edilir |
|
||||
| `stroke_after` (after snapshot) | ~33MB | Her `end_stroke`'da `clone()`, background thread'e move edilir |
|
||||
|
||||
## Kritik Gözlem
|
||||
|
||||
`end_stroke()` çağrıldığında fırça darbesi bitmiştir. Bir sonraki `begin_stroke()`'a kadar `layer.pixels`'e hiçbir yazılmaz. Bu, background thread'in raw pointer ile okuma yapabileceği anlamına gelir — unsafe ama güvenli.
|
||||
|
||||
## Optimize Edilmiş Akış (Hedef)
|
||||
|
||||
```
|
||||
begin_stroke() end_stroke()
|
||||
───────────── ─────────────
|
||||
1. mask.fill(0) [pooled] 1. before = pooled buffer'dan take
|
||||
2. copy layer.pixels → pooled buf 2. copy layer.pixels → pooled after buf
|
||||
3. stroke_before = Some(pooled buf) 3. both buflar → background thread
|
||||
4. rebuild_below_cache() 4. mask.fill(0) [pooled]
|
||||
5. background thread: sub-rect çıkar, buffer'ları geri gönder
|
||||
```
|
||||
|
||||
## Dosyalar
|
||||
|
||||
- `hcie-engine-api/src/stroke_cache.rs` — begin_stroke, end_stroke
|
||||
- `hcie-engine-api/src/lib.rs` — Engine struct tanımı
|
||||
- `hcie-document/src/lib.rs` — push_draw_snapshot, push_draw_snapshot_subrect
|
||||
- `hcie-protocol/src/lib.rs` — Layer struct tanımı
|
||||
Reference in New Issue
Block a user