Omówienie
Godot Engine to popularny wieloplatformowy silnik gier typu open source, który zapewnia solidne wsparcie dla Androida. Godot może służyć do tworzenia gier praktycznie dowolnego gatunku. Umożliwia tworzenie grafiki 2D i 3D. Wersja 4 Godota wprowadziła nowy system renderowania z zaawansowanymi funkcjami do tworzenia grafiki o wysokiej jakości. Renderer Godot 4 jest przeznaczony do obsługi nowoczesnych interfejsów API grafiki, takich jak Vulkan.
Fundacja Godot zatrudniła ekspertów od optymalizacji grafiki z firmy The Forge Interactive i współpracowała z Google, aby przeanalizować i jeszcze bardziej udoskonalić renderer Godot 4 Vulkan oraz scalić te optymalizacje z repozitorium projektu. Optymalizacje te pomagają deweloperom ulepszać niestandardowe renderery Vulkan na Androidzie.
Metodologia i wyniki optymalizacji
W procesie optymalizacji jako obiektów odniesienia użyto 2 różne sceny 3D w Godot. Czas renderowania scen był mierzony na wielu urządzeniach podczas każdej iteracji optymalizacji. Aby kwalifikować się do uwzględnienia, zmiany w renderowaniu muszą przynosić poprawę wydajności na co najmniej niektórych testowanych urządzeniach i nie mogą powodować pogorszenia wydajności na żadnym urządzeniu.
W testach wykorzystano kilka popularnych architektur GPU na Androida. Wiele optymalizacji przyniosło ogólne ulepszenia, ale niektóre miały większy wpływ na konkretne architektury GPU. Łączna suma wszystkich działań optymalizacyjnych spowodowała ogólne skrócenie czasu renderowania klatek przez GPU o 10–20%.
Ogólna optymalizacja Vulkan
Zespół Forge przeprowadził ogólne przeprojektowanie architektury backendu do renderowania Godot Vulkan, aby zwiększyć wydajność i pomóc backendowi skalować się w związku ze zwiększonym zapotrzebowaniem na renderowanie treści. Optymalizacje te nie dotyczą tylko sprzętu mobilnego, ale przynoszą korzyści wszystkim platformom Godot Vulkan.
Obsługa dynamicznego przesunięcia UBO
Podczas wiązania zbioru deskryptorów zawierającego dynamiczny obiekt jednolity (UBO) Vulkan umożliwia określenie dynamicznych przesunięć w UBO w parametrach wiązania. Ta funkcja umożliwia pakowanie danych dla wielu operacji renderowania do pojedynczego UBO i ponownie wiązanie zbioru deskryptorów za pomocą innego przesunięcia dynamicznego, aby wybrać odpowiednie dane dla shadera. Renderer Godot Vulkan został zaktualizowany, aby umożliwić używanie przesunięć dynamicznych zamiast zawsze inicjowania przesunięcia na zero. Ta poprawka umożliwi w przyszłości optymalizację wydajności.
Zbiory zbiorów opisów linearnych
Wcześniej domyślne zachowanie w renderze Godot Vulkan polegało na tworzeniu wszystkich puli zbiorów deskryptorów za pomocą flagi VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT
, co oznacza, że przydzielenia zbiorów deskryptorów mogły zostać zwolnione z powrotem do puli, a z tej puli mogły być wykonywane rzeczywiste przydzielenia. Ten tryb wymagał dodatkowego nakładu pracy w porównaniu z basenami zbiorów opisów, które umożliwiają tylko przydzielanie liniowe, a następnie całkowite resetowanie puli.
W miarę możliwości zbiory zbiorów deskryptorów są teraz tworzone jako zbiory liniowe bez ustawienia VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT
. W razie potrzeby w przypadku puli liniowych można je zresetować jako całość. Ta praca obejmuje też dodatkową optymalizację do łączenia zbiorczego zestawu wiązań deskryptorów, jeśli to możliwe, co zmniejsza liczbę oddzielnych wywołań do vkCmdBindDescriptorSets()
.
Obsługa stałego próbkowania
Obiekty samplera, które zawierają dane konfiguracji próbkowania, są tradycyjnie powiązane jako część danych zbioru deskryptorów. Ta metoda umożliwia dynamiczną wymianę obiektów samplera w danych zbioru deskryptorów. Vulkan obsługuje też niezmienne próbki, które kodują dane próbki bezpośrednio w układzie zbioru deskryptorów. Konfiguracja próbnika jest powiązana podczas tworzenia zestawu deskryptorów i stanu potoku i nie można jej zmienić po utworzeniu.
Niezmiennicze próbki są mniej elastyczne, ale nie trzeba już zarządzać i wiązać pojedynczych obiektów próbek. Renderer Godot Vulkan został zaktualizowany, aby obsługiwać niezmienne próbkowanie; w praktycznych przypadkach zmieniono sposób korzystania z próbkowania, aby używać niezmiennych próbkowników.
Optymalizacja pod kątem urządzeń mobilnych
Wprowadziliśmy dodatkowe optymalizacje, aby poprawić wydajność renderowania na sprzęcie graficznym urządzeń mobilnych. Z powodu odmiennej architektury optymalizacje nie są na ogół istotne w przypadku kart graficznych klasy desktop.
Optymalizacje obejmują:
- Zastąp użycie dużych stałych wartości przesyłania
- Przydzielanie bufora w trybie leniwym
- Obsługa stałego bufora
- Zmiana trybu dekodowania ASTC
- Obrót ekranu przed rozpoczęciem
Zastępowanie dużych stałych wartości w push
Stale push to funkcja, która umożliwia wstrzyknięcie stałych wartości do aktywnego programu cieniowania do bufora poleceń. Stałe parametry push są wygodne, ponieważ nie wymagają tworzenia ani wypełniania bufora i nie są powiązane z deskryptorami. Stale push mają jednak ograniczony maksymalny rozmiar i mogą negatywnie wpływać na wydajność sprzętu mobilnego.
Podczas testowania na urządzeniach z Androidem udało się poprawić wydajność, zastępując stałe korzystanie z push-notyfikacji o długości większej niż 16 bajtów przez stałe bufory. Cienie, które używały 16 bajtów lub mniej danych stałych, działały wydajniej z wykorzystaniem stałych przesyłanych. Oprócz kwestii związanych z wydajnością niektóre karty graficzne mają minimalne wyrównanie 64-bajtowe dla jednolitych buforów, co zmniejsza efektywność wykorzystania pamięci z powodu nieużywanych wypełnień w porównaniu z wykorzystywaniem stałych przesunięć.
Leniwe przydzielanie bufora
Większość urządzeń mobilnych z grafiką wykorzystuje architekturę opóźnionego renderowania na kafelkach (TBDR). GPU korzystające z TBDR dzielą większy obszar ekranu na siatkę mniejszych kafelków i renderują je pojedynczo. Każda kafelka jest obsługiwana przez niewielką ilość pamięci RAM o wysokiej szybkości, która jest używana przez GPU do przechowywania podczas renderowania. Dzięki TBDR cele renderowania, które nigdy nie są próbkowane przez inny cel, poza ich przetwarzaniem mogą pozostać całkowicie w pamięci RAM płytki i nie wymagają bufora dla głównego magazynu pamięci.
VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
został dodany podczas tworzenia odpowiednich celów renderowania, takich jak główne cele koloru i głębi, aby uniknąć przydzielenia pamięci podręcznej, która nigdy nie zostanie użyta. W przypadku przykładowych scen oszczędność pamięci dzięki nieaktywnym przydziałom wyniosła nawet około 50 MB pamięci RAM.
Obsługa stałego bufora
Sprzęt mobilny korzysta z jednolitej architektury pamięci (UMA) zamiast rozróżniania pamięci RAM głównej i pamięci RAM graficznej. Gdy główna pamięć RAM i pamięć RAM karty graficznej są oddzielne, dane muszą zostać przeniesione z głównej pamięci RAM do pamięci RAM karty graficznej, aby mogły być używane przez procesor graficzny. Godot już teraz wdraża ten proces transferu w swoim mechanizmie renderowania Vulkan za pomocą buforów stagingowych. Na sprzęcie UMA bufor pośredni jest niepotrzebny w przypadku wielu typów danych; pamięci mogą używać zarówno procesor,jak i GPU. W Forge wprowadziliśmy obsługę trwałych współdzielonych buforów na obsługiwanym sprzęcie, aby w miarę możliwości wyeliminować etap pośredni.
Zmiana trybu dekodowania ASTC
Adaptive Scalable Texture Compression (ASTC) to preferowany nowoczesny format kompresji tekstur na sprzęcie mobilnym. Podczas dekompresji GPU może domyślnie dekodować texels do wartości pośredniej o większej precyzji niż wymagana do zachowania wierności wizualnej, co powoduje utratę wydajności teksturowania. Jeśli jest obsługiwana przez sprzęt docelowy, rozszerzenie VK_EXT_astc_decode_mode
służy do określania 8-bitowych wartości beznormalizowanych na komponent podczas dekodowania zamiast 16-bitowych wartości zmiennoprzecinkowych.
Obrót ekranu przed rozpoczęciem
Aby zapewnić optymalną wydajność podczas korzystania z Vulkana na Androidzie, gry muszą dopasowywać orientację ekranu urządzenia do orientacji powierzchni renderowania. Ten proces nazywa się przedrotacją. Niewykonanie tej czynności może spowodować obniżenie wydajności, ponieważ system operacyjny Android musi dodać kompozytor, aby ręcznie obrócić obrazy. Do renderowania Godot dodano obsługę prerotacji na Androidzie.
Ulepszenia debugowania
Oprócz optymalizacji wydajności The Forge ulepszył proces debugowania problemów z grafiką w renderze Godot, wprowadzając te zmiany:
- Rozszerzenie dotyczące awarii urządzenia
- Menu nawigacyjne
- znaczniki debugowania,
Rozszerzenie dotyczące awarii urządzenia
Gdy podczas operacji renderowania GPU napotka problem, sterownik Vulkan może zwrócić wynik VK_ERROR_DEVICE_LOST
z wywołania interfejsu Vulkan API. Domyślnie nie są podawane żadne dodatkowe informacje kontekstowe dotyczące tego, dlaczego kierowca wrócił.
VK_ERROR_DEVICE_LOST
Rozszerzenie VK_EXT_device_fault
udostępnia mechanizm, dzięki któremu kierowca może podać dodatkowe informacje o charakterze błędu. Dodano obsługę rozszerzenia o błędy urządzenia (jeśli jest dostępne) i raportowania informacji zwracanych przez sterownik.
Menu nawigacyjne
Awaria karty graficznej lub zatrzymanie wykonania może być trudne do debugowania. Aby ułatwić identyfikację treści graficznych, które mogły zostać wyrenderowane w momencie wystąpienia błędu, dodający do renderowania Godot obsługę elementów menu nawigacyjnego. Ścieżka to zdefiniowana przez użytkownika wartość, którą można dołączyć do treści na listach rysowania w grafu renderowania. Dane ścieżki przekątnej są zapisywane przed rozpoczęciem nowego przejścia renderowania. Jeśli wystąpi błąd lub zawieszenie wykonania, bieżąca wartość ścieżki może posłużyć do określenia, które dane mogły spowodować problem.
znaczniki debugowania,
Jeśli są obsługiwane przez sterownik, znaczniki debugowania służą do nazywania zasobów. Umożliwia to tworzenie powiązań między ciągami tekstowymi czytelnymi dla użytkownika a operacjami takimi jak renderowanie przejść i zasobami takimi jak bufory i tekstury podczas korzystania z narzędzia graficznego, np. RenderDoc. Do renderera Godot Vulkan dodano obsługę adnotacji znacznika debugowania.
Dodatkowe linki
Blog Godot Engine – informacje o współpracy z Google i The Forge
Prośba o przejęcie kodu dotycząca współpracy z Godot Engine Vulkan