GPU Pipeline &
Rendering Optimization

Aygün ÖZGÜR 2025

00 İçindekiler

01 Bu Workshop Neden Gerekli?

Oyun geliştirme sürecinde performans optimizasyonu genellikle "sonra bakarız" yaklaşımıyla ertelenir.

Ancak temel rendering kavramlarını anlamadan yapılan işler, projenin ilerleyen aşamalarında ciddi performans sorunlarına yol açar.

Workshop'un Amacı:

01 Önemli Not: Profesyonel Yaklaşım

Bu dokümandaki teknik tespitler kişisel eleştiri değildir.

Burada belirtilen sorunlar ve öneriler, yapılan işin daha iyi olması için sunulan teknik geri bildirimlerdir.

Kimse kötü iş yapmıyor.

Sorun genellikle iletişimsiz ve izinsiz yapılan değişikliklerden kaynaklanıyor.

Bu yüzden:

02 CPU vs GPU - Mimari Farklar

Özellik CPU GPU
Core Sayısı 4-16 (güçlü) 1000+ (basit)
Görev Tipi Seri işlemler Paralel işlemler
Karar Verme Mükemmel Zayıf
Aynı İşi Tekrarlama Orta Mükemmel
Analoji

CPU bir profesör gibidir - karmaşık problemleri tek başına çözebilir.

GPU ise bir fabrika hattıdır - aynı basit işlemi binlerce kez paralel yapabilir.

02 GPU'nun Gücünü Doğru Kullanmak

Kritik Bilgi

GPU'ya "karar vermeyi gerektiren" işler yüklerseniz (çok sayıda farklı shader, farklı state'ler), GPU'nun paralel işlem gücünü boşa harcarsınız.

Kötü Kullanım
  • Her obje için farklı shader
  • Sürekli state değişimi
  • GPU "karar veriyor"
İyi Kullanım
  • Aynı shader, farklı material
  • Minimal state değişimi
  • GPU "aynı işi tekrarlıyor"

Altın Kural: GPU en verimli şekilde "aynı işi binlerce kez" yaptığında çalışır.

02 Rendering Pipeline Aşamaları

┌─────────────────┐ │ Application │ ← CPU: Oyun mantığı │ Stage │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Geometry Stage │ ← GPU: Vertex işleme │ (Vertex Shader) │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Rasterization │ ← Triangle → Pixel │ │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Fragment Stage │ ← GPU: Pixel renklendirme │ (Pixel Shader) │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Output Merger │ ← Depth test, blending │ │ └─────────────────┘

Aşamalar

  • Application: CPU tarafında oyun mantığı
  • Vertex Shader: Her köşe noktası için çalışır
  • Rasterization: 3D → 2D dönüşümü
  • Fragment Shader: Her pixel için çalışır
  • Output Merger: Final görüntü

02 Vertex Shader vs Fragment Shader

Vertex Shader

3D modelin her köşe noktası için çalışır.

  • Pozisyon hesaplama
  • Normal transform
  • UV koordinat manipülasyonu
10,000
vertex = 10K çalışma

Fragment Shader

Ekrandaki her pixel için çalışır.

  • Texture sampling
  • Lighting hesaplama
  • Final renk belirleme
2M+
1080p = 2M+ çalışma!
Kritik Nokta

Büyük objeler için Fragment Shader maliyeti çok yüksek olabilir. Ekranda kapladığı alana bağlıdır!

02 Rasterization Nedir?

Rasterization, 3D triangle'ları 2D pixel grid'ine dönüştürme işlemidir.

Triangle (3 vertex) Pixels * ░░░█░░░ / \ → ░░███░░ / \ ░█████░ *─────* ███████

Bu aşamada:

03 Draw Call Nedir?

Draw Call, CPU'nun GPU'ya "şu mesh'i, şu material ile çiz" demesidir.

CPU GPU │ │ ├─► "Mesh A + Material X" ──► Çiz ├─► "Mesh B + Material Y" ──► Çiz ├─► "Mesh C + Material X" ──► Çiz └─► ... ...

Her Draw Call maliyetlidir çünkü:

100-200
Mobil Hedef
500-2K
PC Hedef

03 GPU State Change ve Maliyeti

GPU, render state'ini değiştirdiğinde performans kaybı olur.

State Değişikliği Maliyet Açıklama
Shader değişimi ÇOK YÜKSEK GPU pipeline yeniden konfigüre
Texture değişimi YÜKSEK Farklı texture bind etme
Material property ORTA Aynı shader, farklı parametreler
Mesh değişimi DÜŞÜK Vertex buffer swap
Kritik Bilgi

10 farklı shader kullanmak, 1 shader + 10 material kullanmaktan çok daha maliyetlidir!

