Nowości o produktach

Optymalizacja wydajności na Androidzie XR za pomocą Unity

6 minut czytania
Luke Hopkins
Inżynier ds. relacji z deweloperami, Android

Samsung Galaxy XR jest już dostępny, zasilany przez Androida XR. Ten post na blogu jest częścią tygodnia poświęconego Androidowi XR, w którym udostępniamy materiały – posty na blogu, filmy, przykłady kodu i inne – które pomogą Ci poznać Androida XR, tworzyć aplikacje na tę platformę i przygotować je do działania na niej.  

W tym tygodniu firma Samsung wprowadziła na rynek Galaxy XR, który powstał we współpracy z Google i Qualcomm. To ekscytujący czas dla deweloperów, dlatego chcemy Ci pomóc w uzyskaniu jak najlepszej wydajności aplikacji XR.

Słaba wydajność gier i aplikacji na urządzeniach innych niż XR może być frustrująca dla użytkownika, ale w świecie XR wydajność nie jest opcjonalna, lecz fundamentalna dla sukcesu aplikacji. Jeśli nie uda Ci się osiągnąć docelowej liczby klatek na sekundę w XR, może to spowodować znacznie poważniejsze problemy, takie jak choroba lokomocyjna. 

W tym przewodniku omówimy najważniejsze optymalizacje wydajności, które musisz znać, aby tworzyć aplikacje na Androida XR. Dowiesz się, które funkcje zapewniają największy wzrost wydajności, kiedy ich używać i jak współpracują ze sobą, aby pomóc Ci osiągnąć docelową liczbę klatek na sekundę.

Oto, do czego dążymy: 

  • Minimum: 72 kl./s (część naszych wskazówek dotyczących jakości odtwarzania)
  • Opcjonalnie: 90 kl./s z budżetem 11 ms na klatkę

Więcej informacji o tym, dlaczego ważne jest utrzymywanie tak wysokiej liczby klatek na sekundę, znajdziesz w naszych wskazówkach dotyczących wydajności.   

Funkcje wydajności specyficzne dla XR

Zacznijmy od omówienia 2 funkcji wydajności specyficznych dla XR: renderowania foveated i podpróbkowania Vulkan. 

Renderowanie foveated

Renderowanie foveated to optymalizacja, która ma 2 tryby. Pierwszy to tryb statyczny , który renderuje środek ekranu w wyższej rozdzielczości i stopniowo ją obniża, im dalej od środka patrzysz.

Drugi to tryb śledzenia wzroku , który renderuje w pełnej rozdzielczości obszar, na który patrzysz, a jednocześnie obniża jakość wyświetlaną na obrzeżach pola widzenia. Naśladuje on sposób, w jaki działa ludzki wzrok – widzimy szczegóły tylko w obszarze, na którym się skupiamy.

Renderowanie foveated znacznie zmniejsza obciążenie GPU bez pogorszenia postrzeganej przez użytkownika jakości obrazu. Zaletą renderowania foveated jest to, że użytkownicy nie zauważą obniżonej jakości w peryferyjnym polu widzenia, ale GPU z pewnością zauważy poprawę wydajności.

Wyobraź sobie, że tworzysz muzeum z misternymi artefaktami 3D. Bez renderowania foveated trudno byłoby utrzymać 90 kl./s podczas renderowania wszystkiego w polu widzenia. Dzięki renderowaniu foveated możesz zachować szczegóły o dużej liczbie wielokątów w miejscu, na które patrzy użytkownik, ale tło będzie renderowane w niższej jakości. Użytkownicy nie zauważą różnicy, ale Ty będziesz mieć więcej miejsca na dodanie szczegółów do sceny.

Podpróbkowanie Vulkan

Podpróbkowanie Vulkan to najlepszy przyjaciel renderowania foveated. Renderowanie foveated decyduje, co renderować na różnych poziomach jakości, a podpróbkowanie Vulkan obsługuje wydajne renderowanie na różnych poziomach jakości za pomocą map gęstości fragmentów.

W połączeniu z renderowaniem foveated podpróbkowanie Vulkan zapewnia dodatkowe 0, 5 ms wydajności. Pomaga też wygładzić poszarpane krawędzie w peryferyjnym polu widzenia, dzięki czemu obraz wygląda czyściej.

Na przykład w symulatorze lotu, w którym użytkownicy skupiają się na instrumentach i elementach sterujących, połączenie renderowania foveated z podpróbkowaniem Vulkan oznacza, że szczegółowe elementy sterujące są renderowane ostro, ale struktura kokpitu w peryferyjnym polu widzenia zużywa mniej zasobów. Dodatkowe 0,5 ms nie brzmi jak dużo, ale może to być różnica między miejscem na dodatkowy element interaktywny a spadkiem liczby klatek w intensywnych momentach.

