Mechanizmy natywne i zastrzeżone

Wprowadzenie do Vulkana na Androidzie

Vulkan to podstawowy interfejs API grafiki niskiego poziomu na Androidzie. Vulkan zapewnia optymalną wydajność w grach, które implementują własny silnik gry i mechanizm renderowania.

Aby prawidłowo zaimplementować Vulkana w silniku gry, musisz:

  • określić, które urządzenia z Androidem będą używać Vulkana;
  • zrozumieć kompromisy związane z obsługą starszych urządzeń z Androidem;
  • dodać Vulkana do docelowej wersji Androida;
  • wybrać kompilator cieniowania, aby utworzyć SPIR-V dla Vulkana;
  • określić dostępną wersję interfejsu Vulkan API w czasie działania;
  • dowiedzieć się, jak zoptymalizować operacje renderowania w Vulkanie za pomocą profili Vulkana, tempa klatek i wstępnego obrotu;
  • wybrać narzędzia graficzne do debugowania i analizy wydajności.
    Uwaga: informacje o używaniu Vulkana na Androidzie z silnikami gier Unity lub Unreal znajdziesz w tych artykułach:
  • Vulkan w Unity
  • Vulkan w Unreal

Wybieranie minimalnych specyfikacji urządzenia dla Vulkana

Vulkan jest dostępny na Androidzie od wersji 7.0 (poziom 24 interfejsu API). Nie wszystkie urządzenia z Androidem w wersji 7.0 lub nowszej obsługują Vulkana. Musisz określić, które urządzenia z Androidem obsługujące Vulkana są obsługiwane przez Twoją grę.

Rekomendacje

Użyj tych specyfikacji jako minimalnych wymagań dotyczących obsługi Vulkana:

  • Urządzenie ma Androida w wersji 10.0 (poziom 29 interfejsu API) lub nowszej.
  • Urządzenie obsługuje interfejs Vulkan API w wersji 1.1 lub nowszej.
  • Urządzenie ma funkcje sprzętowe zgodne z profilem Android Baseline 2022 .

Obsługa starszych urządzeń

Jeśli Twoja gra jest przeznaczona do działania na wielu urządzeniach o różnym poziomie możliwości graficznych , może być konieczne obsługiwanie urządzeń starszych niż te , które są zalecane w sekcji Wybieranie minimalnych specyfikacji urządzenia dla Vulkana. Zanim zaczniesz obsługiwać starsze urządzenia, sprawdź, czy Vulkan przyniesie Twojej grze korzyści. W przypadku gier, które mają wiele wywołań rysowania i używają OpenGL ES, może wystąpić znaczny narzut sterownika ze względu na wysoki koszt wywołań rysowania w OpenGL ES. Te gry mogą być ograniczone przez procesor, ponieważ dużą część czasu renderowania klatek spędzają w sterowniku graficznym. Przełączenie się z OpenGL ES na Vulkana może też znacznie zmniejszyć zużycie procesora i energii. Dotyczy to zwłaszcza gier ze złożonymi scenami, które nie mogą skutecznie wykorzystywać instancjonowania do zmniejszenia liczby wywołań rysowania. W przypadku starszych urządzeń dodaj obsługę renderowania OpenGL ES jako rezerwę, ponieważ niektóre urządzenia na liście urządzeń docelowych mogą mieć implementacje Vulkana, które nie będą w stanie niezawodnie uruchomić Twojej gry.

Możesz nie chcieć obsługiwać starszych urządzeń obsługujących Vulkana, ponieważ mają one niską wydajność i niewiele funkcji lub występują na nich problemy ze stabilnością.

Wydajność i funkcje

