0d1b0eae4c
- 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.
71 lines
3.6 KiB
Markdown
71 lines
3.6 KiB
Markdown
# 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ı
|