piątek, 31 lipca 2009

Optymalizcja gemetrii ciąg dalszy

Ze względu na pewne wątpliwości odnośnie licencji dla NvTriStrip, zdecydowałem się poszukać innego rozwiązania.

Założyłem nawet temat na Warsztacie.

Ostatecznie zdecydowałem się na Vertex cache optimization librar.

Efekty działania są jak najbardziej zadowalające.

czwartek, 30 lipca 2009

Optymalizacja geometrii

Ponieważ wczytany model zmasakrował moją aplikację, postanowiłem zainteresować się tym jak go zoptymalizować.

Jak na razie postanowiłem sprawić, aby stał się bardziej "cache friendly". Wyjaśnię co to znaczy, bo okazało się, że kolega programista nie zrozumiał.

Otóż procesor graficzny GPU, ma wbudowaną pamięć tzw. vertex cache. Przechowuje w niej wyniki obliczeń dla ostatnich N wierzchołków. Kluczem do ponownego użycia już otrzymanych wyników jest użycie indeksowanej geometrii.

Warunkiem jest tu jednak, aby już obliczone wierzchołki nie "wypadły" z cache'u. Odpowiednia organizacja bufora indeksów nie jest zadaniem trywialnym, postanowiłem więc skorzystać z gotowca: biblioteka NvtriStrip. Do biblioteki jest przykład użycia: NVTriStrip Test App.





Coprzedpo
Ilość narysowanych obiektów:2867328673
Średni czas jednego draw call'a [ms]:0.06882970.0721264
Średni czas jednej klatki [ms]:13.757111.497
Ilość draw call'i na klatkę:88
Średni fps:68.399581.8658
Co z tego wynika ?
1) Relacja pomiędzy fps, a czasem renderowania klatki jest wyraźna. Czyli dobrze, bo to znaczy, że system nie spędza za dużo czasu poza samym renderingiem.
2) Draw call, o ile wiem jest wykonywany asynchronicznie. CPU nie czeka na jego zakończenie. Pomiary nijak się mają do czasu rysowania całej klatki. To też dobrze wróży, bo oznacza, że CPU ma lepsze rzeczy do roboty niż zlecanie kolejnych zadań do narysowania. Mam tu też pewien, spory jak sądzę, zapas mocy.
3) Zyskałem ~2.3 milisekundy. Co znaczy, że optymalizacja geometrii dała zysk rzędu 16 %. Jednak ta wartość jest zakłamana, ponieważ pixel shader do lekkich nie należy. Uruchomiłem aplikację w perfHud, ale za dużo nie udało mi się wyciągnąć sensownych informacji. Wiem tylko, że % VS z 40 spadł do 30. Niestety nie za bardzo wiem jak to dokładnie interpretować.
4) 1 + 2 + 3 moja grafika ledwo zipie ;)

środa, 29 lipca 2009

Instancing ciąg dalszy

Tak jak sądziłem przesunięcie analizy kolejki obiektów do wyrenderowania o jeden stopień wyżej poprawiło nieco osiągnięty wynik:
Ilość narysowanych obiektów: 28673 - 28673
Średni czas jednego draw call'a: 0.0054 ms - 0.00342 ms
Średni czas jednej klatki: 19.02 ms - 12.46 ms
Ilość draw call'i na klatkę: 8 - 8
Średni fps: 49.3 - 69.9

To dobrze. Chciałoby się podnieść ten etap jeszcze o jeden poziom wyżej, ale to chyba nie możliwe. Założenie jest takie, że dla każdego punktu obserwacji (kamery, światła) do kolejki trafią inne obiekty, więc ich wspólna analiza nie za bardzo wchodzi w grę.

Mój początkowy zachwyt nad tymi wynikami spotkał się dziś z lodowatym prysznicem :) Skończyłem pisać ładowanie plików ASE i zamieniłem sześcian na sześcian z wyciętym środkiem. Źródło inspiracji: ten projekt. Spodobał mi się, bo ten w sumie prosty model ma tę cechę, że rzuca cień sam na siebie. Model i render wykonany w blenderze przeze mnie:
Z Engine