Starsze urządzenia z Androidem obsługujące Vulkana mogą nie mieć wydajności renderowania ani obsługi sprzętowej funkcji potrzebnych do uruchomienia Twojej gry. Jest to szczególnie prawdopodobne, jeśli Twoja gra ma grafikę wysokiej jakości, a Vulkan jest jedynym interfejsem API, na którym się skupiasz na Androidzie. Wiele starszych urządzeń jest ograniczonych do wersji 1.0.3 interfejsu Vulkan API i często brakuje im powszechnie używanych rozszerzeń Vulkana dostępnych na nowocześniejszym sprzęcie.

Stabilność

Starsze urządzenia z Androidem mogą używać nieaktualnych sterowników Vulkana. Te wersje sterowników mogą zawierać błędy, które mogą wpływać na stabilność Twojej gry. Omijanie błędów sterowników może wymagać znacznej ilości czasu na testowanie i inżynierię.

Dodawanie Vulkana do projektu

Aby dodać Vulkana do projektu, musisz:

  • dołączyć nagłówki interfejsu Vulkan API;
  • skompilować kod cieniowania do SPIR-V;
  • wywołać interfejs Vulkan API w czasie działania.

Dołączanie nagłówków interfejsu Vulkan API

Aby skompilować kod, który używa Vulkana, gra musi zawierać pliki nagłówkowe interfejsu Vulkan API. Kopię nagłówków Vulkana znajdziesz w Android NDK lub w pakiecie SDK Vulkana. Każda wersja NDK zawiera tylko nagłówki Vulkana dostępne w momencie wydania NDK. Jeśli używasz nagłówków Vulkana z NDK, użyj NDK w wersji 25 lub nowszej, która zawiera pliki nagłówkowe obsługujące Vulkana w wersji 1.3. Pakiet SDK Vulkana zawiera najnowszą wersję nagłówków.

Kompilowanie kodu cieniowania do SPIR-V

Interfejs Vulkan API oczekuje, że programy cieniowania będą dostarczane w binarnym formacie pośrednim SPIR-V. Ta konwencja różni się od OpenGL ES, gdzie można było przesyłać kod źródłowy napisany w języku OpenGL Shading Language (GLSL) jako ciągi tekstowe. Użyj kompilatora cieniowania, aby przekształcić kod napisany w języku cieniowania , takim jak GLSL lub High-level Shader Language (HLSL) , i skompilować go do modułów SPIR-V do użycia z Vulkanem.

Kompilator shaderc może służyć do kompilowania programów cieniowania napisanych w GLSL do SPIR-V. Jeśli Twoja gra używa HLSL, DirectXShaderCompiler obsługuje dane wyjściowe SPIR-V. Zazwyczaj kompilujesz programy cieniowania offline w ramach procesu kompilacji zasobów dla swojej gry i dołączasz moduły SPIR-V jako część zasobów czasu działania.

Wywoływanie interfejsu Vulkan API w czasie działania

Aby wywołać interfejs Vulkan API, gra musi uzyskać wskaźniki funkcji do wywołań interfejsu Vulkan API. Najprostszym sposobem jest połączenie z biblioteką współdzieloną libvulkan.so, która jest dołączona do Android NDK. Łączenie z biblioteką ma 2 wady: dodatkowy narzut na wysyłanie funkcji i ograniczenia dotyczące tego, które wskaźniki funkcji interfejsu Vulkan API są automatycznie rozpoznawane.

Gdy wywołujesz funkcję interfejsu Vulkan API, sterowanie przechodzi przez tabelę wysyłania zarządzaną przez konstrukcję o nazwie moduł ładujący Vulkana. Android używa własnej implementacji modułu wczytującego Vulkana, a nie modułu wczytującego LunarG. Ten system modułu wczytującego jest częścią architektury warstw interfejsu Vulkan API. Łączenie z biblioteką systemową w czasie kompilacji powoduje dodatkowy poziom wysyłania dla danego wywołania interfejsu API. Narzut jest niewielki, ale może być zauważalny w przypadku gier, które wykonują dużą liczbę wywołań Vulkana.

