Wdrażanie Vulkana

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

Aby interfejs Vulkan działał prawidłowo, urządzenie musi zawierać:

  • Loader Vulkan dostarczany przez Androida.
  • Sterownik Vulkana dostarczany przez układy SoC, takie jak GPU IHV, który implementuje interfejs Vulkan API. Aby obsługiwać funkcje Vulkan, urządzenie z Androidem musi mieć procesor graficzny obsługujący Vulkan i odpowiedni sterownik. Procesor graficzny musi też obsługiwać GLES 3.1 i nowsze wersje. Skontaktuj się z dostawcą układu SoC, aby poprosić o obsługę sterownika.

Jeśli urządzenie zawiera sterownik Vulkan, musi deklarować funkcje systemowe FEATURE_VULKAN_HARDWARE_LEVELFEATURE_VULKAN_HARDWARE_VERSION w wersjach, które dokładnie odzwierciedlają możliwości urządzenia. Pomaga to zapewnić, że urządzenie jest zgodne z dokumentem definicji zgodności (CDD).

Program ładujący Vulkan

Program ładujący Vulkanplatform/frameworks/native/vulkan to główne narzędzie do komunikacji między aplikacjami Vulkan a sterownikiem Vulkan urządzenia. Program ładujący Vulkan jest zainstalowany w lokalizacji /system/lib[64]/libvulkan.so. Program wczytujący udostępnia główne punkty wejścia interfejsu Vulkan API, punkty wejścia rozszerzeń wymaganych przez dokument CDD Androida oraz wiele dodatkowych rozszerzeń opcjonalnych. Rozszerzenia integracji z systemem Windows (WSI) są eksportowane przez program wczytujący i implementowane głównie w nim, a nie w sterowniku. Program ładujący obsługuje też wyliczanie i wczytywanie warstw, które mogą udostępniać dodatkowe rozszerzenia i przechwytywać wywołania podstawowych interfejsów API w drodze do sterownika.

NDK zawiera bibliotekę libvulkan.so do linkowania. Biblioteka eksportuje te same symbole co program wczytujący. Aplikacje wywołują funkcje wyeksportowane z prawdziwej biblioteki libvulkan.so, aby w programie wczytującym wywołać funkcje trampoliny, które na podstawie pierwszego argumentu przekazują sterowanie do odpowiedniej warstwy lub sterownika. Wywołanie vkGet*ProcAddr() zwraca wskaźniki funkcji, do których przekierowują trampoliny (czyli wywołuje bezpośrednio kod podstawowego interfejsu API). Wywoływanie funkcji za pomocą wskaźników funkcji, a nie wyeksportowanych symboli, jest bardziej wydajne, ponieważ pomija trampolinę i wysyłanie.

Wykrywanie i wczytywanie sterowników

Po utworzeniu obrazu systemu Android oczekuje, że system będzie wiedzieć, które procesory graficzne są dostępne. Ładowarka korzysta z istniejącego mechanizmu HAL w hardware.h, aby wykryć i załadować sterownik. Preferowane ścieżki dla 32-bitowych i 64-bitowych sterowników Vulkan to:

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

W Androidzie 7.0 i nowszym pochodna Vulkan hw_module_t otacza pojedynczą strukturę hw_module_t. Obsługiwany jest tylko jeden sterownik, a stały ciąg znaków HWVULKAN_DEVICE_0 jest przekazywany do open().

Pochodna Vulkan hw_device_t odpowiada pojedynczemu sterownikowi, który może obsługiwać wiele urządzeń fizycznych. Struktura hw_device_t może obejmować funkcje eksportu vkGetGlobalExtensionProperties(), vkCreateInstance() i vkGetInstanceProcAddr(). Program wczytujący może znaleźć wszystkie inne funkcje VkInstance(), VkPhysicalDevice()vkGetDeviceProcAddr(), wywołując vkGetInstanceProcAddr() struktury hw_device_t.

Od Androida 15 program wczytujący obsługuje APEX, aby wczytywać sterownik Vulkan. Ustaw ro.vulkan.apex na nazwę pakietu APEX Vulkan, aby załadować interfejs Vulkan z pakietu APEX.

Wykrywanie i wczytywanie warstw

Program ładujący Vulkan obsługuje wyliczanie i wczytywanie warstw, które mogą udostępniać dodatkowe rozszerzenia i przechwytywać wywołania podstawowych interfejsów API w drodze do sterownika. Android nie zawiera warstw w obrazie systemu, ale aplikacje mogą je uwzględniać w swoim pliku APK.

