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 zapewnia 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 prawidłowo zaimplementować 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 API Vulkana. 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, 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 urządzenie będzie zgodne z dokumentem definicji zgodności (CDD).

Wczytnik 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 pod adresem /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.

NDK zawiera stub biblioteki libvulkan.so do łączenia. Biblioteka eksportuje te same symbole co ładowarka. Aplikacje wywołują funkcje wyeksportowane z rzeczywistej biblioteki libvulkan.so, aby wywołać funkcje trampoliny w ładowarce, która przekazuje 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 głównego interfejsu API). Wywoływanie za pomocą wskaźników funkcji zamiast wyeksportowanych symboli jest wydajniejsze, ponieważ pomija trampolinę i wysyłanie.

Wyliczanie i wczytywanie sterownika

Gdy obraz systemu jest tworzony, Android oczekuje, że system będzie wiedzieć, które GPU są dostępne. W celu wykrycia i załadowania sterownika ładowarka korzysta z dotychczasowego mechanizmu HAL w hardware.h. 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 Vulkana hw_device_t odpowiada jednemu sterownikowi, 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.

Podczas korzystania z warstw 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 na dysku kopii pamięci, dzienników interfejsu API itp. na potrzeby 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 weryfikacyjnych i shimów 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. Zakłada się, że inżynierowie IHV i OEM, którzy chcą diagnozować 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 (domyślne) warstwy – obejmują warstwy takie jak częstotliwość wyświetlania klatek, sieć społecznościowa i nakładki w uruchomieniach gier, które są udostępniane przez użytkownika lub inną aplikację bez wiedzy lub zgody tej aplikacji. Te aplikacje naruszają zasady bezpieczeństwa Androida i nie są obsługiwane.

W przypadku aplikacji, których nie można debugować, ładowarka wyszukuje warstwy tylko w katalogu natywnej biblioteki aplikacji i próbuje załadować dowolną bibliotekę o nazwie pasującej do określonego wzorca (np. 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

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ż wiązać z obiektmi przejść renderowania ani z ramkami buforów. Łą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 układu SoC, a nie w ramach.

Najważniejsze funkcje Vulkan 1.3 na Androida:

  • Obsługa instancji przejść renderowania w pojedynczym przejeździe
  • Obsługa natychmiastowego zakończenia wywołania shadera
  • Bardziej szczegółowa kontrola nad tworzeniem, udostępnianiem i sterowaniem przepływem

Vulkan 1.3 zawiera też kilka mniejszych funkcji i ulepszeń interfejsu API. Wszystkie zmiany wprowadzone w podstawowym interfejsie Vulkan w wersji 1.3 znajdziesz w sekcji Podstawowe wersje (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 oraz dodatkowe informacje, które można uzyskać 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 i synchronizacji, co umożliwia producentom OEM obsługę Vulkan 1.1 na 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 na Androida:

  • Obsługa importowania i eksportowania buforów pamięci oraz obiektów synchronizacji spoza Vulkana (do współpracy z kamerą, 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).

Wybieranie obsługi Vulkana

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ć 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 Vulkana do niższej wersji.
  2. W przypadku Vulkana 1.3 lub 1.1 upewnij się, że funkcja systemu zwracana przez menedżera pakietów zwraca true dla prawidłowej wersji Vulkana.
    • W przypadku Vulkan 1.3 ta 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 Vulkana 1.3 dodaj:
      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 Vulkana 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, zgodnie z opisem w przewodniku po profilu Android Baseline.

Każde urządzenie obsługujące Androida 14 lub nowszego i interfejs 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.
  • Shading sample i interpolację multisample można uzyskać za pomocą 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żony 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ć pola *grallocConsumerUsage i *grallocProducerUsage flagami Gralloc wymaganymi dla formatu i użycia. 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 funkcja vkGetSwapchainGrallocUsageANDROID() jest wycofywana, ale nadal wywołuje funkcję vkGetSwapchainGrallocUsageANDROID(), jeśli kierowca nie poda vkGetSwapchainGrallocUsage2ANDROID():

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

vkGetSwapchainGrallocUsageANDROID() nie obsługuje flag użycia swapchain ani rozszerzonych flag użycia Gralloc.

Obrazy z obsługą Gralloc

VkNativeBufferANDROID to struktura rozszerzenia vkCreateImage służąca do tworzenia obrazu obsługiwanego przez bufor Gralloc. VkNativeBufferANDROID jest udostępniany vkCreateImage() w łańcuchu struktury VkImageCreateInfo. Połączenia z numerem vkCreateImage() z numerem VkNativeBufferANDROID występują podczas połączenia z numerem vkCreateSwapchainKHR. Implementacja WSI przydziela liczbę natywnych buforów żądanych dla swapchainu, 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 z podporą 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 udostępnia strukturę rozszerzenia VkSwapchainImageCreateInfoKHR w łańcuchu VkImageCreateInfo przekazywanym do vkCreateImage, gdy wymagane są flagi użycia obrazu swapchain. Struktura rozszerzenia zawiera flagi użycia obrazu w łańcuchu 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ł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. Wartość imageIndex określona w strukturze VkBindImageMemorySwapchainInfoKHR musi być prawidłowym indeksem obrazu swapchain. 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ć natywny obiekt ogrodzenia do obiektów VkSemaphoreVkFence udostępnianych przez aplikację (jednak w tym wywołaniu obiekty semaphore i fence są opcjonalne). Sterownik może też wykorzystać tę okazję do rozpoznania i obsługi wszelkich zewnętrznych zmian stanu bufora Gralloc. W przypadku wielu sterowników nie trzeba nic robić. To wywołanie powoduje, że VkSemaphoreVkFence przechodzą w taki sam stan oczekujący, jak gdyby sygnał został wysłany przez vkQueueSubmit. Dzięki temu kolejki mogą oczekiwać na semaforze, a aplikacja może oczekiwać na semafor.

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ść. Sterownik 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.

Publikowanie obrazów

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 zostały 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 konsumentów powinno odbywać się asynchronicznie w ramach przejścia obrazu do VK_IMAGE_LAYOUT_PRESENT_SRC_KHR.

Jeśli obraz został utworzony za pomocą VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID, kierowca musi zezwolić na wielokrotne wywoływanie funkcji vkQueueSignalReleaseImageANDROID() bez pośrednich wywołań funkcji vkAcquireImageANDROID().

Obsługa udostępnianych obrazów do prezentacji

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 Vulkana 1.1 ani rozszerzenia VK_KHR_physical_device_properties2, ładowarka nie reklamuje obsługi udostępnianych obrazów prezentacyjnych. 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 kodowana jako 32-bitowa liczba całkowita w ten 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 2020-03-01, która jest datą powiązaną z testami dEQP Vulkana dla Androida 11. Jeśli flaga funkcji ma co najmniej tę wartość, urządzenie twierdzi, że przeszło wszystkie testy dEQP Vulkana w Androidzie 11.

Wartość 0x07E60301 odpowiada dacie 2022-03-01, która jest datą związaną z testami dEQP Vulkan dla Androida 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 na Androidzie (Android 10, Android 11 lub Android 13) z tą flagą zostały zaliczone. To urządzenie może przejść testy dEQP Vulkana z późniejszej wersji Androida.

Vulkan dEQP jest częścią pakietu Android CTS. Począwszy 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 przechodzą.