Biblioteka systemowa zwykle rozpoznaje tylko wskaźniki do funkcji Vulkana, które są uważane za część podstawowego interfejsu API. Vulkan ma dużą liczbę rozszerzeń, które definiują dodatkowe funkcje Vulkana. Wiele z nich nie jest automatycznie rozpoznawanych przez bibliotekę systemową. Przed użyciem tych funkcji Vulkana musisz ręcznie rozpoznać wskaźniki do nich.

Aby rozwiązać te problemy, dynamicznie rozpoznawaj wskaźniki do wszystkich funkcji Vulkana, których zamierzasz używać w czasie działania. Możesz to zrobić, używając biblioteki meta-loader open source, takiej jak volk. Przykładowa gra AGDKTunnel integruje volk w tym celu. Jeśli używasz biblioteki meta-loader, nie łącz się z biblioteką współdzieloną libvulkan.so w skryptach kompilacji.

Określanie dostępnej wersji interfejsu Vulkan API

Android obsługuje te wersje interfejsu Vulkan API:

  • 1.0.3
  • 1.1
  • 1.3

Najwyższy numer wersji interfejsu Vulkan API dostępny na danym urządzeniu jest określany przez wersję Androida i obsługę sterownika Vulkana.

Wersja Androida

Obsługa platformy dla wersji interfejsu Vulkan API zależy od minimalnej wersji Androida (poziomu interfejsu API):

  • 1.3 – Android 13.0 (poziom 33 interfejsu API) i nowszy
  • 1.1 – Android 10.0 (poziom 29 interfejsu API) i nowszy
  • 1.0.3 – Android 7.0 (poziom 24 interfejsu API) i nowszy

Obsługa sterownika Vulkana

Obsługa platformy Android dla wersji interfejsu Vulkan API nie gwarantuje, że ta wersja interfejsu API jest obsługiwana przez sterownik Vulkana urządzenia. Urządzenie z Androidem 13 może obsługiwać tylko wersję 1.1 interfejsu Vulkan API.

Podczas inicjowania Vulkana nie żądaj wersji interfejsu API większej niż:

  • maksymalna wersja interfejsu Vulkan API dla wersji Androida działającej na urządzeniu;
  • wersja interfejsu Vulkan API zgłoszona przez vkEnumerateInstanceVersion
  • wersja interfejsu Vulkan API zgłoszona przez właściwość apiVersion struktury VkPhysicalDeviceProperties.

Oto przykład określania najwyższej obsługiwanej wersji interfejsu Vulkan API:

// Minimum Android API levels for Vulkan 1.3/1.1 version support
static constexpr int kMinimum_vk13_api_level = 33;
static constexpr int kMinimum_vk11_api_level = 29;

uint32_t GetHighestSupportedVulkanVersion(VkPhysicalDevice physical_device) {
  uint32_t instance_api_version = 0;
  vkEnumerateInstanceVersion(&instance_api_version);

  VkPhysicalDeviceProperties device_properties;
  vkGetPhysicalDeviceProperties(physical_device, &device_properties);

  // Instance and device versions don't have to match, use the lowest version
  // number for API support if they don't.
  const uint32_t driver_api_version =
      (instance_api_version < device_properties.apiVersion) ?
      instance_api_version : device_properties.apiVersion;

  const int device_api_level = android_get_device_api_level();
  if (device_api_level >= kMinimum_vk13_api_level &&
      driver_api_version >= VK_API_VERSION_1_3) {
    return VK_API_VERSION_1_3;
  } else if (device_api_level >= kMinimum_vk11_api_level &&
             driver_api_version >= VK_API_VERSION_1_1) {
    return VK_API_VERSION_1_1;
  }
  return VK_API_VERSION_1_0;
}

Określanie zgodności profilu Vulkana