03 Batching Türleri

Batching, birden fazla Draw Call'u tek bir Draw Call'a birleştirme işlemidir.

Static Batching

  • Statik objeler tek mesh'e birleştirilir
  • Static flag + aynı material gerekli
  • Runtime CPU maliyeti yok
  • Memory artışı dezavantajı

Dynamic Batching

  • Küçük mesh'ler runtime'da birleşir
  • <300 vertex, aynı material
  • CPU overhead var

SRP Batcher (URP/HDRP)

  • Aynı shader variant gruplandırılır
  • Farklı material property'leri olabilir
  • En modern yaklaşım
Static Batching: Mesh A + Mat X ─┐ Mesh B + Mat X ─┼─► Tek Draw Call Mesh C + Mat X ─┘ SRP Batcher: Mesh A + Mat X (shader Y) ─┐ Mesh B + Mat Z (shader Y) ─┼─► GPU State korunur Mesh C + Mat W (shader Y) ─┘

03 Static Batching Dikkat!

Static Batching ve Culling Sorunu

Static Batching kullanıldığında, birleştirilen tüm objeler tek bir bounding box altında gruplanır.

Bu durum:

Çözüm

Static Batching'i dikkatli kullanın. Çok geniş alana yayılmış objeler için ayrı batch'ler oluşturun veya SRP Batcher tercih edin.

04 Culling Sistemleri

Frustum Culling

Kameranın görüş alanı dışındaki objeleri render etmeme işlemi.

Kamera Görüş Alanı ╱─────────╲ ╱ ╲ ╱ [Render] ╲ ╱ ╲ ╱ ╲ [X] [X] Cull Cull

OTOMATİK Unity'de otomatik çalışır.

Occlusion Culling

Başka objeler tarafından kapatılan objeleri render etmeme.

Kamera ──► [Duvar] [Arkadaki] Render Cull ✓

MANUEL Ayar gerektirir:

  1. Window → Rendering → Occlusion Culling
  2. Occluder/Occludee işaretleme
  3. Bake işlemi

04 Ne Zaman Culling Çalışmaz?

Durum Neden Çözüm
Vertex displacement Bounding box güncellenmez Custom bounds ayarla
Çok büyük bounding box Obje her zaman "görünür" Mesh'i parçala
LOD Group yanlış ayar Culling distance hatalı LOD seviyelerini kontrol et
Static Batching Tek bounding box Batch gruplarını dikkatli oluştur

04 Mesh Vertex Sorunları

Mesh'lerin ek noktalarında veya weld edilen kısımlarda ufak boşluklar kalabilir:

Kötü Weld Örneği: Mesh A Mesh B │ │ └──┐ ┌────┘ │ ◄── │ Boşluk (gap) ┌──┘ └────┐ │ │

Sorunlar:

Çözüm

3D yazılımda vertex'leri merge edin. Wireframe mode'da kontrol edin. Tolerance: 0.001 unit

05 Shader Variant Nedir?

Shader Variant, aynı shader'ın farklı keyword kombinasyonlarıyla derlenmiş versiyonlarıdır.

#pragma multi_compile _ FOG_ON
#pragma multi_compile _ SHADOWS_ON

Bu shader için 4 variant derlenir:

  1. (hiçbiri)
  2. FOG_ON
  3. SHADOWS_ON
  4. FOG_ON + SHADOWS_ON
N keyword = 2N variant

05 Boolean ve Factorial Growth

Her boolean/toggle 2x variant demektir:

Boolean Sayısı Hesaplama Variant Sayısı
1 boolean 2
5 boolean 2⁵ 32
10 boolean 2¹⁰ 1,024
20 boolean 2²⁰ 1,048,576
50 boolean 2⁵⁰ 1+ Katrilyon!
Kritik Uyarı

Shader'a her eklediğiniz [Toggle] property, variant sayısını KATLAR. 10 toggle = 1024 variant = build süresinde patlama!

05 multi_compile vs shader_feature

Direktif Derleme Kullanım
multi_compile HEPSİ derlenir Runtime'da değişecek global keyword'ler
shader_feature Sadece kullanılanlar Material'e bağlı, strip edilir
shader_feature_local En verimli Sadece o material için
Kötü
#pragma multi_compile _ EFFECT_A
#pragma multi_compile _ EFFECT_B
#pragma multi_compile _ EFFECT_C
// Hepsi build'e dahil!
İyi
#pragma shader_feature_local _ EFFECT_A
#pragma shader_feature_local _ EFFECT_B
#pragma shader_feature_local _ EFFECT_C
// Sadece kullanılanlar!

05 Shared Material Avantajları

