Wdrażanie interfejsu Vulkan

Vulkan to wieloplatformowy interfejs API o niskim obciążeniu, który umożliwia tworzenie wydajnych grafik 3D. Podobnie jak OpenGL ES (GLES), Vulkan udostępnia narzędzia do tworzenia wysokiej jakości grafik w czasie rzeczywistym w aplikacjach. Zalety używania Vulkana to m.in. zmniejszenie obciążenia procesora i obsługa języka SPIR-V Binary Intermediate.

Aby można było wdrożyć Vulkan, urządzenie musi zawierać:

  • Ładowarka Vulkana, udostępniana przez Androida.
  • Sterownik Vulkana udostępniany przez SoC, np. przez dostawców interfejsu IHV GPU, który implementuje interfejs Vulkan API. Aby obsługiwać funkcję Vulkan, urządzenie z Androidem musi mieć kartę graficzną z obsługą Vulkan i powiązany z nią sterownik. Karta graficzna musi też obsługiwać GLES 3.1 lub nowszą. Aby uzyskać pomoc dotyczącą sterownika, skontaktuj się z dostawcą SoC.

Jeśli urządzenie zawiera sterownik Vulkan, musi deklarować funkcje systemu FEATURE_VULKAN_HARDWARE_LEVELFEATURE_VULKAN_HARDWARE_VERSION w wersjach, które dokładnie odzwierciedlają możliwości urządzenia. Dzięki temu możesz mieć pewność, że urządzenie jest zgodne z dokumentem z definicją zgodności (CDD).

Ładowarka Vulkan

Ładowarka Vulkana platform/frameworks/native/vulkan to główny interfejs między aplikacjami Vulkan a sterownikami Vulkana na urządzeniu. Wczytnik Vulkan jest zainstalowany w /system/lib[64]/libvulkan.so. Ładowarka udostępnia główne punkty wejścia interfejsu Vulkan API, punkty wejścia rozszerzeń wymagane przez specyfikację Android CDD oraz wiele dodatkowych opcjonalnych rozszerzeń. Rozszerzenia integracji z systemem operacyjnym (WSI) są eksportowane przez ładowarkę i głównie są implementowane w ładowarce, a nie w sterowniku. Obsługuje on też warstwy wczytywania i wyliczania, które mogą udostępniać dodatkowe rozszerzenia oraz przechwytywać wywołania interfejsu API na drodze do sterownika.

Pakiet NDK zawiera bibliotekę z kropką libvulkan.so do łączenia. Biblioteka eksportuje te same symbole co ładowarka. Aplikacje wywołują funkcje wyeksportowane z rzeczywistej biblioteki libvulkan.so, by wprowadzić w ładowarce funkcje trampolin, które wysyłają je do odpowiedniej warstwy lub sterownika na podstawie pierwszego argumentu. Wywołanie vkGet*ProcAddr()zwraca wskaźniki funkcji, do których odsyłają trampoliny (czyli wywołuje bezpośrednio kod interfejsu API). Wywoływanie za pomocą wskaźników funkcji zamiast wyeksportowanych symboli jest bardziej wydajne, ponieważ pomija trampolinę i wysyłanie.

Wyliczanie i wczytywanie sterowników

Podczas tworzenia obrazu systemu Android oczekuje, że system będzie wiedział, które GPU jest dostępne. Moduł ładowania korzysta z istniejącego mechanizmu HAL w hardware.h do wykrywania i wczytywania sterownika. Preferowane ścieżki dla 32- i 64-bitowych sterowników Vulkan:

/vendor/lib/hw/vulkan.<ro.hardware.vulkan>.so
/vendor/lib/hw/vulkan.<ro.product.platform>.so
/vendor/lib64/hw/vulkan.<ro.hardware.vulkan>.so
/vendor/lib64/hw/vulkan.<ro.product.platform>.so

W Androidzie 7.0 i nowszych pochodna Vulkana hw_module_tobejmuje pojedynczą strukturę hw_module_t; obsługiwany jest tylko 1 sterownik, a ciąg znaków stałych HWVULKAN_DEVICE_0 jest przekazywany do funkcji open().

