# Render Stabilite + Performans Yol Haritası

fikatia-local Vulkan render katmanı denetimi — final "döngülü performans" fazının yol haritası.
Donanım hedefi: RTX 4090 / 24 GB VRAM (Vulkan compute agresif). Salt denetim; kod değiştirilmedi.

Denetlenen dosyalar: `motor/render/{vulkan_aygit,vulkan_baglam,pencere_yuzeyi,viewport_hedef,gpu_tampon,boru_hatti,secim_gpu,compute_baglam}.cpp/.hpp`, `uygulama/fikocad/{belge_ciz,belge_yonetici,main}.cpp`, `motor/sahne/src/secim_sistemi.cpp`.

---

## 0. Genel değerlendirme

Render katmanı **olgun ve büyük ölçüde doğru**. Mimari temiz ayrık: `VulkanAygit` (uygulama-global: instance/device/queue/VMA/renderpass/transfer/emekli tampon/kare sayacı/device-lost) + `PencereYuzeyi` (pencere-başına swapchain, 2 kare-uçuşta) + `ViewportHedef` (offscreen 3B hedef) + `SecimGpu` (1×1 GPU pick). Device-lost yönetimi, timeout'lu bekleme (asla sonsuz), sıfır-boyut/NaN guard'ları, ertelenmiş tampon yıkımı, iki-yönlü subpass bağımlılıkları — hepsi mevcut ve düşünülmüş.

**Ana bulgu:** En büyük tek kazanç bir stabilite sorunu değil, bir israf: **GPU pick geçişi her kare tüm sahneyi ikinci kez raster ediyor** (§P1). Stabilite tarafında kritik açık YOK — bilinen MDI retire-race mimari değişiklikle (ayrı-süreç "Yeni Belge") **kapandı**. Kalan stabilite işleri "temizlik + gözlemlenebilirlik" seviyesinde.

**Öncelik:** Dalga 0 (ölçüm altyapısı) → Dalga 1 (stabilite temizliği) → Dalga 2 (pick gating = en yüksek kazanç) → Dalga 3 (ölçek: instancing/LOD/chunk) → Dalga 4 (4090 agresif: async compute/MSAA/occlusion).

---

## 1. STABİLİTE riskleri (öncelikli)

