# Render & Performans Araştırma Raporu (GÜNCEL)

**Konu:** Fikatia 3D viewport render pipeline'ı (`belge_ciz.cpp`)
**Durum:** Sadece inceleme — kod değiştirilmedi.
**Son Güncelleme:** 2026-08-24 — P1 bulgusu geri çekildi (yanlış tespit), P4 riskli olarak güncelledi.

---

## 1. Build Durumu

✅ **Derleme başarılı** (`insa.bat` → exit 0). ID çakışması fix'i (`istakip_kayit_penceresi.cpp`) hatasız derlendi.

> Not: `insa.bat`'ın sonundaki `PAUSE` satırları bash üzerinden çıktıyı blokluyordu; `cmd.exe` + geçici log ile build'i teyit ettim.

---

## 2. Render Mimarisi Özeti

Viewport renderer `belge_ciz.cpp` → `belgeCiz()` fonksiyonunda. Temel akış:

| Katman | Teknik | Durum |
|--------|--------|-------|
| Draw-call kitleme | Mega-parti batching (48+ govde) | Aktif |
| LOD | Orbit/hover etkilesiminde kaba mesh | Aktif |
| GPU pick | Kenar/nokta icin, yüz CPU BVH | Aktif |
| Frustum culling | Node-basi gorunurluk (dugumFrustumGorunur) | Aktif |
| Double-buffering | GpuTampon 2-slot VMA | Aktif |
| Hover caching | Imlek/matris degisince yeniden hesap | Aktif |
| VSync | FIFO + resize debounce (250ms) | Aktif |
| İmza-based cook tetikleme | FNV-1a her kare (zaten filtresli) | Aktif |

Pipeline iskeleti iyi kurulmus. Aşağıdaki bulgular **alan darboğazları / riskli fırsatlar**.

---

## 3. Bulunan Darboğazlar (GÜNCELLENMİŞ)

### P1 - Her kare için imza hesaplaması (CPU) — **ZATEN OPTİMİZE EDİLMİŞ / KALDIRILDI** ❌

**Konum:** `belge_ciz.cpp:1111-1136`

```cpp
for (auto& d : sahne.dugumler()) {
    if (!d.gorunurBit_ || d.indeksSayi == 0) continue;   // <-- filtresi ZATEN VAR
    if (analizVarMi(d.kimlik) || kesitVar) continue;
    if (!secimPartide && seciliMiGovde(d.kimlik)) continue;
    if (d.cpuKonum.empty() || d.cpuIndeks.empty()) continue;
    if (d.saydamlik < 1.0f) continue;
    if (d.dinamikMesh) continue;
    ... FNV-1a imza ...
}
```

**DÜZELTME:** Rorumdaki "görünürlük filtresi olmadan çalışıyor" iddianti **HATALIYDI.** Döngü satır 1114'te `gorunurBit_` + `indeksSayi==0` filtresini içeriyor → sadece ağda görünür + mesh'li gövde için çalışır. Ek olarak `analizVarMi`, `seciliMiGovde`, `cpuKonum.empty()`, `saydamlik`, `dinamikMesh` filtresleri de var.

**Maliyet analiz:** 48 gövde × ~32 FNV-1a op = ~1,500 op/frame. 60 fps'de ~92k op/saniye. Modern bir CPU ~10M op/s → **CPU'nun <%1'i.** Kritik değil.

**Karar: Öncelik YOK. Kodu dokunulmadık bırak.**

---

### P4 - Cook loop'u frustum cull yapmıyor — **FIRSAT RİSKLİ (şimdi implemente edilmez)** ⚠️