Pamiętaj, że model zabezpieczeń i zasady Androida znacznie różnią się od innych platform. W szczególności Android nie zezwala na wczytywanie kodu zewnętrznego do procesu, którego nie można debugować, na urządzeniach produkcyjnych (bez dostępu do roota) ani nie zezwala na sprawdzanie ani kontrolowanie pamięci, stanu itp. procesu przez kod zewnętrzny. Obejmuje to zakaz zapisywania na dysku zrzutów pamięci, śladów API itp. w celu późniejszego sprawdzenia. Na urządzeniach produkcyjnych włączone są tylko warstwy dostarczane w ramach aplikacji, których nie można debugować, a sterowniki nie mogą udostępniać funkcji, które naruszają te zasady.

Warstwy mogą być używane w tych przypadkach:

  • Warstwy czasu programowania – weryfikacja: warstwy i elementy pośredniczące do narzędzi śledzących, profilujących i debugujących nie powinny być instalowane w obrazie systemu na urządzeniach produkcyjnych. Warstwy weryfikacji i wstawki 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 programowania, mogą zmodyfikować pakiet aplikacji, np. dodając plik do katalogu bibliotek natywnych. Inżynierowie IHV i OEM, którzy chcą diagnozować błędy w przypadku aplikacji, których nie można modyfikować, mają dostęp do wersji obrazu systemu innych niż produkcyjne (z dostępem do roota), 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 urządzenia. Deweloperzy wybierają warstwy i ich wersje, które będą używane w ich aplikacji. Różne aplikacje korzystające z tej samej warstwy mogą używać różnych wersji. Deweloperzy wybierają, które z tych warstw mają być zawarte w pakiecie aplikacji.
  • Wstrzykiwane (niejawne) warstwy – obejmują warstwy takie jak liczba klatek na sekundę, nakładki sieci społecznościowych i programów uruchamiających gry dostarczane przez użytkownika lub inną aplikację bez wiedzy lub zgody aplikacji. Te naruszają zasady bezpieczeństwa Androida i nie są obsługiwane.

W przypadku aplikacji, których nie można debugować, program wczytujący wyszukuje warstwy tylko w katalogu bibliotek natywnych aplikacji i próbuje wczytać każdą bibliotekę o nazwie pasującej do określonego wzorca (np. libVKLayer_foo.so).

W przypadku aplikacji, które można debugować, program wczytujący wyszukuje warstwy w /data/local/debug/vulkan i próbuje wczytać dowolną bibliotekę pasującą do określonego wzorca.

Android umożliwia przenoszenie warstw ze zmianami w środowisku kompilacji między Androidem a innymi platformami. Szczegółowe informacje o interfejsie między warstwami a programem wczytującym znajdziesz w artykule Architecture of the Vulkan Loader Interfaces (w języku angielskim). Warstwy weryfikacji utrzymywane przez Khronos są hostowane w warstwach weryfikacji Vulkan.

Wersje i możliwości interfejsu Vulkan API

W tej tabeli 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 interfejsu Vulkan 1.3

Wulkan 1.3 wprowadza szereg wcześniej opcjonalnych rozszerzeń do podstawowych funkcji Vulkan. Większość tych funkcji została dodana w celu zwiększenia kontroli i szczegółowości interfejsu programowania Vulkan. Instancje przepustek renderowania jednoprzebiegowego nie potrzebują już obiektów przepustek renderowania ani buforów ramki. Można zmniejszyć łączną liczbę obiektów stanu potoku i zmienić sposób synchronizacji w interfejsie API. Vulkan 1.3 ma takie same wymagania sprzętowe jak Vulkan 1.2, 1.1 i 1.0. Większość implementacji znajduje się w sterowniku graficznym specyficznym dla układu SoC, a nie w platformie.

Najważniejsze funkcje interfejsu Vulkan 1.3 na Androidzie to:

  • Obsługa instancji pojedynczego przejścia renderowania
  • Obsługa natychmiastowego zakończenia wywołania shadera
  • Większa szczegółowość tworzenia, udostępniania i kontrolowania potoków

Vulkan 1.3 zawiera też kilka mniejszych funkcji i ulepszeń w zakresie użyteczności interfejsu API. Wszystkie zmiany wprowadzone w podstawowym interfejsie Vulkan API w ramach drobnej wersji 1.3 znajdziesz na stronie Core Revisions (Vulkan 1.3).

