Vertex Buffer Objects neden performansı geliştiriyor?


10

Temel anlayışımdan, bir Vertex Buffer Object böyle bir şey (sözde kod) çalışır:

Normalde biri kare çizmek isterse, çizgi çizme komutları verebilir.

line (0, 0) -> (1, 0)
line (1, 0) -> (1, 1)
line (1, 1) -> (0, 1)
line (0, 1) -> (0, 0)

Bir VBO kullanmak, doğru anlarsam, köşeleri bir VBO'ya yükler.

define VBO
load (0,0) -> VBO
load (1,0) -> VBO
load (1,1) -> VBO
load (0,1) -> VBO
load (0,0) -> VBO

Sonra bir çizim komutu verebilirsiniz.

draw VBO vertices

VBO'ların nasıl çalıştığını anlasam da, performansı neden geliştirdiklerini bilmiyorum.

Performansı nasıl geliştiriyorlar?

Yanıtlar:


11

Genel olarak, bir nesneyi (örneğin, çizgi çizme komutları veren) hemen bir modda oluşturduğunuzda, çizmek için grafik kartına gönderdiğiniz bir dizi komut oluşturursunuz. Çok fazla veri çiziyorsanız veya çok sık çiziyorsanız, bu verileri tekrar tekrar göndermek için çok zaman harcayabilirsiniz.

Tepe noktası arabelleği, grafik kartına bir kez gönderdiğiniz tek bir nesne oluşturmanıza olanak tanır. Geometrinizi değiştirmeniz gerekmiyorsa, grafik kartında bırakabilir ve grafik kartına bu nesneyi çizme isteği gönderebilirsiniz. Her çiziminizde kopyadan kaçındığından, her çizim için çok daha az ek yük vardır.

Bir köşe arabelleği nesnesinin kullanılmasının her zaman çok önemli bir hızlanma sağlamadığını unutmayın. Nesneyi kare başına yalnızca bir kez çiziyorsanız ve her karenin arasındaki geometriyi değiştiriyorsanız, her kareyi kopyalamaktan kaçınmanın avantajlarından yararlanamazsınız.

Deneyimlerimin çoğu, OpenGL gibi grafik API'leri kullanarak programlar yazmaktan geliyor, bu yüzden bir grafik sürücüsünün arka ucuyla uğraşan biri muhtemelen daha ayrıntılı bir cevap sağlayabilir, ancak umarım bu biraz daha açık hale getirir.


10

VBO'yu acil moddan daha verimli hale getiren iki adım vardır.

  1. Anında mod ( glBegin / glEnd , glVertex * , vb.), Her karede, sürücüye, köşeleri kaşıkla, öznitelik başına özniteliği (konum, normal, renk vb.) Beslediğiniz anlamına gelir ve daha sonra bunları yeniden biçimlendirir ve sonunda gönderir GPU'ya komut olarak tüm paketi. Her karede köşe başına bir çok işlev çağırır.
    ( Anında modun OpenGL 3.0'dan bu yana kaldırıldığını ve 3.2'den tamamen kaldırıldığını unutmayın .)

  2. Kullanarak köşe dizileri (bkz glDrawArrays , glDrawElements , glVertexPointer vb), Köşeleri yeniden biçimlendirme yükü tek seferde ve onunla tasarrufu sürücüye her şeyi verebilir. Köşe başına birkaç işlev çağrısını, tüm ağ için yalnızca bir avuç çağrı ile etkili bir şekilde değiştiriyorsunuz. Ama bunu yine de bir kez yapmalısın.

  3. Vertex Buffer Object veya VBO (bkz. GlGenBuffers , glBindBuffer , vb.) Bir adım daha ileri gider ve verileri GPU tarafında depolar: yalnızca bir kez gönderirsiniz ve sadece bir tutamaçla başvurursunuz. Her karede aynı verileri tekrar tekrar göndermeyerek bant genişliğinden tasarruf edersiniz.


6

Anında mod arabirimi kullanarak (örn. Eski stil OpenGL glBegin () / glEnd () / glVertex ()), sürücüye her seferinde bir veriyi etkili bir şekilde damlatıyorsunuz. Daha sonra bu tek veri parçasını almalı, yeniden biçimlendirmeli ve donanıma aktarmalıdır (bu günlerde bir komut arabelleğine koymak anlamına gelir).

Bir köşe arabelleği nesnesi kullanarak, sürücüye kullanılması gerektiğinde (umarım) büyük bir veri bloğu sağlarsınız. GPU parça parça beslemek zorunda kalmanın yanı sıra bir dizi optimizasyon (yeniden biçimlendirme, video belleğine yerleştirme) gerçekleştirebilir.

Pratikte sadece az sayıda ilkel çiziyorsanız, muhtemelen çok fazla fark yaratmayacaktır, ancak multi-milyon üçgen örgü çiziyorsanız, video belleğindeki VBO'lar gitmenin yoludur.

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.