Pochodna interfejsu Vulkan hw_device_t odpowiada jednemu kierowcy, który może obsługiwać wiele urządzeń fizycznych. Struktura hw_device_t może obejmować eksport funkcji vkGetGlobalExtensionProperties(), vkCreateInstance()vkGetInstanceProcAddr(). Ładowarka może znaleźć wszystkie inne funkcje VkInstance(), VkPhysicalDevice() i vkGetDeviceProcAddr(), wywołując funkcję vkGetInstanceProcAddr() struktury hw_device_t.

Wykrywanie i wczytywanie warstw

Ładowarka Vulkan obsługuje wyliczanie i wczytywanie warstw, które mogą udostępniać dodatkowe rozszerzenia i przechwytywać wywołania interfejsu API na drodze do sterownika. Android nie zawiera warstw w obrazie systemu, ale aplikacje mogą zawierać warstwy w plikach APK.

Pamiętaj, że model zabezpieczeń i zasady Androida znacznie różnią się od tych na innych platformach. W szczególności Android nie zezwala na wczytywanie kodu zewnętrznego do procesu, który nie obsługuje debugowania, na urządzeniach produkcyjnych (niezrootowanych). Nie zezwala też na to, aby kod zewnętrzny sprawdzał ani kontrolował pamięci, stanu itp. procesu. Obejmuje to zakaz zapisywania zrzutów rdzeni, śladów interfejsu API itp. na dysku w celu późniejszej kontroli. Na urządzeniach produkcyjnych można włączyć tylko warstwy dostarczane w ramach aplikacji, które nie są przeznaczone do debugowania. Sterowniki nie mogą zapewniać funkcji, które naruszają te zasady.

Przykłady zastosowań warstw:

  • Warstwy na etapie rozwoju – warstw weryfikujących i uzupełniających dla narzędzi do śledzenia, profilowania i debugowania nie należy instalować w obrazie systemu na urządzeniach produkcyjnych. Warstwy weryfikacji i przekładki dla narzędzi do śledzenia, profilowania i debugowania powinny być aktualizowane bez obrazu systemu. Deweloperzy, którzy chcą używać jednej z tych warstw podczas tworzenia aplikacji, mogą zmodyfikować pakiet aplikacji, na przykład przez dodanie pliku do katalogu natywnych bibliotek. Uważa się, że inżynierowie IHV i OEM, którzy chcą zdiagnozować błędy w dostarczanych niemodyfikowalnych aplikacjach, mają dostęp do wersji nieprodukcyjnych (z rootem) obrazu systemu, chyba że te aplikacje można debugować. Więcej informacji znajdziesz w artykule Warstwy weryfikacji Vulkan na Androidzie.
  • Warstwy narzędziowe – te warstwy udostępniają rozszerzenia, takie jak warstwa implementująca menedżera pamięci dla pamięci urządzenia. Deweloperzy wybierają warstwy i ich wersje, które mają być używane w aplikacji. Różne aplikacje korzystające z tej samej warstwy mogą używać różnych wersji. Deweloperzy decydują, które z tych warstw uwzględnić w pakiecie aplikacji.
  • Wstrzyknięte (niejawne) warstwy – obejmuje warstwy, takie jak liczba klatek, sieć społecznościowa czy nakładki z programem uruchamiającym gry, udostępnione przez użytkownika lub inną aplikację bez wiedzy i zgody aplikacji. Naruszają one zasady bezpieczeństwa Androida i nie są obsługiwane.

W przypadku aplikacji niemożliwych do debugowania moduł ładowania wyszukuje warstwy tylko w katalogu biblioteki natywnej aplikacji i próbuje wczytać dowolną bibliotekę o nazwie pasującej do określonego wzorca (na przykład libVKLayer_foo.so).

W przypadku aplikacji z możliwością debugowania ładowarka wyszukuje warstwy w /data/local/debug/vulkan i próbuje załadować wszystkie biblioteki pasujące do określonego wzorca.

Android umożliwia przenoszenie warstw z modyfikacjami środowiska kompilacji między Androidem a innymi platformami. Szczegółowe informacje o interfejsie między warstwami a ładowarką znajdziesz w artykule Architektura interfejsów ładowarki Vulkan. Utrzymywane przez Khronos warstwy walidacji są hostowane w warstwach walidacji Vulkana.

Wersje i możliwości interfejsu Vulkan API