Omówienie funkcji interfejsu Vulkan 1.2

Wulkan 1.2 dodaje wiele funkcji i rozszerzeń, które upraszczają interfejs API. Obejmuje to ujednolicony model pamięci i dodatkowe informacje, o które można zapytać sterownik urządzenia. Wulkan 1.2 ma takie same wymagania sprzętowe jak Wulkan 1.0 i 1.1. Cała implementacja znajduje się w sterowniku graficznym specyficznym dla układu SoC, a nie w frameworku.

Najważniejszą funkcją Vulkan 1.2 dla 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 Vulkan API w ramach drobnej wersji 1.2 znajdziesz na stronie Core Revisions (Vulkan 1.2).

Omówienie funkcji interfejsu Vulkan 1.1

Vulkan 1.1 obsługuje interoperacyjność pamięci i synchronizacji, co umożliwia producentom OEM obsługę tej wersji na urządzeniach. Dodatkowo interoperacyjność pamięci/synchronizacji umożliwia programistom określenie, czy Vulkan 1.1 jest obsługiwany na urządzeniu, i skuteczne korzystanie z niego, gdy jest. Vulkan 1.1 ma takie same wymagania sprzętowe jak Vulkan 1.0, ale większość implementacji znajduje się w sterowniku graficznym specyficznym dla SOC, a nie w frameworku.

Najważniejsze funkcje interfejsu Vulkan 1.1 dla Androida to:

  • Obsługa importowania i eksportowania buforów pamięci oraz obiektów synchronizacji spoza Vulkan (w celu współdziałania 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 ramach drobnej wersji 1.1 znajdziesz na stronie Core Revisions (Vulkan 1.1).

Wybierz obsługę interfejsu Vulkan

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

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

Urządzenia z Androidem 10 powinny obsługiwać Vulkan 1.1.

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

Obsługa wersji interfejsu Vulkan

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

  1. Dodaj sterownik Vulkan, który obsługuje interesującą Cię wersję Vulkana (musi to być jedna z wersji 1.3, 1.1 lub 1.0) wraz z dodatkowymi wymaganiami CDD dotyczącymi wersji Androida. Możesz też zaktualizować istniejący sterownik Vulkan o niższym numerze wersji.
  2. W przypadku interfejsu Vulkan 1.3 lub 1.1 upewnij się, że funkcja systemowa zwrócona przez menedżera pakietów zwraca true dla prawidłowej wersji interfejsu Vulkan.
    • W przypadku interfejsu Vulkan 1.3 funkcja ta to PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x403000).
    • W przypadku interfejsu Vulkan 1.1 ta funkcja jest PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x401000).
    Menedżer pakietów zwróci true dla Vulkana 1.3 i Vulkana 1.1, dodając do odpowiedniego pliku device.mk regułę w postaci:
    • W przypadku interfejsu 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 interfejsu Vulkan 1.1 dodaj te informacje:
      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 do dostosowania wszystkich urządzeń z Androidem do najnowszego profilu Android Baseline 2022, zgodnie z przewodnikiem po profilu Android Baseline.

Każde urządzenie, które obsługuje Androida 14 lub nowszego i interfejs API Vulkan, musi spełniać wszystkie funkcje zdefiniowane w profilu Android Baseline 2021. Pełna lista wymaganych funkcji znajduje się w pliku profilu Vulkan json, ale kluczowy podzbiór wymaganych funkcji obejmuje:

  • Skompresowane tekstury w formatach ASTC i ETC.
  • Zmienne przestrzenie kolorów przez VK_EXT_swapchain_colorspace.
  • Próbkowanie cieniowania i interpolacja wielopróbkowa za pomocą funkcji sampleRateShading.

Integracja systemu okiennego (WSI)

libvulkan.so sterownik implementuje te rozszerzenia integracji systemu okien (WSI):

  • VK_KHR_surface
  • VK_KHR_android_surface
  • VK_KHR_swapchain
  • VK_KHR_driver_properties, zaimplementowane w przypadku Vulkan 1.1 tylko na Androidzie 10
  • VK_GOOGLE_display_timing, zaimplementowane w dowolnej wersji interfejsu Vulkan w Androidzie 10

Obiekty VkSurfaceKHRVkSwapchainKHR 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 udostępniane aplikacjom.