Profile Vulkana to pliki JSON, które definiują zestaw wymaganych funkcji, rozszerzeń, możliwości i minimalnych limitów parametrów, które urządzenie Vulkan musi obsługiwać, aby było zgodne z profilem. Aby sprawdzić, czy urządzenie jest zgodne z określonym profilem Vulkana, np. profilem Android Baseline 2022, użyj biblioteki open source Vulkan Profiles API. Możesz też samodzielnie przeanalizować plik JSON profilu i sprawdzić możliwości urządzenia za pomocą odpowiednich interfejsów Vulkan API, aby określić zgodność profilu.

Profile Vulkana

Android używa profili Vulkana które określają, jakie funkcje i rozszerzenia są dostępne na każdym urządzeniu z Androidem.

Profil podstawowy Androida (ABP) to pierwsza próba utworzenia profilu Vulkana. ABP2021 i ABP2022 to profile wsteczne, które mają obejmować ponad 85% aktywnych urządzeń w danym momencie. Nie będzie nowych profili ABP.

Profile Vulkana na Androida (VPA) to nowy profil przyszłościowy, który ma odzwierciedlać potrzeby programistów i wprowadzać spójne funkcje, gdy tylko będą one dostępne dla programistów sprzętu. VPA15_minimums to pierwszy profil dla Androida 15. Co roku będzie się pojawiać nowy profil VPA, który będzie obejmować każdą główną wersję Androida.

Implementowanie tempa klatek

Prawidłowe tempo klatek jest niezbędne do zapewnienia wysokiej jakości rozgrywki. Android Game Development Kit zawiera bibliotekę tempa klatek, która pomaga grze osiągnąć optymalne tempo klatek. Więcej informacji o implementacji znajdziesz w artykule Integrowanie tempa klatek Androida z rendererem Vulkana.

Nie polegaj na niejawnej synchronizacji i tempie klatek

vkAcquireNextImageKHR i vkQueuePresentKHR służą do zarządzania łańcuchem wymiany. Unikaj polegania na ich potencjalnym zachowaniu blokującym w przypadku ogólnej synchronizacji aplikacji lub GPU.

Dokładne zachowanie blokujące tych funkcji może się znacznie różnić w zależności od:

  • urządzeń z Androidem;
  • sterowników GPU;
  • stanów silnika prezentacji (VkPresentModeKHR).

Jedynym celem funkcji vkAcquireNextImageKHR jest uzyskanie dostępnego obrazu do wyświetlenia. Może ona blokować lub nie. Podobnie funkcja vkQueuePresentKHR umieszcza w kolejce żądanie wyświetlenia obrazu i też może blokować lub nie.

Żadna z tych funkcji nie zapewnia niezawodnych gwarancji synchronizacji niezwiązanych ze sobą zadań procesora ani operacji GPU.

Aby zapewnić niezawodną synchronizację, zawsze używaj jawnych elementów pierwotnych Vulkana, takich jak semafory dla zależności GPU-GPU (np. renderowanie do wyświetlania), bariery dla synchronizacji GPU-CPU (np. wiedza o tym, kiedy renderowanie jest zakończone na procesorze) oraz bariery potoku lub zdarzenia dla bardziej szczegółowej zależności wykonywania i pamięci GPU. Używanie jawnej synchronizacji zapewnia przewidywalne zachowanie i pozwala uniknąć subtelnych błędów spowodowanych różnicami w czasie działania, które są nieodłączne od różnorodnego ekosystemu sprzętowego Androida.

Implementowanie wstępnego obrotu

Urządzenia z Androidem mogą wyświetlać obraz w różnych orientacjach. Orientacja urządzenia może się różnić od orientacji powierzchni renderowania. W przeciwieństwie do OpenGL ES na Androidzie Vulkan nie obsługuje rozbieżności między tymi 2 orientacjami. Aby dowiedzieć się, jak działa proces orientacji i jaka jest optymalna metoda obsługi różnic orientacji podczas korzystania z Vulkana, przeczytaj artykuł Obsługa obrotu urządzenia za pomocą wstępnego obrotu Vulkana.