W tabeli poniżej znajdziesz wersje interfejsu Vulkan API dla kilku wersji Androida.
Wersja Androida Wersja interfejsu Vulkan
Android 13 Vulkan 1.3
Android 9 Vulkan 1.1
Android 7 Vulkan 1.0

Omówienie funkcji Vulkan 1.3

Wersja Vulkan 1.3 wprowadza do głównej funkcjonalności Vulkana wiele wcześniej opcjonalnych rozszerzeń. Wiele z tych funkcji zostało dodanych w celu zwiększenia kontroli i dokładności interfejsu programowania Vulkan. Instancji przejść renderowania w jednym przejeździe nie trzeba już tworzyć obiektów ani ramek renderowania przejść. Łączna liczba obiektów stanu potoku może zostać zmniejszona, a synchronizacja w interfejsie API została zmieniona. Vulkan 1.3 ma te same wymagania sprzętowe co Vulkan 1.2, 1.1 i 1.0, a większość implementacji znajduje się w sterowniku graficznym dla konkretnego SoC, a nie w ramach.

Najważniejsze funkcje Vulkan 1.3 dla Androida to:

  • Obsługa instancji przejść renderowania w pojedynczym przejeździe
  • Obsługa natychmiastowego kończenia wywoływania mechanizmu cieniowania
  • Bardziej szczegółowa kontrola nad tworzeniem, udostępnianiem i zarządzaniem przepływem

Vulkan 1.3 zawiera też kilka mniejszych funkcji i ulepszeń interfejsu API. Wszystkie zmiany wprowadzone w podstawowym interfejsie Vulkan API w wersji 1.3 znajdziesz w wersji podstawowej (Vulkan 1.3).

Omówienie funkcji Vulkan 1.2

Vulkan 1.2 zawiera kilka funkcji i rozszerzeń, które upraszczają interfejs API. Obejmuje to zintegrowany model pamięci i dodatkowe informacje, które można zapytać z sterownika urządzenia. Vulkan 1.2 ma te same wymagania sprzętowe co Vulkan 1.0 i 1.1. Cała implementacja znajduje się w sterowniku graficznym dla konkretnego układu SoC, a nie w ramach.

Najważniejszą funkcją Vulkan 1.2 na Androida jest obsługa 8-bitowej pamięci.

Vulkan 1.2 zawiera też kilka mniejszych funkcji i ulepszeń interfejsu API. Wszystkie zmiany wprowadzone w podstawowym interfejsie Vulkana w ramach poprawki 1.2 znajdziesz w sekcji Podstawowe poprawki (Vulkan 1.2).

Omówienie funkcji interfejsu Vulkan 1.1

Vulkan 1.1 obsługuje interoperacyjność pamięci/synchronizacji, dzięki czemu producenci OEM mogą obsługiwać Vulkan 1.1 na swoich urządzeniach. Dodatkowo interoperacyjność pamięci/synchronizacji umożliwia deweloperom określenie, czy Vulkan 1.1 jest obsługiwany na urządzeniu, i jego efektywne używanie w takim przypadku. Vulkan 1.1 ma te same wymagania sprzętowe co Vulkan 1.0, ale większość implementacji znajduje się w sterowniku graficznym dla konkretnego układu SOC, a nie w ramach.

Najważniejsze funkcje Vulkan 1.1 dla Androida to:

  • Obsługa importowania i eksportowania buforów pamięci i obiektów synchronizacji spoza Vulkana (na potrzeby współpracy z aparatem, kodekami i GLES)
  • Obsługa formatów YCbCr

Vulkan 1.1 zawiera też kilka mniejszych funkcji i ulepszeń interfejsu API. Wszystkie zmiany wprowadzone w podstawowym interfejsie Vulkan API w wersji 1.1 można znaleźć w sekcji Podstawowe wersje (Vulkan 1.1).

Wybierz obsługę interfejsu Vulkan

Urządzenia z Androidem powinny obsługiwać najbardziej zaawansowany dostępny zestaw funkcji Vulkana, o ile obsługują 64-bitowy interfejs ABI i nie mają mało pamięci.

Urządzenia z Androidem 13 lub nowszym powinny obsługiwać interfejs Vulkan 1.3.

Urządzenia uruchamiane w Androidzie 10 powinny obsługiwać Vulkan 1.1.

Inne urządzenia mogą opcjonalnie obsługiwać Vulkan 1.3, 1.2 i 1.1.

