Dlaczego OpenGL> = 3 zezwala tylko na VBO?

21

Widzę, że OpenGL w wersji 3 i wyższej eliminuje użycie renderowania po stronie klienta. Tryb natychmiastowy został wyeliminowany, a tablice wierzchołków wydają się przestarzałe. Zamiast tego, jeśli dobrze rozumiem, VBO są głównym sposobem renderowania wierzchołków.

Chociaż widzę logikę kryjącą się za jednolitym sposobem renderowania wszystkiego, to czy przypadkiem VBO nie mają poważnych wad w porównaniu z tablicami wierzchołków? Myślałem, że VBO powinny być dużymi buforami zawierającymi> 1 MB danych. Co jeśli mam scenę, która ma dużo mniejszą geometrię? Mam wykres sceny z dużą liczbą węzłów, z których każdy wymaga własnej transformacji itp. Każdy węzeł powinien mieć możliwość oddzielnego usuwania, dodawania do osobnych itp. Wcześniej używałem tablic wierzchołków. Moje pierwsze pytanie brzmi więc, czy jeśli przejdę na VBO, będzie więcej obciążeń dla obiektów wykresu sceny, ponieważ dla każdego obiektu należy przydzielić VBO.

Innym problemem jest to, że geometria, którą renderuję, może być bardzo dynamiczna. W najgorszym przypadku mogą zdarzyć się chwile, gdy cała geometria będzie musiała zostać ponownie wysłana do każdej klatki przez pewien okres czasu. Czy VBO będą miały gorszą wydajność niż tablice wierzchołków w tym przypadku użycia, czy też VBO w najgorszym przypadku wykonują tyle samo pracy, co tablice wierzchołków, ale nie więcej?

Tak więc, w bardziej zwięzłym formacie, moje pytania są następujące:

1) Czy istnieje znaczny narzut związany z przydzielaniem / zwalnianiem VBO (mam na myśli sam fakt utworzenia bufora)?

2) Jeśli aktualizuję dane z procesora w każdej ramce, czy może to być znacznie gorsze niż w przypadku użycia tablic wierzchołków?

Na koniec chciałbym wiedzieć:

3) Jeśli odpowiedź na którekolwiek z powyższych pytań brzmi „tak”, po co odrzucać inne tryby renderowania, które mogłyby mieć przewagę nad VBO? Czy czegoś mi brakuje, na przykład technik, które powinienem zastosować, aby zmniejszyć niektóre z tych potencjalnych kosztów alokacji itp.?

4) Czy odpowiedzi na którekolwiek z tych pytań ulegają zasadniczej zmianie w zależności od używanej wersji OpenGL? Jeśli zmienię kod mojego kodu na zgodny z OpenGL 3 lub 4, używając VBO w sposób, który jest wydajny, czy te same techniki będą działały dobrze w OpenGL 2, czy też jest prawdopodobne, że niektóre techniki są znacznie szybsze w OpenGL 3 + i inne z OpenGL 2?

Zadałem to pytanie na temat przepełnienia stosu, ale przesyłam ponownie tutaj, ponieważ zdałem sobie sprawę, że ta strona może być bardziej odpowiednia do mojego pytania.

Powaga
źródło
1
Po co głosować, aby zamknąć? Czy to dupek? Jeśli tak, czy mogę zobaczyć link, aby móc z niego skorzystać?
Grawitacja

Odpowiedzi:

23

Czy istnieje znaczny narzut związany z przydzielaniem / zwalnianiem VBO (mam na myśli sam fakt utworzenia bufora)?

Zdefiniuj „znaczny”. Na ogół mądrze jest nie tworzyć ich w środku ramek; należy je skonfigurować podczas inicjalizacji lub gdziekolwiek. Ale dotyczy to większości obiektów OpenGL, takich jak tekstury, bufory renderujące lub shadery.

Jeśli aktualizuję dane z procesora w każdej ramce, czy może to być znacznie gorsze niż w przypadku użycia tablic wierzchołków?

Czy to możliwe Tak. OpenGL definiuje funkcjonalność, a nie wydajność . Rzeczywiście można znacznie spowolnić. Lub możesz przyspieszyć. Wszystko zależy od tego, jak z niego korzystasz.

Wiki OpenGL ma dobry artykuł na temat prawidłowego przesyłania danych .

