2013-07-12 15 views
7

Używam FBO + RBO, i zamiast regularnego podwójnego buforowania na domyślnym buforze ramki, rysuję do RBO, a następnie blit bezpośrednio na buforze GL_FRONT domyślnego FBO (0) w pojedynczym zbuforowanym kontekście OpenGL.podwójne buforowanie z FBO + RBO i glFinish()

Jest w porządku i nie dostaję żadnego migotania, ale jeśli scena robi się nieco skomplikowana, doświadczam OGROMNEGO spadku fps, czegoś tak dziwnego, że wiedziałem, że coś musi być nie tak. I nie mam na myśli od 1/60 do 1/30 z powodu pominiętej synchronizacji, mam na myśli nagły spadek o 90%.

Próbowałem glFlush() po blit - bez różnicy, a następnie próbowałem glFinish() po blit, i miałem 10x fps doładowania.

Więc użyłem zwykłego buforowania doble na domyślnym buforze ramki i swapbufferach(), a fps również dostał boost, jak przy użyciu glFinish().

nie mogę dowiedzieć się, co się dzieje. Dlaczego glFinish() robi tak wielką różnicę, kiedy nie powinno? i czy można używać RBO i blit bezpośrednio na buforze frontowym, zamiast używać wywołania swapbuffers w kontekście podwójnego buforowania? Wiem, że Im brakuje vsync, ale menedżer kompozytowy i tak będzie synchronizować (w rzeczywistości nie widzę żadnego łzawienia), to tak, jakby monitor brakuje 9 na 10 klatek.

A tak z ciekawości, czy native swapbuffers() użyć glFinish() na Windows lub Linux?

+0

* "wtedy spróbowałem glFinish() po blicie, a miałem 10x fps boost" * - Raczej brzmi jak problem z twoją metodą pomiaru czasu, coś jak to nie jest zsynchronizowane dobrze z twoim GPU (który ' oczywiście glFinish). Jeszcze jeden kod byłby interesujący. –

+0

Nie widzę sposobu, w jaki reimplementacja podwójnego buforowania byłaby lepsza, biorąc pod uwagę wszystkie elementy w sterownikach takich jak potrójne buforowanie, adaptacyjny VSync i tak dalej. –

+0

@BartekBanachewicz Ma to sens, jeśli potrzebujesz bufora zarówno do renderowania na ekranie, jak i poza ekranem, ale naprawdę będziesz miał sporo pracy, aby (ponownie) zoptymalizować część ekranową. – KillianDS

Odpowiedz

1

wierzę, że jest to kwestia związana Sync.

Podczas renderowania bezpośrednio do RBO i blittingiem do bufora przodu, po prostu nie ma żadnej synchronizacji. Tak więc na złożonych scenach kolejka poleceń GPU zapełni się dość szybko, wtedy kolejka sterownika procesora również będzie się szybko wypełniała, dopóki synchronizacja procesora nie zostanie wymuszona przez sterownik podczas polecenia OpenGL. W tym momencie wątek procesora zostanie zatrzymany.

Chodzi mi o to, że bez jakiejkolwiek formy synchronizacji, złożone renderingi (renderingi, dla których jedno lub więcej poleceń OpenGL zostanie umieszczone w kolejce) zawsze spowodują zatrzymanie wątku CPU w pewnym momencie, ponieważ jako kolejki się wypełnią, procesor będzie wydawał coraz więcej poleceń.

Aby uzyskać płynną (bardziej stałą) interakcję użytkownika, potrzebna jest synchronizacja (z użyciem specyficznych dla platformy funkcji swapbuffers() lub glFinish()), aby zatrzymać procesor od robienia rzeczy pogarszających wydawanie coraz więcej polecenia (co z kolei mogłoby doprowadzić nitkę procesora do zatrzymania później)

referencyjny: OpenGL Synchronization

+0

Procesor wydający coraz więcej poleceń nie powinien pogarszać rzeczywgo renderowania, ale spowoduje, że procesor i GPU nie będą zsynchronizowane, a procesor mógłby myśleć, że renderował już 20 klatek, a GPU zakończyło tylko 1. Ale nie sądzę, by procesor publikujący wiele poleceń w kolejce miał tak duży wpływ na widoczną ilość klatek na sekundę (mierzoną ilość klatek na sekundę ...). Jednak to tylko odrobina intuicji, nie można tego teraz wypróbować :). – KillianDS

1

są to odrębne kwestie, które są tu również trochę podłączony.

1) Re-realizacja podwójnego buforowania siebie, podczas gdy na spec to samo, nie jest to samo dla kierowcy. Sterowniki są wysoce zoptymalizowane pod kątem wspólnego przypadku. Na przykład wiele żetonów ma odrębne jednostki 2d i 3d. Wymiana w swapBuffers jest często obsługiwana przez jednostkę 2d. Buforowanie prawdopodobnie nadal odbywa się za pomocą jednostki 3d.

2) glFlush (i wykończenie) są ignorowane przez wielu kierowców. Flush jest reliktem renderowania serwera klienta. Wykończenie było przeznaczone do profilowania. Ale zostało nadużyte, aby obejść błędy sterownika. Teraz kierowcy często ignorują go, aby poprawić wydajność starszego kodu, który został zastosowany jako rozwiązanie zastępcze.

3) Tylko nie rób pojedynczy buforowane. Nie ma korzyści z wydajności i pracujesz na "dobrej" ścieżce sterownika. Menedżery okien są superoptymalizowane pod kątem podwójnego buforowania OpenGL.

4) To, co widzisz, wygląda tak, jakbyś po prostu przeciekał zasoby. Czy alokujesz bufory, nie zwalniając ich? Szybkim i brudnym sposobem sprawdzenia jest, czy jakiekolwiek funkcje glGen * zwracają ciągle rosnące identyfikatory.