Ayrı Material'ler
Building_01 → M_Building_01 → Shader X
Building_02 → M_Building_02 → Shader X
Building_03 → M_Building_03 → Shader X

= 3 Draw Call, batch break
Shared Material
Building_01 ─┐
Building_02 ─┼─► M_Buildings → Shader X
Building_03 ─┘

= 1 Draw Call (batched)

Shared Material Gereksinimleri:

06 Kritik Bağlam: Entegrasyon Projesi

ÖNEMLİ

Bu proje (Integration Project) ana oyundan ayrı bir entegrasyon projesidir. Ana oyuna dahil edildiğinde shader sayıları birleşecek.

Proje Shader Sayısı
Bu proje (Integration) ~60
Ana proje ~300-600 (5-10x)
Birleştirildiğinde ~360-660+

"Az shader var" diyip geçmeyin.
Her eklenen shader, final build'de katlanarak etki eder.

06 Mevcut Durum Analizi

60+
Custom Shader
~50
.shader dosyası
~15
.shadergraph
1,500+
Material

Kritik Shader Sorunları:

Shader Sorun Kritiklik
Splatmap.shader 600+ shader_feature YÜKSEK
Grunge.shader 50+ multi_compile YÜKSEK
Weather System 40+ farklı shader ORTA

06 Örnek: Grunge Shader

[Toggle] _Grunge_ON
[KeywordEnum(R,G,B)] _GrungeChannel
+ 50 adet multi_compile direktifi

Hesaplama:

2 × 3 × 250 = ?
6,755,399,441,055,744
Altı katrilyon yedi yüz elli beş trilyon üç yüz doksan dokuz milyar
dört yüz kırk bir milyon elli beş bin yedi yüz kırk dört variant
Pratik olarak SONSUZ variant!

Bu shader build patlamasına ve memory bloat'a neden olur. multi_compile → shader_feature_local'e dönüştürülmeli.

06 Shader'ın Gerçek Maliyeti

Ana projede yapılan URP/Lit shader stripping işlemi sonuçları:

8 GB
Stripping Öncesi RAM
1.5 GB
Stripping Sonrası RAM
18 saat
Stripping Öncesi Build
15 dk
Stripping Sonrası Build
%81
RAM Azalması
%98.6
Build Süresi Azalması
Bu stripping manuel yapıldı:
  • Tüm variant'lar tek tek not edildi
  • Sahnelerde gezilerek kullanılan variant'lar tespit edildi
  • Farklı kalite ayarlarına göre test edildi

Her eklediğiniz shader, development'a ekstra iş demek.

07 Pratik Araçlar

Frame Debugger

Window → Analysis → Frame Debugger

  • Her Draw Call'un sırası
  • Hangi shader/material kullanılıyor
  • Batch'lerin neden bozulduğu
  • Render state değişiklikleri

Shader Variant Sayısını Görme

  1. Shader asset'ini seç
  2. Inspector → "Compile and show code"
  3. "Show" → variant listesi

Profiler

Window → Analysis → Profiler → GPU

  • SetPass Calls: Shader değişim sayısı
  • Draw Calls: Toplam çizim komutları
  • Batches: Birleştirilmiş Draw Call
  • Triangles: Çizilen geometri

Build Log

Console'da "Compiling shader" satırlarını arayın.

08 Checklist

Shader Yazarken

  • multi_compile yerine shader_feature_local
  • Boolean sayısını minimize et
  • KeywordEnum seçeneklerini sınırla
  • SRP Batcher uyumluluğunu kontrol et

Material Oluştururken

  • Mümkünse mevcut material'i paylaş
  • Texture atlas kullan
  • MaterialPropertyBlock düşün

Sahne Optimizasyonu

  • Static objeleri işaretle
  • LOD Group kullan
  • Occlusion Culling bake et
  • Cast Shadows gereksizse kapat

Build Öncesi

  • Shader variant count kontrol et
  • Graphics Settings stripping ayarları
  • Kullanılmayan shader'ları kaldır

08 Özet

Konu Anahtar Nokta
GPU Çalışma Prensibi Paralel işlem, state değişimi maliyetli
Draw Call CPU→GPU komut maliyeti, batching ile azalt
Shader Variant Boolean sayısı = 2N variant, dikkatli ol
Material Sharing Aynı material = batch, farklı = ayrı Draw Call
Culling Frustum otomatik, Occlusion manuel setup

Altın Kural

GPU'ya mümkün olduğunca az "karar" verdirin.
Aynı shader, aynı material, aynı state = maksimum performans.

Sorular?

Teknik sorularınız için iletişime geçebilirsiniz.

Aygün ÖZGÜR
Space