Bir dokuyu değiştirmek (üzerinde boyama) “durum değişikliği” olarak mı kabul edilir?


11

Grafiklerdeki kural, daha az durum değişikliği gerçekleştirmenin, daha fazla durum değişikliği (anahtarlayıcı gölgeler, bağlayıcı tamponlar, bağlayıcı dokular vb.) Gerçekleştirmekten daha iyi olmasıdır. Dokular için, çokgenleri tek bir atlas kullanarak (sprite / metin oluşturmak için) her çokgen için yeni bir doku tek tek bağlamaktan daha hızlıdır.

Sürekli olarak bir dokuya resim yapıyorsam bu doğru olur glTexSubImage2Dmu? Ben (bir ağ üzerinden) gelen işleme devam eden ve daha sonra bir kerede bir satır bir doku boyalı veri akışı var. Veriler sonsuz bir kaydırma ile görsel olarak sunulur.

Büyük bir dikdörtgenin üzerinde oluşturulan bir dokuya boyamaktan daha iyi olur muyum (boyalı verileri görünüme kaydırmak)? Buradaki fikir, boyamaya devam ederken herhangi bir zamanda bir (veya iki) dokuya sahip olacağım.

Yoksa çok sayıda küçük dikdörtgen boyamalı mıyım (sadece boyama yapılırken dikdörtgeni açığa çıkar)? Her dikdörtgen için bir doku bağlayacağımı varsayıyorum.

Yanıtlar:


11

Grafik aygıtındaki bir bellek alanını (doku, arabellek ve benzeri) güncellemek, oluşturma durumunu değiştirmekle aynı şey değildir.

Bir render durumu değişikliğini pahalı yapan şey, sürücünün yeni durumları doğrulamak ve boru hattını yeniden sıralamak için yapması gereken iş miktarıdır. Bu büyük olasılıkla CPU ve grafik cihazı arasında bir miktar senkronizasyona neden olacaktır. Ancak, durum değişikliği için aygıtlar arasında aktarılan veri miktarı az olmalıdır (muhtemelen sadece birkaç komut).

Öte yandan bir doku / tampon güncellemesi için ana maliyet veri aktarımının kendisinde yatmaktadır. Teorik olarak, güncelleme sonrasında doku verilerini CPU'ya geri okumadığınız sürece, senkronizasyon veya boru hattı durakları olmamalıdır. Ancak, başka bir husus da dikkate alınmalıdır: API yükü. Grafik aygıtına gönderdiğiniz veri miktarı az olsa bile, bunu yeterince sık yaparsanız, sonuçta sürücü / aygıtla iletişim maliyeti veri aktarım maliyetinden daha fazla olacaktır. Oluşturucuyu optimize ederken yığınlamanın bu kadar önemli olmasının bir başka nedeni de budur.

Yani sizin durumunuzda, en iyi yaklaşım, bana göre, her yeni veri geldiğinde güncellediğiniz dokunun sistem belleği kopyasını tutmak olacaktır. Kirli bir bayrak ayarlayın glTexSubImageve tüm doku (veya büyük bir ardışık kısmı) için mümkün olduğunca çok güncellemeyi birleştirin . Ayrıca, Pixel Buffer Objects ile oynayabilir ve boru hattı duraklarını mümkün olduğunca azaltmak için asenkron veri aktarımı yapmaya çalışabilirsiniz. Bir tür çift tamponlama uygulayabilirseniz, diğeri ile işlenirken dokunun bir kopyasına yazabilirsiniz. Bu eğitimbu senaryoyu inceler. Bu benim sezgisel yaklaşımım, API çağrılarının sayısını azaltmaya ve doku güncellemelerini "toplu" yapmaya çalışacağım. Bununla birlikte, bu çok spekülatiftir ve kullanım durumunuzda en yüksek performansın hangisi olduğundan emin olmak için bunu birkaç küçük güncelleme yapmak gibi diğer yaklaşımlarla karşılaştırmanız ve karşılaştırmanız gerekir.

Bir yan not olarak, NVidia'nın bu sunumu da alakalı ve birçok iyi fikir veriyor: OpenGL'de Sıfır Sürücü Yüküne Yaklaşma .


5
Kesin olarak bilmiyorum, ancak kesinlikle son karede veya iki işlemden geçirilen bir doku üzerinde glTexSubImage'ın boru hattını durduracağından şüphelenirim, çünkü PC sürücüleri genellikle bir veya iki çerçeveyi arabelleğe almaya çalışır ve olası değildir küçük bir güncelleme nedeniyle tüm dokuların kopyalarını çıkarmak istemektedir. Bu nedenle, maksimum performans için dokuların (veya piksel tampon nesnelerinin) çift veya üçlü tamponlama beklenmesi beklenir.
John Calsbeek
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.