| # | Risk | Konum | Neden | Fix yönü | Önem/Efor |
|---|------|-------|-------|----------|-----------|
| **S1** | Global `kareSayac_` retire-race | `vulkan_aygit.cpp:87,97-105` `gpu_tampon.hpp:17-23` | Tek global sayaç + ping-pong slot, "pencere başına kare 1 ilerler" varsayar. Aynı-süreç çok-pencerede ihlal. | **ARTIK MOOT** — "Yeni Belge" ayrı `fikocad.exe` süreci oldu (`main.cpp:462-463`). Ek-pencere yolu kaldırıldı. `belgeleriKaydet` çok belgeyi TEK `kb`/TEK fence'e çizer → güvenli. **Yalnız invariant koruması:** `VulkanAygit::ucusteKare(112)` == `PencereYuzeyi::ucusteKare(73)` çift-tanımlı; tek sabite indir + `static_assert`. Aynı-süreç çok-pencere geri gelirse race geri gelir → yorum-uyarı bırak. | Düşük / XS |
| **S2** | Validation layer var ama mesaj yakalanmıyor | `vulkan_aygit.cpp:123-132` | Debug'da `VK_LAYER_KHRONOS_validation` etkin, ama `VK_EXT_debug_utils` uzantısı + `VkDebugUtilsMessenger` callback YOK. Sync/layout/lifetime uyarıları yalnız varsayılan çıktıya gider, `gunluk`'a düşmez → sessiz kalır. | Debug'da `VK_EXT_debug_utils` ekle + messenger kur → `gunluk::hata/uyari`'ya köprüle. **Gerçek sync bug'larını görmenin ön koşulu** (Dalga 0). | Yüksek / S |
| **S3** | Kare-içi GPU serileştirme (mid-frame stall) | `vulkan_aygit.cpp:307-326` (`anindaGonder`), tetik: `belge_ciz.cpp:303,324,446-449` | `GpuTampon` statik ctor yolu `anindaGonder` → `vkQueueSubmit`+`vkWaitForFences` (tam bekleme). Bu, kare `kb`'si AÇIKKEN (kayıt sırasında) grafik kuyruğuna submit+wait yapar. Yasal ama tüm GPU'yu serileştirir → mega-parti yeniden pişince / analiz skaler tamponu kurulunca kare takılır. | Doğruluk sorunu değil, **hitch kaynağı**. Skaler/sıfır tamponları `GpuTampon::guncelle` (dinamik, submit'siz) yoluna taşı; mega-parti uploadını `topluYukleme` batch'ine al. | Orta / M |
| **S4** | Resize'da çoklu device-idle | `belge_yonetici.cpp:54-55`, `viewport_hedef.cpp:83`, `secim_gpu.cpp:286` | Pencere yeniden boyutlanınca `ViewportHedef::boyutla` ve `SecimGpu::boyutAyarla` AYRI AYRI `vb_.bekle()` (tam `vkDeviceWaitIdle`) çağırır → resize başına birden çok tam GPU boşaltma → sürükleyerek boyutlandırmada gözle görülür takılma. | Resize'ı kare-başı tek device-idle noktasında topla (yenidenBoyutlandır bayrağı zaten `pencere_yuzeyi`'nde var — aynı kalıba çek). | Orta / S |
| **S5** | `pngKaydet` layout varsayımı | `viewport_hedef.cpp:132-159` | Bariyer `oldLayout = SHADER_READ_ONLY` varsayar; hiç kare render edilmeden çağrılırsa görüntü `UNDEFINED`'da → validation hatası / yanlış içerik. Oto-test yolunda tetiklenebilir. | İlk render'dan önce çağrıyı engelle veya layout'u izle. Düşük (yalnız --oto-test). | Düşük / XS |
| **S6** | Minimize'da busy-loop | `main.cpp:437-448`, `pencere_yuzeyi.cpp:233` | Minimize/0-boyutta `kareBasla`→null → kare atlanır ama ana döngüde `Sleep`/`WaitMessage` yok → boşta bir CPU çekirdeği %100. | Renderlenebilir pencere yoksa `WaitMessage`/kısa sleep. Güç/termal; stabilite değil. | Düşük / XS |

**Sağlam bulunan (dokunma):** swapchain OUT_OF_DATE/SUBOPTIMAL + acquire timeout işlenişi (`pencere_yuzeyi.cpp:257-265,325-330`), device-lost tek-nokta yönetimi (`aygitKaybiIsaretle`), fence'li timeout bekleme (asla sonsuz), sıfır-boyut GpuTampon guard (`gpu_tampon.cpp:19`), NaN kamera-fit guard (adaptif derinlik `belge_ciz.cpp:211-227`), derinlik görsel-başına (kare-arası hazard yok), subpass bağımlılıkları çift-yönlü.

---

## 2. PERFORMANS fırsatları (RTX 4090)

| # | Fırsat | Konum | Kazanç | Efor |
|---|--------|-------|--------|------|
| **P1** | **GPU pick her kare tüm sahneyi raster ediyor** | `belge_ciz.cpp:261` → `secim_sistemi.cpp:31-64` | Pick geçişi (yüz+kenar+nokta, düğüm-başı ayrı bind+draw) **her karede** koşuyor — fare hareket etmese/hover gerekmese bile. Bu, tam bir ikinci sahne çizimi. **Fareyi sadece hareket ettiğinde / tık beklerken çalıştır** (imleç deltası veya tık kuyruğu). Yoğun sahnede en büyük tek kazanç — kare başına bir sahne raster'ı düşer. | **En yüksek / S** |
| **P2** | Pick geçişi mega-parti kullanmıyor | `secim_sistemi.cpp:55-64` | Düğüm-başı bind+push+draw. Statik gövdeler için kimlik-per-instance'lı tek instanced/multidraw'a çevrilebilir (render mega-partinin ikizi). P1 sonrası ikincil. | Orta / M |
| **P3** | Mega-parti tek-blok → frustum cull yok | `belge_ciz.cpp:462-477` (model), `763-775` (kenar) | Tüm statik katılar dünya-uzayında TEK VB/IB → tek draw. Görünürlüğe bakılmaksızın tamamı çizilir. Büyük montajda ekran-dışı da raster edilir. **Uzaysal chunk'lara böl** (küme başına mega-parti) → chunk başına frustum cull. | Orta-Büyük / L |
| **P4** | Tekrarlı parça = instancing yok | `belge_ciz.cpp:480-508` | Montajda aynı mesh'in N kopyası her biri kendi VB'siyle çizilir. Özdeş mesh düğümleri **instanced draw** (per-instance model matrisi) ile tek çağrıya inebilir. Montajlarda büyük kazanç. | Büyük / L |
| **P5** | LOD yok | `belge_ciz.cpp` tüm çizim | Her düğüm her zaman tam çözünürlük. Ekran-uzayı LOD / decimation ile uzak/küçük mesh'ler basitleşir. Büyük mesh'lerde kare bütçesi kazancı. | Büyük / L |
| **P6** | Occlusion culling yok | — | Yalnız frustum var. 4090'da Hi-Z / query-tabanlı occlusion — CATIA-ölçek montajda büyük. Karmaşık. | Büyük / XL |
| **P7** | MSAA yok (her yerde 1 örnek) | `boru_hatti.cpp:93`, `secim_gpu.cpp:181`, `viewport_hedef.cpp:30` | Offscreen viewport aliaslı. 4090 2-4× MSAA'yı rahat kaldırır (yalnız renk hedefi + resolve; pick hedefi 1× kalmalı). Kalite; küçük perf + resolve maliyeti. | Kalite / M |
| **P8** | Compute grafik kuyruğunda serileşiyor | `compute_baglam.cpp:216-263` | `ComputeBaglam::calis` grafik kuyruğuna submit+tam-bekleme. Async compute yok. Döküm/SPH/SDF/analiz compute'u **ayrı compute kuyruğu + async** ile grafik render'la örtüşebilir. Compute-ağır döküm sim için büyük. | Büyük / L |
| **P9** | Pipeline cache yok | `boru_hatti.cpp:145`, `secim_gpu.cpp:217`, `compute_baglam.cpp:150` | Tüm `vkCreate*Pipelines` `VK_NULL_HANDLE` cache ile. Disk-destekli `VkPipelineCache` yok → her açılışta pipeline'lar sıfırdan derlenir (açılış gecikmesi, ~15+ grafik + N compute pipeline). | Küçük (açılış) / S |
| **P10** | MAILBOX → sınırsız FPS | `pencere_yuzeyi.cpp:111-119` | MAILBOX seçili (4090'da present bloklamaz) → boşta bile tam GPU/CPU + güç/termal. İsteğe bağlı FPS cap / FIFO toggle (ayar sistemine). | Küçük / S |

**İyi durumda:** Model + kenar için mega-parti (imza-tetikli rebuild, hover'dan bağımsız) zaten var (`belge_ciz.cpp:374-459,721-775`) — güçlü temel. Analiz geçişinde pipeline yeniden-bağlama minimize (`aktifHat` izleme, `belge_ciz.cpp:634`). Push-constant tabanlı (descriptor set yok → minimal state). Draw-call sayacı + mega-cook süresi loglanıyor (`belge_ciz.cpp:455,580-582`).

---

## 3. CPU sıcak yolları

| # | Sorun | Konum | Not |
|---|-------|-------|-----|
| **C1** | `sahne.dugumler()` kare başı ~12 kez tam taranıyor | `belge_ciz.cpp:214,388,411,480,545,596,723,737,776,805,819,873` + pick `secim_sistemi.cpp:56` | Adaptif derinlik, mega imza, mega cook, bireysel, hover, saydam, analiz, kenar imza/cook/bireysel, ref, eksen, seçim geçişleri — hepsi ayrı O(N) tarama. **Kare başı tek "görünür düğüm" listesi** (agacGorunur+frustum filtreli) kur, geçişler onu paylaşsın. | Orta / M |
| **C2** | `seciliMiGovde` iç-döngüde lineer | `belge_ciz.cpp:381-385` (çağrı 391,414,484,516,718) | Seçili sayısı × düğüm = O(N·S). Kare başı seçili-kimlik `unordered_set` önhesapla. | Küçük / S |
| **C3** | `analizSis.tumRenderBilgi()` kare başı map inşası | `belge_ciz.cpp:235` | Her kare yeni harita. Analiz sürümü değişmedikçe cache'le. | Küçük / S |
| **C4** | Mid-frame statik-ctor alloc | `belge_ciz.cpp:409,446-449,736,751` | Mega rebuild `std::vector` + statik upload stall (bkz S3). Nadir (imza değişince) ama tetiklendiğinde tam pipeline stall. | Orta (S3 ile) |

---

## 4. Ölçüm altyapısı (mevcut → hedef)

**Mevcut:** `[perf]` logları (mega-cook ms `belge_ciz.cpp:455,756`, draw-call sayısı her 600 karede `580`), kare süresi `kareSuresiMs_` main'de izleniyor. **Ekranda HUD yok, GPU timestamp yok, VRAM izleme yok, validation messenger yok.** `fikoyt-zorro.com`'daki `fiko-performance-monitor` benzeri bir şey native'de YOK.

**Hedef (Dalga 0 — her şeyin ön koşulu):**
1. **Vulkan debug messenger** (S2) → validation `gunluk`'a. Gerçek sync/lifetime bug'larını görmenin tek yolu.
2. **GPU timestamp query** (`VkQueryPool` + `vkCmdWriteTimestamp`) — geçiş başına GPU ms: pick / model / analiz / kenar / ImGui. Kanıt-tabanlı optimizasyon.
3. **Ekran-içi perf HUD** (ImGui overlay): FPS, kare ms (CPU), geçiş-başı GPU ms, draw-call, mega-indeks sayısı. `fiko-performance-monitor` native karşılığı.
4. **VRAM bütçesi**: `vmaGetHeapBudgets` → kullanılan/toplam VRAM (24 GB'ı agresif kullanırken kritik).
5. **Pipeline oluşturma süresi** logu (P9 kararı için).

---

## 5. Dalga planı

**Dalga 0 — Ölçüm altyapısı (ÖNCE, kısa):** debug messenger (S2) + GPU timestamp query pool + perf HUD + VMA VRAM bütçesi. Sonraki tüm dalgalar buna dayanır; kazançlar ölçülebilir olur.

**Dalga 1 — Stabilite temizliği:** messenger'ın açığa çıkardığı validation uyarılarını temizle → S4 (resize tek device-idle) → S3 (mid-frame stall: skaler/mega tamponları submit'siz yola al) → S1 invariant guard + `static_assert` → S5/S6 küçük guard'lar. Hedef: validation temiz, resize/mesh-güncelleme takılması yok.

**Dalga 2 — En yüksek kazanç perf (düşük risk):** **P1 pick gating** (kare-başı sahne raster'ı düşer — en büyük tek kazanç) → C1/C2 tek görünür-düğüm + seçili-set → P9 pipeline cache → P3 analiz skaler dinamik (S3 ile örtüşür). Hedef: tipik sahnede 60→144 FPS.

**Dalga 3 — Ölçek (büyük montaj):** P4 instancing (özdeş parçalar) → P3 chunk'lı mega-parti + chunk-başı frustum cull → P5 LOD. Hedef: 100k+ parça montajda kare bütçesi.

**Dalga 4 — 4090 agresif:** P8 async compute (döküm/SPH grafik'le örtüşür) → P7 MSAA (viewport kalite) → P6 Hi-Z occlusion. Hedef: compute-ağır döküm sim + render eşzamanlı, CATIA-ölçek occlusion.

**Kare bütçesi hedefi:** 144 FPS = 6.9 ms/kare. Dalga 0 HUD ile geçiş-başı bölünüp izlenir; pick (P1) düşünce model+analiz+kenar+ImGui bütçesi rahatlar.