Rozwiązywanie problemów i profilowanie renderowania w Vulkanie

Dostępnych jest wiele narzędzi, które pomagają w diagnozowaniu problemów z renderowaniem i wydajnością kodu renderowania w Vulkanie.

Więcej informacji o narzędziach do debugowania i profilowania Vulkana znajdziesz w sekcji Narzędzia i funkcje zaawansowane.

Warstwy walidacji Vulkana

Warstwy walidacji Vulkana to biblioteki czasu działania, które można włączyć, aby sprawdzać wywołania interfejsu Vulkan API i wyświetlać ostrzeżenia lub błędy dotyczące nieprawidłowego lub nieoptymalnego użycia. Te warstwy walidacji nie są domyślnie aktywne, ponieważ proces walidacji zwiększa narzut czasu działania i wpływa na wydajność gry. Informacje o tym, jak używać warstw walidacji w grze, znajdziesz w artykule Debugowanie za pomocą warstwy walidacji.

Narzędzia do przechwytywania klatek

Używaj narzędzi do przechwytywania klatek, aby rejestrować i odtwarzać wywołania interfejsu Vulkan API wykonywane podczas klatki gry. Te narzędzia umożliwiają:

  • wyświetlanie informacji o aktywnych zasobach graficznych i ich wizualizacjach;
  • wyświetlanie sekwencji wywołań interfejsu API wykonywanych przez grę oraz parametrów interfejsu API;
  • sprawdzanie stanu potoku graficznego w momencie wywołania rysowania;
  • wizualizowanie wyników renderowania do określonego wywołania rysowania w klatce.

Użyj narzędzia open source RenderDoc, aby przechwytywać klatki z gier działających na Androidzie. RenderDoc obsługuje przechwytywanie klatek zarówno w Vulkanie, jak i OpenGL ES.

Do przechwytywania klatek Vulkana można też używać Android GPU Inspector (AGI).

Narzędzia do analizy wydajności

Używaj narzędzi do analizy wydajności, aby badać problemy z renderowaniem w grze, które powodują nieoptymalną liczbę klatek. Poszczególni dostawcy GPU udostępniają narzędzia do profilowania gry i dostarczania danych o skuteczności specyficznych dla ich architektur GPU. Charakterystyka wydajności i wąskie gardła gry mogą się znacznie różnić w zależności od tego, czy renderowanie odbywa się na GPU różnych dostawców, czy nawet na różnych generacjach GPU tego samego dostawcy.

Do zbierania i analizowania danych o skuteczności możesz też używać Android GPU Inspector. W przeciwieństwie do narzędzi dostawców Android GPU Inspector jest zgodny z wieloma GPU różnych dostawców. Android GPU Inspector nie obsługuje jednak starszych urządzeń z Androidem i może nie być zgodny ze wszystkimi nowymi urządzeniami.

Ulepszanie testowania Vulkana za pomocą CTS-D

Producenci urządzeń z Androidem używają pakietu CTS (Compatibility Test Suite), aby zapewnić zgodność swoich urządzeń. Testy CTS-D (Developer-Powered CTS) to testy przesyłane przez deweloperów aplikacji na Androida, aby upewnić się, że przyszłe urządzenia z Androidem będą spełniać ich przypadki użycia oraz będą w stanie płynnie i bez błędów uruchamiać ich aplikacje.

Jeśli uda Ci się wykryć nowy błąd w aplikacji Vulkan, który wpływa na konkretne urządzenie z Androidem, możesz przesłać nową propozycję testu, opisując problem i sposoby jego sprawdzenia. Dzięki temu problem zostanie rozwiązany w przyszłej aktualizacji urządzenia, a ten sam błąd nie wystąpi na żadnym innym urządzeniu.

Szczegółowe instrukcje przesyłania propozycji testu znajdziesz w artykule Proces przesyłania testów CTS.