Obsługa wersji interfejsu Vulkan

Urządzenie z Androidem obsługuje wersję Vulkan, jeśli są spełnione te warunki:

  1. Dodaj sterownik Vulkana, który obsługuje interesującą Cię wersję Vulkana (musi to być wersja Vulkana 1.3, 1.1 lub 1.0) wraz z dodatkowymi wymaganiami CDD dla wersji Androida. Możesz też zaktualizować istniejący sterownik Vulkan do niższej wersji.
  2. W przypadku Vulkana 1.3 lub 1.1 sprawdź, czy funkcja systemu zwracana przez menedżera pakietów zwraca true dla prawidłowej wersji Vulkana.
    • W przypadku interfejsu Vulkan 1.3 funkcja to PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x403000).
    • W przypadku Vulkan 1.1 ta funkcja jest dostępna w wersjiPackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x401000).
    Menedżer pakietów zwróci true dla Vulkana 1.3 i Vulkana 1.1, dodając regułę (pokazana poniżej) do odpowiedniego pliku device.mk.
    • W przypadku Vulkan 1.3 dodaj te informacje:
      PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.vulkan.version-1_3.xml:
      $(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml
      
    • W przypadku Vulkan 1.1 dodaj:
      PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.vulkan.version-1_1.xml:
      $(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml
      

Profil podstawowy Androida (ABP)

Zachęcamy, aby wszystkie urządzenia z Androidem były zgodne z najnowszym profilem Android Baseline 2022 opisanym w przewodniku po profilu Android Baseline.

Każde urządzenie z Androidem 14 lub nowszym i interfejsem Vulkan API musi spełniać wszystkie funkcje zdefiniowane w profilu Android Baseline 2021. Pełna lista wymaganych funkcji jest wymieniona w pliku profilu Vulkana json, ale kluczowy podzbiór wymaganych funkcji obejmuje:

  • skompresowane tekstury za pomocą ASTC i ETC;
  • Zmienne przestrzenie kolorów za pomocą VK_EXT_swapchain_colorspace.
  • Przykładowe cieniowanie i interpolacja wielu próbek do sampleRateShading.

Integracja z systemem okien (WSI)

W libvulkan.so sterownik implementuje te rozszerzenia integracji z systemem okien (WSI):

  • VK_KHR_surface
  • VK_KHR_android_surface
  • VK_KHR_swapchain
  • VK_KHR_driver_properties, wdrożone w Vulkan 1.1 tylko na Androidzie 10
  • VK_GOOGLE_display_timing, zaimplementowane w dowolnej wersji Vulkana w Androidzie 10

Obiekty VkSurfaceKHR i VkSwapchainKHR oraz wszystkie interakcje z ANativeWindow są obsługiwane przez platformę i nie są widoczne dla kierowców. Implementacja WSI opiera się na rozszerzeniu VK_ANDROID_native_buffer, które musi być obsługiwane przez sterownik. To rozszerzenie jest używane tylko przez implementację WSI i nie jest widoczne dla aplikacji.

Flagi wykorzystania Gralloc

Implementacje Vulkan mogą wymagać przydzielenia buforów swapchain za pomocą flag prywatnego użycia Gralloc zdefiniowanych przez implementację. Podczas tworzenia swapchain Android prosi sterownik o przetłumaczenie żądanego formatu i flag użycia obrazu na flagi użycia Gralloc, wywołując:

typedef enum VkSwapchainImageUsageFlagBitsANDROID {
    VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID = 0x00000001,
    VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkSwapchainImageUsageFlagBitsANDROID;
typedef VkFlags VkSwapchainImageUsageFlagsANDROID;

VkResult VKAPI vkGetSwapchainGrallocUsage2ANDROID(
    VkDevice                          device,
    VkFormat                          format,
    VkImageUsageFlags                 imageUsage,
    VkSwapchainImageUsageFlagsANDROID swapchainUsage,
    uint64_t*                         grallocConsumerUsage,
    uint64_t*                         grallocProducerUsage
);

Parametry formatimageUsage są pobierane ze struktury VkSwapchainCreateInfoKHR. Sterownik powinien wypełnić flagi wykorzystania Gralloc i *grallocConsumerUsage oraz *grallocProducerUsage wymagane w przypadku formatu i użytkowania. Flagi użycia zwracane przez sterownik są łączone z flagami użycia żądanymi przez konsumenta swapchainu podczas przydzielania buforów.

Android 7.x wywołuje wcześniejszą wersję VkSwapchainImageUsageFlagsANDROID() o nazwie vkGetSwapchainGrallocUsageANDROID(). W Androidzie 8.0 i nowszych vkGetSwapchainGrallocUsageANDROID() jest wycofane, ale nadal wywołuje vkGetSwapchainGrallocUsageANDROID(), jeśli kierowca nie poda vkGetSwapchainGrallocUsage2ANDROID():

VkResult VKAPI vkGetSwapchainGrallocUsageANDROID(
    VkDevice            device,
    VkFormat            format,
    VkImageUsageFlags   imageUsage,
    int*                grallocUsage
);

vkGetSwapchainGrallocUsageANDROID() nie obsługuje flag wykorzystania swapchain ani rozszerzonych flag wykorzystania Gralloc.

Obrazy z obsługą Gralloc

VkNativeBufferANDROID to struktura rozszerzenia vkCreateImage służąca do tworzenia obrazu obsługiwanego przez bufor Gralloc. VkNativeBufferANDROID jest dostarczany do vkCreateImage() w łańcuchu struktury VkImageCreateInfo. Połączenia z numerem vkCreateImage() z użytkownikiem VkNativeBufferANDROID są wykonywane podczas połączenia z numerem vkCreateSwapchainKHR. Implementacja WSI przydziela liczbę natywnych buforów żądanych na potrzeby wymiany, a następnie tworzy VkImage dla każdego z nich:

typedef struct {
    VkStructureType             sType; // must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
    const void*                 pNext;

    // Buffer handle and stride returned from gralloc alloc()
    buffer_handle_t             handle;
    int                         stride;

    // Gralloc format and usage requested when the buffer was allocated.
    int                         format;
    int                         usage;
    // Beginning in Android 8.0, the usage field above is deprecated and the
    // usage2 struct below was added. The usage field is still filled in for
    // compatibility with Android 7.0 drivers. Drivers for Android 8.0
    // should prefer the usage2 struct, especially if the
    // android.hardware.graphics.allocator HAL uses the extended usage bits.
    struct {
        uint64_t                consumer;
        uint64_t                producer;
    } usage2;
} VkNativeBufferANDROID;

Podczas tworzenia obrazu obsługiwanego przez Gralloc, VkImageCreateInfo zawiera te dane:

  .sType               = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
  .pNext               = the above VkNativeBufferANDROID structure
  .imageType           = VK_IMAGE_TYPE_2D
  .format              = a VkFormat matching the format requested for the gralloc buffer
  .extent              = the 2D dimensions requested for the gralloc buffer
  .mipLevels           = 1
  .arraySize           = 1
  .samples             = 1
  .tiling              = VK_IMAGE_TILING_OPTIMAL
  .usage               = VkSwapchainCreateInfoKHR::imageUsage
  .flags               = 0
  .sharingMode         = VkSwapchainCreateInfoKHR::imageSharingMode
  .queueFamilyCount    = VkSwapchainCreateInfoKHR::queueFamilyIndexCount
  .pQueueFamilyIndices = VkSwapchainCreateInfoKHR::pQueueFamilyIndices

W Androidzie 8.0 i nowszych platforma zapewnia strukturę rozszerzenia VkSwapchainImageCreateInfoKHR w łańcuchu VkImageCreateInfo udostępnianym vkCreateImage, gdy do swapchain wymagane są jakiekolwiek flagi wykorzystania obrazu wymiany. Struktura rozszerzenia zawiera flagi użycia obrazu swapchain:

typedef struct {
    VkStructureType                        sType; // must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID
    const void*                            pNext;

    VkSwapchainImageUsageFlagsANDROID      usage;
} VkSwapchainImageCreateInfoANDROID;

W Androidzie 10 i nowszych platforma obsługuje VK_KHR_swapchain w wersji 70, dzięki czemu aplikacja Vulkan może utworzyć VkImage z pamięcią swapchain. Aplikacja najpierw wywołuje funkcję vkCreateImage z strukturą VkImageSwapchainCreateInfoKHR połączoną z strukturą VkImageCreateInfo. Następnie aplikacja wywołuje funkcję vkBindImageMemory2(KHR) z strukturą VkBindImageMemorySwapchainInfoKHR połączoną z strukturą VkBindImageMemoryInfo. imageIndex określony w strukturze VkBindImageMemorySwapchainInfoKHR musi być prawidłowym indeksem obrazów zamiany. Platforma udostępnia strukturę rozszerzenia VkNativeBufferANDROID z odpowiednimi informacjami o buforze Gralloc dla łańcucha VkBindImageMemoryInfo, dzięki czemu sterownik wie, z którym buforem Gralloc ma powiązać VkImage.

Pobieranie obrazów

vkAcquireImageANDROID przejmuje własność obrazu swapchain i importuje natywny płot sygnalizowany z zewnątrz do istniejącego obiektu VkSemaphore i istniejącego obiektu VkFence:

VkResult VKAPI vkAcquireImageANDROID(
    VkDevice            device,
    VkImage             image,
    int                 nativeFenceFd,
    VkSemaphore         semaphore,
    VkFence             fence
);

Funkcja vkAcquireImageANDROID() jest wywoływana podczas vkAcquireNextImageKHR, aby zaimportować natywne ogrodzenie do obiektów VkSemaphore i VkFence dostarczanych przez aplikację (w tym wywołaniu obiekty semfora i ogrodzenia są opcjonalne). Kierowca może również wykorzystać tę możliwość, by rozpoznać i zająć wszelkie zewnętrzne zmiany w stanie bufora Gralloca – wielu kierowców nie będzie musiało nic robić. To wywołanie powoduje, że VkSemaphoreVkFence przechodzą w taki sam stan oczekiwania, jak gdyby sygnał został wysłany przez vkQueueSubmit. Dzięki temu kolejki mogą czekać na semaforze, a aplikacja może czekać na semaforze.

Oba obiekty są sygnalizowane, gdy sygnał wysyła rdzenna bariera. Jeśli rdzenna bariera została już sygnalizowana, semafora jest w stanie sygnalizowanym, gdy funkcja zwraca wartość. Kierowca przejmuje prawo własności do deskryptora pliku ogrodzenia i zamyka go, gdy nie jest już potrzebny. Musi to zrobić nawet wtedy, gdy nie podano obiektu semafora ani ogrodzenia lub gdy vkAcquireImageANDROID zakończy działanie z błędem. Jeśli fenceFd to –1, oznacza to, że sygnał został już przekazany.

Opublikuj zdjęcia

vkQueueSignalReleaseImageANDROID przygotowuje obraz swapchain do użytku zewnętrznego, tworzy natywny płot i planuje wysłanie sygnału do natywnego płotu po tym, jak sygnały zostaną wysłane przez semapfory wejściowe:

VkResult VKAPI vkQueueSignalReleaseImageANDROID(
    VkQueue             queue,
    uint32_t            waitSemaphoreCount,
    const VkSemaphore*  pWaitSemaphores,
    VkImage             image,
    int*                pNativeFenceFd
);

vkQueuePresentKHR() połączeń vkQueueSignalReleaseImageANDROID() w podanej kolejce. Sterownik musi wygenerować natywną barierę, która nie sygnalizuje, dopóki wszystkie semafory waitSemaphoreCount w sygnale pWaitSemaphores i wszystkie dodatkowe czynności wymagane do przygotowania image do prezentacji nie zostaną ukończone.

Jeśli semafora oczekiwania (jeśli występuje) została już sygnalizowana, a proces queue jest nieaktywny, sterownik może ustawić *pNativeFenceFd na -1 zamiast rzeczywistego natywnego deskryptora pliku ogrodzenia, co oznacza, że nie ma na co czekać. Użytkownik wywołujący jest właścicielem i zamyka wskaźnik pliku zwracany w funkcji *pNativeFenceFd.

Wiele sterowników może zignorować parametr image, ale niektóre mogą wymagać przygotowania struktur danych po stronie procesora powiązanych z buforem Gralloc na potrzeby zewnętrznych konsumentów obrazu. Przygotowanie zawartości bufora do użycia przez zewnętrznych odbiorców powinno odbywać się asynchronicznie w ramach przejścia obrazu do VK_IMAGE_LAYOUT_PRESENT_SRC_KHR.

Jeśli obraz został utworzony za pomocą funkcji VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID, sterownik musi zezwalać na wielokrotne wywoływanie funkcji vkQueueSignalReleaseImageANDROID() bez ingerencji w wywołania vkAcquireImageANDROID().

Obsługa udostępnianych obrazów

Niektóre urządzenia mogą udostępniać własność jednego obrazu między rurociągiem wyświetlania a implementacją Vulkan, aby zminimalizować opóźnienia. W Androidzie 9 i nowszych wersjach ładowarka wyświetla reklamę rozszerzenia VK_KHR_shared_presentable_image w sytuacji, gdy kierowca zareaguje na wywołanie funkcji vkGetPhysicalDeviceProperties2.

Jeśli sterownik nie obsługuje Vulkan 1.1 ani rozszerzenia VK_KHR_physical_device_properties2, program ładujący nie reklamuje obsługi udostępnianych obrazów do prezentacji. W przeciwnym razie ładowarka wysyła zapytanie o możliwości sterownika, wywołując funkcję vkGetPhysicalDeviceProperties2() i uwzględniając w łańcuchu VkPhysicalDeviceProperties2::pNext tę strukturę:

typedef struct {
    VkStructureType sType; // must be VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID
    const void*     pNext;
    VkBool32        sharedImage;
} VkPhysicalDevicePresentationPropertiesANDROID;

Jeśli sterownik może udostępnić obraz systemowi wyświetlania, ustawia element sharedImage na VK_TRUE.

Weryfikacja

Producenci OEM mogą testować implementację Vulkana za pomocą CTS, która obejmuje:

  • testy zgodności Khronos Vulkan w module CtsDeqpTestCases, które obejmują testy funkcjonalności interfejsu API dla Vulkan 1.0, 1.1, 1.2 i 1.3;
  • moduł CtsGraphicsTestCases, który sprawdza, czy urządzenie jest prawidłowo skonfigurowane pod kątem obsługiwanych przez nie funkcji Vulkan;

Flaga funkcji Vulkan

Aby ujawnić flagę funkcji, wymagane jest urządzenie z Androidem 11 lub nowszym, które obsługuje interfejs Vulkan API.android.software.vulkan.deqp.level Wartość tej flagi funkcji to data zakodowana jako liczba całkowita. Określa datę związaną z testami Vulkan dEQP, które urządzenie twierdzi, że przeszło.

Data w formacie RRRR-MM-DD jest zakodowana jako 32-bitowa liczba całkowita w następujący sposób:

  • Bity 0–15 przechowują rok.
  • Bity 16–23 przechowują miesiąc
  • Bits 24-31 store the day

Minimalna dozwolona wartość flagi funkcji to 0x07E30301, która odpowiada dacie 01.03.2019, czyli dacie powiązanej z testami dEQP Vulkana dla Androida 10. Jeśli flaga funkcji ma co najmniej tę wartość, urządzenie twierdzi, że przeszło wszystkie testy dEQP Vulkan w Androidzie 10.

Wartość 0x07E40301 odpowiada dacie 1 marca 2020 r., czyli daty związanej z testami dEQP interfejsu Vulkan w Androidzie 11. Jeśli flaga funkcji ma co najmniej tę wartość, urządzenie informuje, że przeszły wszystkie testy dEQP Androida 11.

Wartość 0x07E60301 odpowiada dacie 1 marca 2022 r., czyli daty związanej z testami dEQP interfejsu Vulkan na Androidzie 13. Jeśli flaga funkcji ma co najmniej tę wartość, urządzenie ma przejść wszystkie testy dEQP Vulkana w Androidzie 13.

Urządzenie, które udostępnia określoną flagę funkcji (np. 0x07E30301, 0x07E40301, 0x07E60301), zapewnia, że wszystkie testy dEQP Vulkana w Androidzie (Android 10, Android 11 lub Android 13) z tą flagą zostały zaliczone. To urządzenie może przejść testy Vulkan dEQP z późniejszej wersji Androida.

Vulkan dEQP jest częścią pakietu Android CTS. Od Androida 11 komponent testów dEQP w CTS jest świadomy flagi funkcji android.software.vulkan.deqp.leveli pomija wszystkie testy Vulkan dEQP, które – zgodnie z tą flagą funkcji – nie są obsługiwane przez urządzenie. Takie testy są zgłaszane jako testy, które łatwo przejść.