Flagi użycia Gralloc

Implementacje interfejsu Vulkan mogą wymagać przydzielania buforów łańcucha wymiany z prywatnymi flagami użycia Gralloc zdefiniowanymi przez implementację. Podczas tworzenia łańcucha wymiany 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ć pola *grallocConsumerUsage*grallocProducerUsage flagami użycia Gralloc wymaganymi w przypadku danego formatu i użycia. Flagi użycia zwracane przez sterownik są łączone z flagami użycia żądanymi przez odbiorcę łańcucha wymiany podczas przydzielania buforów.

Android 7.x wywołuje starszą wersję VkSwapchainImageUsageFlagsANDROID(), o nazwie vkGetSwapchainGrallocUsageANDROID(). Android 8.0 i nowsze wersje wycofują vkGetSwapchainGrallocUsageANDROID(), ale nadal wywołują vkGetSwapchainGrallocUsageANDROID(), jeśli vkGetSwapchainGrallocUsage2ANDROID() nie jest dostarczany przez sterownik:

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

vkGetSwapchainGrallocUsageANDROID() nie obsługuje flag użycia łańcucha wymiany ani rozszerzonych flag użycia Gralloc.

Obrazy obsługiwane przez Gralloc

VkNativeBufferANDROID to struktura vkCreateImage rozszerzenia do tworzenia obrazu obsługiwanego przez bufor Gralloc. VkNativeBufferANDROID jest przekazywany do vkCreateImage() w łańcuchu struktury VkImageCreateInfo. Połączenia z numerem vkCreateImage() z numeru VkNativeBufferANDROID są wykonywane podczas połączenia z numerem vkCreateSwapchainKHR. Implementacja WSI przydziela liczbę buforów natywnych wymaganych dla łańcucha 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 ma 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 udostępnia strukturę rozszerzenia VkSwapchainImageCreateInfoKHR w łańcuchu VkImageCreateInfo przekazywanym do vkCreateImage, gdy dla łańcucha wymiany wymagane są flagi użycia obrazu łańcucha wymiany. Struktura rozszerzenia zawiera flagi użycia obrazu łańcucha wymiany:

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ługujeVK_KHR_swapchain v70, więc aplikacja Vulkan może tworzyćVkImage z pamięcią łańcucha wymiany. Aplikacja najpierw wywołuje funkcję vkCreateImage ze strukturą VkImageSwapchainCreateInfoKHR połączoną ze strukturą VkImageCreateInfo. Następnie aplikacja wywołuje funkcję vkBindImageMemory2(KHR) ze strukturą VkBindImageMemorySwapchainInfoKHR połączoną ze strukturą VkBindImageMemoryInfo. Wartość imageIndex określona w strukturze VkBindImageMemorySwapchainInfoKHR musi być prawidłowym indeksem obrazu łańcucha wymiany. Platforma udostępnia strukturę rozszerzenia z odpowiednimi informacjami o buforze Gralloc do łańcucha VkBindImageMemoryInfo, dzięki czemu sterownik wie, z którym buforem Gralloc powiązać VkImage.VkNativeBufferANDROID

Pobieranie obrazów

vkAcquireImageANDROID przejmuje własność obrazu łańcucha wymiany i importuje do istniejącego obiektu VkSemaphore i istniejącego obiektu VkFence zewnętrznie sygnalizowany natywny płot:

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

vkAcquireImageANDROID() jest wywoływana podczas vkAcquireNextImageKHR, aby zaimportować natywny płot do obiektów VkSemaphoreVkFence dostarczonych przez aplikację (jednak zarówno obiekty semafora, jak i płotu są w tym wywołaniu opcjonalne). Sterownik może też wykorzystać tę okazję do rozpoznania i obsłużenia wszelkich zewnętrznych zmian stanu bufora Gralloc. Wiele sterowników nie będzie musiało niczego robić. To wywołanie umieszcza VkSemaphoreVkFence w tym samym stanie oczekiwania, co w przypadku sygnału wysyłanego przez vkQueueSubmit, dzięki czemu kolejki mogą czekać na semafor, a aplikacja może czekać na barierę.