Funkcje GPU dla złożonych scen

Oprócz renderowania foveated i podpróbkowania Vulkan istnieją też funkcje GPU, które zmniejszają niepotrzebne obciążenie dzięki inteligentnemu instancjonowaniu i wycinaniu. Są one szczególnie skuteczne w przypadku złożonych scen z powtarzającą się geometrią lub znacznym okluzją.

GPU Resident Drawer

GPU Resident Drawer automatycznie używa instancjonowania GPU, aby zmniejszyć liczbę wywołań rysowania i zwolnić czas przetwarzania procesora. Zamiast więc informować GPU o każdym obiekcie z osobna, procesor grupuje podobne obiekty.

Ta funkcja jest najbardziej skuteczna w przypadku dużych scen z powtarzającymi się siatkami, takimi jak drzewa w lesie, meble w biurowcu czy rekwizyty rozrzucone po całym otoczeniu.

Wyobraź sobie scenę leśną z 200 drzewami, które używają tej samej siatki bazowej. Bez GPU Resident Drawer masz 200 wywołań rysowania, które obciążają GPU, a tym samym zwalniają procesor. Gdy włączysz tę funkcję, GPU inteligentnie instancjonuje te drzewa, co powinno zmniejszyć liczbę wywołań rysowania do zaledwie 5–10. To ogromna oszczędność GPU, którą możesz wykorzystać na logikę rozgrywki lub obliczenia fizyczne.

GPU Occlusion Culling

GPU Occlusion Culling używa GPU zamiast procesora do identyfikowania i pomijania renderowania ukrytych obiektów. Automatycznie wykrywa, co jest zasłonięte (ukryte) za innymi obiektami, dzięki czemu nie marnujesz GPU na rzeczy, których użytkownik nie widzi.

Ta funkcja jest szczególnie przydatna w przypadku przestrzeni wewnętrznych z wieloma pomieszczeniami, gęstych środowisk lub scen architektonicznych, w których ściany, podłogi i obiekty naturalnie zasłaniają widok.

Załóżmy na przykład, że tworzysz dom z wieloma pomieszczeniami. Gdy użytkownik jest w salonie, po co marnować cykle GPU na renderowanie w pełni szczegółowej kuchni, która jest całkowicie ukryta za ścianą? GPU Occlusion Culling automatycznie pomija renderowanie tych ukrytych obiektów, dzięki czemu masz większy budżet wydajności na to, co jest faktycznie widoczne.

Monitorowanie skuteczności

Nie wystarczy tylko używać tych funkcji. Musisz też mierzyć optymalizacje, aby móc określić ich wpływ i sprawdzić, czy zmiany rzeczywiście działają.

Performance Metrics API

Interfejs Performance Metrics API umożliwia monitorowanie w czasie rzeczywistym wykorzystania pamięci, wydajności procesora i wydajności GPU przez aplikacje. Dostarcza kompleksowe dane z warstw kompozytora i środowiska wykonawczego, dzięki czemu możesz dokładnie zobaczyć, co dzieje się w aplikacji.

Przed wprowadzeniem zmian ustal punkt odniesienia, zastosuj optymalizację, zmierz jej wpływ i powtórz. Dzięki temu podejściu opartemu na danych wiesz , że rzeczywiście poprawiasz wydajność, a nie tylko zgadujesz.

Przed włączeniem renderowania foveated czas renderowania klatki GPU może wynosić 13 ms, czyli przekraczać budżet 11 ms. Włącz renderowanie foveated, zmierz ponownie i miejmy nadzieję, że czas klatki spadnie do 9 ms. To 4 ms dodatkowego czasu, które możesz wykorzystać na dodanie szczegółów do sceny, poprawę jakości obrazu w innych miejscach lub po prostu zapewnienie płynniejszej wydajności w szerszym zakresie treści.

Bez tych danych optymalizujesz na ślepo. Performance Metrics API mówi prawdę o tym, co rzeczywiście pomaga w Twoim konkretnym przypadku użycia.

Frame Debugger

Narzędzie Frame Debugger to wbudowane w Unity narzędzie, które pozwala dokładnie zrozumieć, jak renderowana jest scena, klatka po klatce. Pokazuje sekwencję wywołań rysowania i umożliwia ich przechodzenie, aby sprawdzić, czy optymalizacje działają prawidłowo.