**Konum:** `belge_ciz.cpp:1162` (cook loop'u) + imza döngüsü 1111'de AYRI

Mega-parti'ye dahil edilen **görünür ama ekranda görünmeyen** (frustum dışı) gövdenin vertex'leri bosha world-space'e dönüştürülüyor. Cook loop'u frustum-cull yapmıyor; render path'i (`belge_ciz.cpp:1261`) zaten `dugumFrustumGorunur` ile cull ediyor.

**`dugumFrustumGorunur`** → `motor/sahne/include/fiko/sahne/sahne.hpp:309` (inline). Dünyâ-ölçekli geçerli sınırlı katı gövdeleri `fr.kureGorunur()` ile test eder; ekran-sabit datum/wireframe her zaman görünür sayılır.

**RİSK (bu bir engel, sadece risk değil):**
1. Frustum her frame kameradan hesaplanır (statik değil). Cook loop'u frustum-cull ederse ve bunu imza döngüsüne (`imzaScratch`) yansırırsan, **imza her frame değişir** → mega-parti her frame yeniden pişer → **performans GERİLER.**
2. Cook'a frustum eklesek bile **imzaya eklememek** gerekir — ama bu da edge-case'ler doğurur: Gövdenin geometrisi frustum-dışındayken değişirse (dünya matrisi aynı kalır), imza değişmez → yeniden pişim tetiklenmez ama gövde cook'tan cull edildiği için yeni geometri pişirilir/yoksa geri geldiğinde **ESKİ geometri** render edilir. İmza shallow (pointer+boyut+matris); geometrinin derin içeriğini izlemez → bu senaryoyu yakalamaz.

**Karar: ŞİMDİ IMPLEMENTE EDİLEZ — analiz + test gerekli. Güvenli yol:**
- Önce imzanın frustum-dışından bağımsız kaldığından emin ol.
- Ayrı branch'te, önce `perf_hud` ile cook-sayısını izle.
- Cull sonrası cook frekansı düşmüyorsa → yanlış cull; artıyorsa → imza kararsızlığı.
- Edge-case'ler için önce unit-test ekle.

---

### P2 - Mega-parti pişirme: CPU vertex transformu — **Analiz edilmemiş (riskli)**

**Konum:** `belge_ciz.cpp:1162-1229`

Mega-parti'ye giren her gövdenin vertex'leri **dünya-uzayında CPU'da işleniyor** (vertex shader'a gönderilen veri world-space'e bake ediliyor). Vertex sayısı arttıkça lineer maliyet.

Yorumlar "70ms→18ms" iyileştirmesini gerektiriyor ama hala **cook tetiklendiğinde** O(toplam vertex). Ve P1'deki imza her değişiminde tekrarlıyor (ama P1 artık kritik değil — yukarıya bak).

**Durum:** Bu daha gerçekçi bir aday, ama cook fonksiyonunun tam akışını (throttle var mı, static scratch nasıl çalışıyor) okumadan öneri vermek erken. **Sonraki adım:** cook path'ini (1162-1229) detaylı oku.

---

### P3 - Mega-parti eşiği: tek seviye (48 gövde) — **Küçük potansiyel**

**Konum:** `belge_ciz.cpp:1149`

```cpp
constexpr size_t kMegaPartiEsik = 48;
```

Model **<=48 gövde** ise mega-parti KULLANILMAZ → her görünür = 1 draw-call + 1 push-constant + 2 buffer-bind. **48'den az gövdeli modellerde batch yok.**

30 gövdeli bir parça = 30 draw-call. 48+ modellerin tek mega-draw'ına kıyasla ~30x CPU draw-overhead.

**Karar:** Küçük bir kazanım (düşük gövde sayılı modeller). Öncelik düşük. Dinamik eşik önerisi riskli (batch boyutu değişince imza değişir).

---

### P5 - Depth mesafe her kare — **ZATEN CACHE'Lİ**

**Konum:** `belge_ciz.cpp:547-575`

Kamera hareketliyken **her kare O(N)** tüm görünür üzerinde min/max mesafe hesaplıyor. Kamera sabitken 30 kare cache'leniyor (iyi). Ama sürekli sürükleyip/pan yaparken sürekli O(N).

**Karar:** Cache süresini kısaltmak riskli (doğru derinlik için kritik). Öncelik düşük — önce profil çıkar, O(N) gerçekten görünür bir bottleneck mi diye gör.

---

## 4. Doğrulama Eksikliği (Teshhis)

- `belge_ciz.cpp:1253` satırında **"async mesh worker"** yazıyor, ama render path'inde `std::async`/`std::thread`/`std::jthread` **bulamadım.** Mesh yükleme async mi, yoksa başka modülde mi — teyit et. Eger async yoksa, büyük model import'unda main thread donması olabilir.

---

## 5. Özet - Ne Yapilmalı

| Öncelik | Bulgu | Durum |
|---------|-------|-------|
| — | P1 İmza filtresi | ✅ ZATEN OPTİMİZE EDİLMİŞ — dokunma |
| ⚠️ | P4 Frustum cull cook | Analiz + test gerekli — şimdi yapma |
| 📖 | P2 CPU vertex transform | Cook path'ini oku, sonra karar |
| ↓ | P3 Dinamik mega-parti eşiği | Küçük kazanım, düşük öncelik |
| ↓ | P5 Depth cache | Profil çıkar, önce gör |

---

**EN KRİTİK DÜZELTME:** Rorumun ilk versiyonunda P1'i "her kare, tüm node'lar için filtresiz 25 hash op" olarak raporlamıştım. **Bu yanlışydı.** Döngü zaten `gorunurBit_` ile filtresli ve maliyeti CPU'nun <%1'i. Kod dokunulmadık bırakıldı.

---

## 6. Kaynak Dosyalar

- `uygulama/fikocad/belge_ciz.cpp` - Ana viewport renderer (draw zinciri + mega-parti)
- `uygulama/fikocad/belge_ciz.hpp` - PerfGosterge + draw-call sayacı
- `motor/sahne/include/fiko/sahne/sahne.hpp:309` - dugumFrustumGorunur (frustum cull yardımcısı)
- `motor/render/src/gpu_tampon.cpp` - GpuTampon double-buffering
- `motor/render/src/boru_hatti.cpp` - Vulkan graphics pipeline + push-constant
- `motor/render/src/pencere_yuzeyi.cpp` - Swapchain + resize debounce
- `uygulama/fikocad/istakip_kayit_penceresi.cpp` - ImGui ID cakismasi fix'i