Oba obiekty są sygnalizowane, gdy sygnalizuje je bazowy natywny obiekt bariery. Jeśli natywny obiekt bariery został już zasygnalizowany, semafor jest w stanie zasygnalizowanym, gdy ta funkcja zwraca wartość. Sterownik przejmuje własność deskryptora pliku bariery i zamyka go, gdy nie jest już potrzebny. Sterownik musi to zrobić nawet wtedy, gdy nie podano semafora ani obiektu bariery lub nawet wtedy, gdy funkcja vkAcquireImageANDROID zakończy się niepowodzeniem i zwróci błąd. Jeśli wartość fenceFd wynosi -1, oznacza to, że natywna bariera została już zasygnalizowana.

Zwalnianie obrazów

vkQueueSignalReleaseImageANDROID przygotowuje obraz łańcucha wymiany do użytku zewnętrznego, tworzy natywny sygnał i planuje jego wysłanie po wysłaniu sygnałów przez semafory 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 utworzyć natywną barierę, która nie wysyła sygnału, dopóki wszystkie semafory waitSemaphoreCountpWaitSemaphores nie wyślą sygnału i nie zostaną wykonane wszystkie dodatkowe czynności wymagane do przygotowania image do wyświetlenia.

Jeśli semafory oczekiwania (jeśli takie istnieją) zostały już zasygnalizowane, a queue jest już w stanie bezczynności, sterownik może ustawić *pNativeFenceFd na -1 zamiast rzeczywistego deskryptora pliku bariery natywnej, co oznacza, że nie ma na co czekać. Wywołujący jest właścicielem deskryptora pliku zwróconego w *pNativeFenceFd i zamyka go.

Wielu sterowników może zignorować parametr obrazu, ale niektóre mogą wymagać przygotowania struktur danych po stronie procesora powiązanych z buforem Gralloc do użycia przez zewnętrznych odbiorców obrazu. Przygotowywanie zawartości bufora do użycia przez odbiorców zewnętrznych powinno odbywać się asynchronicznie w ramach przekształcania obrazu w 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 wywoływania funkcji vkAcquireImageANDROID().

Obsługa udostępnianych obrazów

Niektóre urządzenia mogą współdzielić własność pojedynczego obrazu między potokiem wyświetlania a implementacją Vulkan, aby zminimalizować opóźnienie. W Androidzie 9 i nowszych wersjach program wczytujący warunkowo reklamuje rozszerzenie VK_KHR_shared_presentable_image na podstawie odpowiedzi sterownika 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ępnionych obrazów prezentowanych. W przeciwnym razie moduł wczytujący 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ć własność obrazu systemowi wyświetlania, ustawia wartość sharedImage na VK_TRUE.

Weryfikacja

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

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

Flaga funkcji Vulkan

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

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

  • Bity 0–15 przechowują rok.
  • Bity 16–23 przechowują miesiąc.
  • Bity 24–31 przechowują dzień.

Minimalna dozwolona wartość flagi funkcji to 0x07E30301, co odpowiada dacie 2019-03-01, która jest datą powiązaną z testami Vulkan dEQP na Androida 10. Jeśli flaga funkcji ma co najmniej tę wartość, urządzenie deklaruje, że przeszło wszystkie testy dEQP Vulkan w Androidzie 10.

Wartość 0x07E40301 odpowiada dacie 2020-03-01, która jest datą powiązaną z testami Vulkan dEQP na Androida 11. Jeśli flaga funkcji ma co najmniej tę wartość, urządzenie deklaruje, że przeszło wszystkie testy dEQP Vulkan w Androidzie 11.

Wartość 0x07E60301 odpowiada dacie 2022-03-01, która jest datą powiązaną z testami Vulkan dEQP na Androidzie 13. Jeśli flaga funkcji ma co najmniej tę wartość, urządzenie deklaruje, że przeszło wszystkie testy dEQP Vulkan w Androidzie 13.

Urządzenie, które udostępnia konkretną flagę funkcji (np. 0x07E30301, 0x07E40301, 0x07E60301), deklaruje, że przechodzi wszystkie testy dEQP Vulkan na Androidzie dotyczące tej flagi funkcji (odpowiednio Android 10, Android 11 i Android 13). To urządzenie może przejść testy dEQP Vulkana z późniejszej wersji Androida.

Vulkan dEQP jest częścią pakietu Android CTS. Od Androida 11 komponent CTS o nazwie dEQP test runner rozpoznaje android.software.vulkan.deqp.level flagę funkcji i pomija wszystkie testy Vulkan dEQP, które – zgodnie z tą flagą funkcji – urządzenie nie obsługuje. Takie testy są zgłaszane jako trywialnie zdane.