Bu geometri gölgelendirici neden programımı çok yavaşlatıyor?


27

Bir OpenGL programım var ve bir arazi ağı oluşturuyorum. Köşe arabelleğindeki köşeleri yerinden oynatıyorum ve onları henüz parça gölgelendiricisinde renklendirmiyorum. Her seferinde bir parça bir geometri gölgelendirici ekliyorum.

Geometri gölgelendiricisini eklemeden önce, sadece boru hattının parça ve tepe gölgelendirme adımlarını programlarken, yaklaşık 30+ kare hızına sahip oluyordum. Yeterince herhangi bir kırılma fark edemedim. Geometri gölgelendiricisini ekledikten sonra saniyede yaklaşık 5 kare alıyorum. Niye ya? Bu, geometri gölgelendiricinin tamamıdır:

#version 420

layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

void main()
{
    for (int i = 0; i < gl_in.length(); i++)
    {
        gl_Position = gl_in[i].gl_Position;
        EmitVertex();
    }
    EndPrimitive();
}

Bu tam olarak OpenGL'nin geometri gölgelendiricisi olmadan yaptığı şey değil miydi?

Yanıtlar:


40

Bu tam olarak OpenGL'nin geometri gölgelendiricisi olmadan yaptığı şey değil miydi?

Hayır değil. GS isteğe bağlı bir adımdır, varsayılan olan bir adım değildir.

OpenGL'nin bir geometri gölgelendiricisi kullanması için " ilkel montaj " olarak bilinen şeyi yapması gerekir . Üzerinden bir dizi üçgen oluşturduğunuzda GL_TRIANGLE_STRIP, OpenGL bitişik her 3 köşeyi ayrı bir üçgene dönüştürmek için içsel şeyler yapar ve sarım sırasını uygun şekilde değiştirir.

Normal olarak, bir GS kullanılmadığında, bu işlem bir kez gerçekleştirilir. Ancak bir GS kullandığınızda, GS çalıştırılmadan önce gerçekleştirilmesi gerekir. Ancak bir GS tamamen farklı bir ilkel tip (ör. Dörtlü) verebildiğinden GS'den sonra da gerçekleştirilmelidir .

Şimdi, sistemi temelde bir hiç için fazladan bir sürü ek iş yapıyorsunuz. Sonuçta, OpenGL olamaz varsayalım sizin GS şey (yani bir karar verilemeyen bir problem var) yaptığını.

Ayrıca, bir dizi optimizasyon artık GS varlığında çalışmaz. Dizin oluşturulmuş işleme almayı düşünün.

Bir eleman dizisi arabelleğindeki her bir dizin, bir köşe gölgelendiriciden aynı çıktıları üretecektir. Bu yüzden GPU bu çıkışları sık sık bir T&L önbelleğinde önbelleğe alır . Zaten önbellekte olan bir dizin görürse, VS tekrar çalışmaz; sadece önbellekten veri alır.

Bu ne"? "Bu" ... ilkel montaj birimi . Evet, GS kullandığında iki kez akan şey. Dizin önbellekleme şeyler? Sadece GS girişleri için çalışır .

Öyleyse GS'nin çıktılarına ne olacak? Bu donanıma bağlı. Ancak bir çeşit hafıza tamponuna girmek zorunda. Ve orada sorun var: bu tampon hiç endeksli değil. Bir glDrawArrays durumu gibi.

Bu nedenle, bir dizin arabelleği gönderirseniz 0, 1, 2, 0, 2, 3, bu işlem T ve L önbelleğinde 4 köşeye çevrilir. Ancak GS sonrası köşelerin köşeleri şimdi 6 köşeye sahiptir. GS sonrası arabellek daha fazla alan kullanır. Eğer düzgün bir şekilde post-T ve L optimizasyonlu üçgen listeleri veya şeritleri yapma sıkıntısını yaşarsanız ve sizinki gibi bir geçişli GS'yi çevirirseniz, performansınızın yarısını bu optimizasyondan kazanmış olursunuz.

İşe yaramaz değildi, ama acıtıyor.

Buna ek olarak, birçok GL 3.x sınıfı GPU'nun (aka: DX10) GS sonrası tamponları oldukça küçük olduğu gerçeğidir. Tampon ne kadar küçükse, eşzamanlı olarak aktif olabileceğiniz GS kontrolleri o kadar az olacaktır. Böylece donanımınız GS üzerinde etkili bir şekilde tıkanıyor. Çünkü Mozaik 4.x sınıf donanım büyük bir özelliktir, bu tür pek çok donanım ağır GS canlı kullanmak için yeterli tampon vardır.

Bu nedenle, bir GS kullanmak, kod vertex işlemlerinizi darboğaz yapmak için daha olasıdır. Tabii ki, köşe ve parça gölgelendiricilerinizi daha karmaşık hale getirerek her zaman bu avantajı kullanabilirsiniz, çünkü bu noktada sadece ücretsiz performans.

GS kaynaklı yavaşlamalar hakkında daha fazla bilgi için bu makaleyi okuyun .

İşte GS'lerin temel bir kuralı: GS'yi asla kullanmayın çünkü gösterimi daha hızlı hale getireceğini düşünüyorsunuz . Yapmaya çalıştığınız şeyi mümkün kılarken kullanmalısınız. Yapmaya çalıştığınız şey bir optimizasyon ise, başka bir şey kullanın.

Bunun genel istisnaları:


Her poligonun dikliğini en yüksek yüksekliğini alarak ve en düşük yüksekliğini çıkartarak hesaplamaya çalışıyorum. Bununla birlikte, bir geometri gölgelendirici beni mutlaka bu miktarda yavaşlatırsa, vertex gölgelendiricisinde yaratıcı bir şekilde yapabileceğimi düşünüyorum.
Avi

1
@Avi, bir üçgenin en yüksek ve en düşük noktalarının size dikliğini vermeyeceğini unutmayın; Üç noktaya da ihtiyacın var.
sam hocevar,

2
Şahsen ben her zaman nokta sprite için GS'den daha yararlı olduğunu buldum.
Maximus Minimus

1
Sprite sprite istisnası, gölgelendiricilere genelleştiriliyor layout(points) in;mu? Yoksa sabit çıktı boyutu mu? Ya da belki her ikisi de?
Philip
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.