Dlaczego obiekty buforów wierzchołków poprawiają wydajność?

10

Z mojego podstawowego zrozumienia, obiekt bufora wierzchołków działa mniej więcej tak (pseudo kod):

Zwykle, jeśli ktoś chce powiedzieć, narysować kwadrat, można wydać polecenia rysowania linii.

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

Używanie VBO, jeśli dobrze rozumiem, ładowałoby wierzchołki do VBO.

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

Następnie możesz wydać jedno polecenie rysowania.

draw VBO vertices

Chociaż rozumiem, jak działają VBO, nie wiem, dlaczego poprawiają wydajność.

Jak poprawiają wydajność?

Ethan Bierlein
źródło

Odpowiedzi:

11

Zasadniczo, gdy renderujesz obiekt w trybie natychmiastowym - na przykład wydając polecenia rysowania linii - budujesz serię poleceń, które przesyłasz na kartę graficzną w celu narysowania. Jeśli rysujesz dużo danych lub rysujesz bardzo często, możesz tracić dużo czasu na wysyłanie tych danych w kółko.

Bufor wierzchołków umożliwia utworzenie jednego obiektu, który zostanie przesłany na kartę graficzną jeden raz. Jeśli nie musisz zmieniać geometrii, możesz zostawić ją na karcie graficznej i po prostu wysłać kartę graficzną z prośbą o narysowanie tego obiektu. Ponieważ unika się kopiowania za każdym razem, gdy rysujesz, dla każdego losowania jest znacznie mniej kosztów ogólnych.

Zauważ, że użycie obiektu bufora wierzchołków nie zawsze zapewnia bardzo znaczące przyspieszenie. Jeśli rysujesz obiekt tylko raz na klatkę i zastępujesz geometrię między każdą klatką, nie zyskujesz korzyści z unikania kopiowania każdej klatki.

Większość mojego doświadczenia pochodzi z pisania programów przy użyciu graficznych interfejsów API, takich jak OpenGL, więc ktoś, kto ma problemy z zapleczem sterownika karty graficznej, może prawdopodobnie udzielić bardziej szczegółowej odpowiedzi, ale mam nadzieję, że to trochę wyjaśni.

porglezomp
źródło
10

Istnieją dwa kroki, dzięki którym VBO jest bardziej wydajny niż tryb natychmiastowy.

  1. Tryb natychmiastowy ( glBegin / glEnd , glVertex * itp.) Oznacza, że ​​w każdej ramce łyżką podajesz wierzchołki, atrybut według atrybutu (pozycja, normalny, kolor itp.), Do sterownika, który następnie formatuje je i ostatecznie wysyła cały pakiet jako polecenie dla GPU. To wiele wywołań funkcji na wierzchołek w każdej ramce.
    (Pamiętaj, że tryb natychmiastowy jest przestarzały od OpenGL 3.0 i został całkowicie usunięty z 3.2 .)

  2. Korzystając z tablic wierzchołków (patrz glDrawArrays , glDrawElements , glVertexPointer , itp.), Możesz nadać sterownikowi całą rzecz naraz i zaoszczędzić jej ciężaru ponownego formatowania wierzchołków. Skutecznie zastępujesz kilka wywołań funkcji na wierzchołek tylko garstką wywołań dla całej siatki. Ale nadal musisz to zrobić po kadrze.

  3. Obiekt bufora wierzchołków lub VBO (patrz glGenBuffers , glBindBuffer itp.) Idą o krok dalej i przechowują dane po stronie GPU: wysyłasz je tylko raz, a następnie odwołujesz się do niego za pomocą uchwytu. Oszczędzasz przepustowość, nie wysyłając ciągle tych samych danych w każdej ramce.

Julien Guertault
źródło
6

Korzystając z interfejsu trybu natychmiastowego (np. Stary styl OpenGL glBegin () / glEnd () / glVertex ()), skutecznie wyciskasz dane do sterownika po jednym kawałku. Następnie musi pobrać ten pojedynczy fragment danych, sformatować go i przekazać sprzętowi (co w dzisiejszych czasach oznacza umieszczenie go w buforze poleceń).

Używając obiektu bufora wierzchołków, zapewniasz (miejmy nadzieję) duży blok danych do sterownika przed tym, kiedy trzeba go użyć. Może przeprowadzać szereg optymalizacji (przeformatowanie, umieszczanie w pamięci wideo), a także nie musi podawać fragmentów GPU.

W praktyce, jeśli rysujesz tylko niewielką liczbę prymitywów, to prawdopodobnie nie zrobi to dużej różnicy, jednak jeśli rysujesz wielomilionową siatkę trójkątów, to VBO w pamięci wideo są dobrym rozwiązaniem.

Andrew Sidwell
źródło