Jak się jednak okazało, model wcale taki prosty nie jest. 97 trójkątów i 105 wierzchołków !!! Pewnie dałoby się to nieco poprawić, ale na drastyczne zmiany bym nie liczył. Tak czy siak, z 70 fps zrobiło się przerywane ~25 (trochę płynnie, trochę szarpie)

Literatura:
Opis formatu ASE
Plugin do blendera

środa, 22 lipca 2009

Instancing

Dziś udało mi się zakończyć kod odpowiedzialny za stosowanie instancing'u.
Scena złożona z 4096 klocków, oświetlona światłem punktowym z wyliczaną dynamicznie mapą cienia (cube).

Klasyczne podejście:
Ilość narysowanych obiektów: 28673
Średni czas jednego draw call'a: 0.0026 ms
Średni czas jednej klatki: 84.91 ms
Ilość draw call'i na klatkę: 28673
Średni fps: 11.33

Instancing:
Ilość narysowanych obiektów: 28673
Średni czas jednego draw call'a: 0.0054 ms
Średni czas jednej klatki: 19.02 ms
Ilość draw call'i na klatkę: 8 !!!
Średni fps: 49.3

No i tu pojawia się pytanie. 8 razy 0.005 to przecież 0.04 milisekundy, czemu więc klatka trwa 20 milisekund ? To jest bagatela 500 razy dłuższy czas ! Mam taką teorię: bufory z macierzami do transformacji świata są nie optymalnie tworzone i wysyłane do karty.

Czemu tak sądzę ?
1. Aktualizuje shadow mapę
1a. Wyznaczenie macierzy PV
1b. Analiza danych pod kątem batch'y
1c. Przygotowanie bufora z macierzami (macierze są już wyliczone, trzeba tylko je skopiować do bufora)
1d. Ustawienie wszystkiego związanego z shaderami
1e. Draw call
1f. Jeśli został jeszcze jakiś kierunek w cube mapie idź do 1a (czyli 6 razy)
2. Aktualizacja kamery
2a. To samo co dla światła, tylko, że mamy jeden kierunek i 4 mrt.
2b. Rysowanie świateł

Łącznie 7 razy analizuję i kopiuje te same dane do karty graficznej. Konieczne są jednak tylko 2 razy.

Pożyjemy zobaczymy, muszę to sprawdzić, ale upał jest tak nieznośny, że wszystkiego się odechciewa.

czwartek, 16 lipca 2009

Depresja

Dawno nic nie napisałem tutaj na blogu, także witam wszystkich po przerwie.

Co się działo przez ostatnie półtora miesiąca ? Mało. Mój projekt znajduje się w stanie "depresji", czyli nastąpiło ogólne zniechęcenie do jego kontynuacji. Poczucie niemocy jest wszechogarniające. Jedyne co mnie jako tako trzyma to fakt, że mi się śpieszy z jego ukończeniem (obrona mgr inż. , poszukiwanie pracy, ślub - wszystko to do Listopada)

Oto co robiłem przez ten czas:

Podstawy GUI napisane. Przyjąłem model a'la Java, czyli słuchacze - ang Listener, który otrzymuje wszystkie informacje o zmianach statusu powiązanego elementu. elementy mają swoje ID, dzięki temu jeden słuchacz może obsłużyć więcej niż jeden element danego typu. Jest i działa, ale dalsze prace nad tym modułem zostały zawieszone na bliżej nie określony czas.

Sporo zmian związanych z modelem danych. Zmieniłem dziedziczenie na kompozycję w kilku istotnych miejscach. Powstała klasa zasobów bez nazwy. Wprowadziłem materiały, zastąpiły one pomyłkę pod tytułem efekty pixel i vertex. W planach są jeszcze efekty post process. Zmieniłem tez nieco koncepcję samego renderingu. Wszystko to razem wymusiło niemal całkowite przepisanie renderera. Przy okazji wprowadziłem nieco rozsądniejszy mechanizm rysowania: "Batch! Batch! Batch!" ;)

Animacja szkieletowa i instancing. Aktualnie pracuje nad tym jak pożenić ze sobą te dwie technologie. Podstawy są już niemal na ukończeniu, potem poprawki do renderera, wykończenie loaderów dla plików md5 i ase.

A co robiłem dzisiaj ? Heh, znowu skracałem czas kompilacji, źródło inspiracji: Czasy kompilacji gier Zaoszczędziłem 12 sekund.