Jeśli odpowiedź na którekolwiek z powyższych pytań brzmi „tak”, po co tracić ważność w innych trybach renderowania, które mogłyby mieć przewagę nad VBO? Czy czegoś mi brakuje, na przykład technik, które powinienem zastosować, aby zmniejszyć niektóre z tych potencjalnych kosztów alokacji itp.?

Po pierwsze, nie były po prostu przestarzałe. Wycofanie oznacza oznaczenie czegoś jako „do usunięcia” w przyszłych wersjach. Zostały one przestarzałe w wersji 3.0 i usunięte w wersji 3.1 i wyższej.

Po drugie, ARB ogólnie wyjaśnił powód, dla którego usunęli rzeczy z OpenGL. To sprawia, że ​​specyfikacja jest mniejsza i prostsza. To sprawia, że ​​interfejs API jest mniejszy i bardziej usprawniony. Ułatwia to wiedzieć, jakich interfejsów API powinieneś używać; 2.1 miał 4 sposoby dostarczania danych wierzchołków; 3.1+ ma 1. Pozbywa się wielu cruft. Itp.

Czy odpowiedzi na którekolwiek z tych pytań zmieniają się znacznie w zależności od używanej wersji OpenGL? Jeśli zmienię kod mojego kodu na zgodny z OpenGL 3 lub 4, używając VBO w sposób, który jest wydajny, czy te same techniki będą działały dobrze w OpenGL 2, czy też jest prawdopodobne, że niektóre techniki są znacznie szybsze w OpenGL 3 + i inne z OpenGL 2?

Mniej więcej nie. Tylko w MacOSX różnica między wersją 3.1 + core i wersjami starszymi niż 3.0 naprawdę widocznie. Profil zgodności jest implementowany przez wszystkie sterowniki dla systemu Linux i Windows, więc można założyć, że profil podstawowy tych sterowników w rzeczywistości dodaje tylko kontrole, aby uniemożliwić wywoływanie funkcji zgodności.

W systemie Mac OSX 10.7 dostępny jest rdzeń GL 3.2, ale nie profil zgodności. To niekoniecznie znaczy nic dla technik wydajnościowych w porównaniu z innymi. Ale to oznacza, że ​​jeśli istnieją różnice, to na tej platformie je zobaczysz.

Nicol Bolas
źródło
1
Ponieważ właśnie opublikowałeś to pytanie , opublikuję swoją odpowiedź.
Nicol Bolas
Kolejną zaletą zachowania zwięzłości API jest to, że ułatwia implementację API OpenGL. To była duża uwaga w oryginalnej specyfikacji OpenGL ES.
notlesh
@stephelton: Ma sens. Moje pytanie „dlaczego przestarzałe wszystko oprócz VBO” opierało się na założeniu, że chociaż utrzymywanie interfejsu API w dobrej formie jest sensowne, nie ma sensu rezygnować z funkcji, które mogą być lepsze niż VBO w wielu przypadkach użycia. Z tego, co słyszę, wydaje się, że korzystanie z VBO nie ma żadnych wad, więc wtedy sensowne jest zaniechanie wszystkiego innego.
Gravity,
@gravity Nie musisz używać VBO. Możesz także użyć tablicy wierzchołków.
notlesh
18

Sposób, w jaki działa OpenGL, za każdym razem, gdy używasz danych spoza VBO, sterownik musi wykonać jego kopię - w praktyce tworzenie tymczasowego VBO - ponieważ nic nie powstrzymuje cię przed modyfikowaniem twoich pustych tablic przestrzeni użytkownika między wywołaniami do OpenGL.

Być może istnieją pewne sztuczki po stronie kierowcy, aby przyspieszyć przydzielanie tymczasowe, ale nie można nic zrobić, aby uniknąć kopiowania.

Tak, tak długo, jak ty - i twórcy sterowników - robisz wszystko dobrze, VBO powinny (tm) zawsze po prostu przyspieszać.