Chcesz sprawdzić, czy SRP Batcher działa? W Frame Debugger poszukaj wpisów „RenderLoopNewBatcher”. Sprawdzasz, czy GPU Resident Drawer prawidłowo grupuje? Poszukaj wpisów „Hybrid Batch Group”. Te wizualne potwierdzenia pomogą Ci zrozumieć, czy ustawienia optymalizacji rzeczywiście działają.

Przejdź przez pierwsze 50 wywołań rysowania w scenie. Jeśli widzisz, że podobne obiekty są rysowane osobno zamiast w grupach, oznacza to, że instancjonowanie lub grupowanie nie działa prawidłowo. Frame Debugger natychmiast uwidacznia te problemy, dzięki czemu możesz je rozwiązać.

Dodatkowe optymalizacje

Oprócz optymalizacji omówionych powyżej nasz pełny przewodnik po wydajności zawiera też kilka innych dodatkowych optymalizacji. Oto krótkie podsumowanie:

  • Ustawienia URP: wyłącz HDR i przetwarzanie końcowe na potrzeby mobilnego XR. Te funkcje mają minimalny wpływ wizualny w porównaniu z kosztem wydajności na sprzęcie mobilnym, dlatego uzyskasz mierzalne korzyści w zakresie wydajności przy ledwo zauważalnych różnicach wizualnych.
  • SRP Batcher: zmniejsza obciążenie procesora w przypadku scen z wieloma materiałami, które używają tego samego wariantu shadera. Dzięki zminimalizowaniu zmian stanu renderowania między wywołaniami rysowania możesz znacznie skrócić czas procesora poświęcony na renderowanie.
  • Częstotliwość odświeżania wyświetlacza: dynamicznie dostosowuj częstotliwość odświeżania w zakresie od 72 do 90 kl./s w zależności od złożoności sceny. Zmniejsz liczbę klatek na sekundę podczas złożonych sekwencji, aby zachować stabilność, a następnie zwiększ ją w prostszych momentach, aby uzyskać płynną interakcję.
  • Tekstury głębi/nieprzezroczyste: wyłącz te tekstury, chyba że są one potrzebne do efektów shadera. Powodują one niepotrzebne operacje kopiowania GPU, które marnują wydajność bez korzyści dla większości aplikacji.
  • Skala renderowania URP: to ustawienie umożliwia renderowanie w obniżonej rozdzielczości w celu zwiększenia wydajności lub zwiększenie rozdzielczości w celu poprawy jakości obrazu.

Szczegółowe instrukcje dotyczące tych i innych optymalizacji znajdziesz w pełnym przewodniku po wydajności Unity na Androidzie XR.

Podsumowanie

Wydajność aplikacji XR to nie tylko techniczne pole wyboru. To różnica między wygodnym, wciągającym doświadczeniem a takim, które powoduje u użytkowników mdłości lub dyskomfort. Optymalizacje, które omówiliśmy, to zestaw narzędzi do osiągania krytycznych docelowych wartości liczby klatek na sekundę na najnowszych urządzeniach XR.

Oto plan działania:

  1. Zacznij od renderowania foveated i podpróbkowania Vulkan. Te funkcje specyficzne dla XR zapewniają natychmiastowe i zauważalne oszczędności GPU.
  2. Jeśli masz złożone sceny z powtarzającą się geometrią lub przestrzenie wewnętrzne, dodaj GPU Resident Drawer i Occlusion Culling.
  3. Monitoruj wszystko za pomocą Performance Metrics API, aby mieć pewność, że zmiany rzeczywiście pomagają.
  4. Poznaj dodatkowe optymalizacje URP, aby uzyskać dodatkowe miejsce na wydajność.

Konieczne jest ciągłe mierzenie i powtarzanie. Nie każda optymalizacja przyniesie takie same korzyści w każdym projekcie, dlatego użyj Performance Metrics API, aby uzyskać jasny obraz tego, co rzeczywiście pomaga w Twoim konkretnym przypadku użycia.

Co dalej: rozwijanie umiejętności

Chcesz dowiedzieć się więcej? Zapoznaj się z tymi materiałami:

  • Przewodnik po wydajności Unity na Androidzie XR – pełne instrukcje krok po kroku dotyczące implementacji wszystkich funkcji omówionych w tym artykule.
  • Pierwsze kroki z Unity i Androidem XR – skonfiguruj środowisko programistyczne i zacznij tworzyć.
  • Dokumentacja dla deweloperów Androida XR – obszerne przewodniki po wszystkich funkcjach Androida XR
Autor:

Czytaj dalej