Jak rozwiązujemy duże wymagania dotyczące pamięci wideo w grze 2D?
Opracowujemy grę 2D (Factorio) w allegro C / C ++, a wraz ze wzrostem zawartości gry mamy problem z rosnącym zapotrzebowaniem na pamięć wideo.
Obecnie zbieramy wszystkie informacje o obrazach, które zostaną użyte jako pierwsze, przycinamy wszystkie te zdjęcia tak bardzo, jak to możliwe i organizujemy je w duże atlasy tak ściśle, jak to możliwe. Atlasy te są przechowywane w pamięci wideo, której rozmiar zależy od ograniczeń systemu; obecnie są to zwykle 2 obrazy o wielkości do 8192 x 8192, więc wymagają one pamięci wideo od 256 Mb do 512 Mb.
Ten system działa dla nas całkiem dobrze, ponieważ dzięki niektórym niestandardowym optymalizacjom i podzieleniu wątku renderowania i aktualizacji jesteśmy w stanie narysować dziesiątki tysięcy obrazów na ekranie przy 60 fps; mamy wiele obiektów na ekranie, a umożliwienie dużego oddalenia jest kluczowym wymogiem. Ponieważ chcielibyśmy dodać więcej, pojawią się pewne problemy z wymaganiami dotyczącymi pamięci wideo, więc ten system prawdopodobnie nie wytrzyma.
Jedną z rzeczy, które chcieliśmy wypróbować, jest posiadanie jednego atlasu z najczęstszymi obrazami, a drugiego jako pamięci podręcznej. Obrazy byłyby tam przenoszone z bitmapy pamięci na żądanie. Z tym podejściem wiążą się dwa problemy:
- Rysowanie z bitmapy pamięci do bitmapy wideo jest boleśnie powolne, w allegro.
- Nie jest możliwa praca z bitmapą wideo w innym wątku niż w allegro, więc jest praktycznie bezużyteczna.
Oto kilka dodatkowych wymagań, które mamy:
- Gra musi być determinacyjna, więc problemy z wydajnością / czasem ładowania nie mogą nigdy zmienić stanu gry.
- Gra odbywa się w czasie rzeczywistym, a wkrótce także w trybie wieloosobowym. Za wszelką cenę musimy unikać nawet najmniejszego jąkania.
- Większość gry to jeden ciągły otwarty świat.
Test polegał na narysowaniu 10 000 duszków w partii dla rozmiarów od 1x1 do 300 x 300, kilka razy dla każdej konfiguracji. Zrobiłem testy na Nvidii Geforce GTX 760.
- Bitmapa wideo do rysowania bitmapy wideo wymagało 0.1us na duszka, gdy źródłowa bitmapa nie zmieniała się pomiędzy poszczególnymi bitmapami (wariant atlasu); rozmiar nie miał znaczenia
- Bitmapa wideo na rysunek bitmapy wideo, podczas gdy źródłowa bitmapa była przełączana między rysunkami (wariant inny niż atlas), zajęła 0,56us na duszka; rozmiar też nie miał znaczenia.
- Bitmapa pamięci do rysowania bitmapy wideo była bardzo podejrzana. Rozmiary od 1x1 do 200x200 wymagały 0,3us na bitmapę, więc nie tak strasznie wolno. W przypadku większych rozmiarów czas zaczął gwałtownie rosnąć - od 9us dla 201x201 do 3116us dla 291x291.
Korzystanie z atlasu zwiększa wydajność o współczynnik większy niż 5. Gdybym miał 10 ms na renderowanie, w atlasie jestem ograniczony do 100 000 duszków na ramkę, a bez niego limit 20 000 duszków. Byłoby to problematyczne.
Próbowałem też znaleźć sposób na przetestowanie kompresji bitmapy i formatu bitmapy 1bpp dla cieni, ale nie byłem w stanie znaleźć sposobu na zrobienie tego w allegro.