Jari Komppa
źródło
6
Bardziej podoba mi się ta odpowiedź. Jest krótszy i bardziej konkretny, imo.
TravisG
@JariKomppa: To brzmi jak bardzo rozsądne wytłumaczenie. Nadal mam jeden problem: VBO powinny być dość dużymi obiektami, często przydzielanymi jako bufory 1 MB - 4 MB podczas ostatniego sprawdzania. Co jeśli moje obiekty geometryczne nie są tak duże, ale nadal martwię się wydajnością, ponieważ mam wiele obiektów? Martwię się, że VBO mogą być przeznaczone do innego zastosowania niż to, co mam. Czy powinienem łączyć wiele obiektów razem w jednym VBO, a następnie używać glDrawRangeElementsdo rysowania każdego pojedynczego obiektu, czy jest to nieefektywne tak jak tablice wierzchołków?
Gravity,
Wątpię, czy to coś zmieni, ale jeśli uważasz, że to niepokój, sprawdź to.
Jari Komppa
@JariKomppa: W co wątpisz, że coś zmieni? Używasz glDrawRangeElementswiele razy na każdym VBO z kilkoma VBO, zamiast nadawać każdemu obiektowi własne VBO?
Gravity,
1
Dokładnie. Wątpię, czy zobaczysz tam dużą różnicę, ale profilowanie niektórych przypadków testowych powinno dać ci więcej informacji. Nie martwiłbym się tym teraz, ponieważ taka zmiana może być zastosowana później, jeśli zajdzie taka potrzeba.
Jari Komppa
9

a tablice wierzchołków wydają się przestarzałe. Zamiast tego, jeśli dobrze rozumiem,

Nie do końca. Tablice wierzchołków są podstawą obiektów buforów wierzchołków. Przeniesiono tylko pamięć z klienta na serwer.

Co jeśli mam scenę, która ma dużo mniejszą geometrię?

Scal mniejsze zestawy geometrii w większe VBO. Nie ma potrzeby posiadania jednego VBO na partię geometrii. Możesz doskonale adresować podzbiory VBO do renderowania. Użyj parametru nonzereo dla parametru gl… Wskaźnik danych.

2) Jeśli aktualizuję dane z procesora w każdej ramce, czy może to być znacznie gorsze niż w przypadku użycia tablic wierzchołków?

W tym celu dostępne są flagi użycia buforów GL_DYNAMIC_DRAW i GL_STREAM_DRAW.

Jeśli odpowiedź na którekolwiek z powyższych pytań brzmi „tak”, po co tracić ważność w innych trybach renderowania, które mogłyby mieć przewagę nad VBO?

Ponieważ nie ma żadnych zalet. Dane geometryczne należy w każdym przypadku przesłać do GPU. Używanie zwykłej tablicy wierzchołków po stronie klienta nadal spowoduje przeniesienie DMA do GPU, a tryb natychmiastowy zbuduje również partię do przeniesienia w pierwszej kolejności.

Nie ma absolutnie żadnej korzyści z nieużywania VBO.

datenwolf
źródło
Więc moja wydajność ogólnie nie powinna być gorsza z VBO niż z tablicami wierzchołków, ale tylko jeśli poprawnie ustawię tryb na GL_STREAM_DRAW?
Grawitacja
@Gravity: Rzeczywiście. Jednak tryb buforowania jest jedynie wskazówką dotyczącą oczekiwanego użycia, ale oczywiście ta wskazówka powinna być zgodna z tym, co zamierzasz zrobić. Nie zapominaj również, że możesz mapować bufory do przestrzeni adresowej procesu na potrzeby aktualizacji (glMapBuffer, glUnmapBuffer).
datenwolf
ale wtedy bufor nie może znajdować się w VRAM, prawda? A może nadal byłby w pamięci VRAM, ale można go adresować tylko za pomocą adresów w przestrzeni procesów? Czy przy tej technice losowy dostęp byłby tani, czy powinienem nadal aktualizować tylko niewielką liczbę ciągłych zakresów?
Grawitacja
@ Grawitacja: bufor można zmapować tylko do odczytu, tylko do zapisu lub do odczytu. W przypadku aktualizacji wybierz tylko zapis. Teraz ważne jest, aby wiedzieć, jak nowoczesny system operacyjny zarządza wirtualną przestrzenią adresową, a mianowicie za pomocą pamięci stronicowanej. W przypadku mapy tylko do zapisu mapowany jest fragment pamięci transferowej DMA, a zapisy do tego mapowanego zakresu trafią do pamięci GPU mniej więcej bezpośrednio (zawartość jest najpierw zapisywana w pamięci RAM procesora, a następnie przesyłana do GPU przez DMA transfer). Ważne jest, aby była to bardziej bezpośrednia ścieżka niż w przypadku, gdy dane przechodzą przez tablicę wierzchołków po stronie klienta: Zwykła pamięć procesów nie jest odpowiednia dla DMA
datenwolf