Vulkan implementieren

Vulkan ist eine plattformübergreifende API mit geringem Overhead für leistungsstarke 3D-Grafiken. Ähnlich wie OpenGL ES (GLES) bietet Vulkan Tools zum Erstellen hochwertiger Echtzeitgrafiken in Apps. Zu den Vorteilen von Vulkan gehören eine Verringerung des CPU-Overheads und die Unterstützung der SPIR-V Binary Intermediate-Sprache.

Für die erfolgreiche Implementierung von Vulkan muss ein Gerät Folgendes enthalten:

  • Der Vulkan-Ladeprogramm von Android
  • Ein Vulkan-Treiber, der von SoCs wie GPU-IHVs bereitgestellt wird und die Vulkan API implementiert. Zur Unterstützung der Vulkan-Funktionalität benötigt das Android-Gerät Vulkan-fähige GPU-Hardware und den zugehörigen Treiber. Die GPU muss außerdem GLES 3.1 und höher unterstützen. Wenden Sie sich an Ihren SoC-Anbieter, um Treibersupport anzufordern.

Wenn ein Gerät einen Vulkan-Treiber enthält, müssen die FEATURE_VULKAN_HARDWARE_LEVEL- und FEATURE_VULKAN_HARDWARE_VERSION-Systemfunktionen mit Versionen deklariert werden, die die Fähigkeiten des Geräts genau widerspiegeln. Dadurch wird sichergestellt, dass das Gerät dem Kompatibilitätsdefinitionsdokument (CDD) entspricht.

Vulkan-Ladeprogramm

Der Vulkan-Ladeprogramm platform/frameworks/native/vulkan ist die primäre Schnittstelle zwischen Vulkan-Apps und dem Vulkan-Treiber eines Geräts. Der Vulkan-Ladeprogramm ist unter /system/lib[64]/libvulkan.so installiert. Der Loader stellt die Haupteinstiegspunkte der Vulkan API, die Einstiegspunkte der vom Android-CDD erforderlichen Erweiterungen und viele zusätzliche optionale Erweiterungen bereit. WSI-Erweiterungen (Window System Integration) werden vom Loader exportiert und hauptsächlich im Loader und nicht im Treiber implementiert. Der Loader unterstützt auch das Auflisten und Laden von Schichten, die zusätzliche Erweiterungen bereitstellen und API-Kernaufrufe auf dem Weg zum Treiber abfangen können.

Das NDK enthält eine Stub-libvulkan.so-Bibliothek für das Verknüpfen. Die Bibliothek exportiert dieselben Symbole wie der Lader. Apps rufen die aus der echten libvulkan.so-Bibliothek exportierten Funktionen auf, um Trampolinfunktionen in den Loader einzugeben, die basierend auf ihrem ersten Argument an die entsprechende Schicht oder den entsprechenden Treiber weitergeleitet werden. Der vkGet*ProcAddr()-Aufruf gibt die Funktionszeigers zurück, an die die Trampoline weitergeleitet werden (d. h., er ruft direkt den API-Kerncode auf). Der Aufruf über die Funktionszeiger statt über die exportierten Symbole ist effizienter, da das Trampolin übersprungen und die Weiterleitung übersprungen wird.

Treiberaufzählung und -Laden

Beim Erstellen des System-Images erwartet Android, dass das System weiß, welche GPUs verfügbar sind. Das Ladeprogramm verwendet den vorhandenen HAL-Mechanismus in hardware.h, um den Treiber zu erkennen und zu laden. Bevorzugte Pfade für 32-Bit- und 64-Bit-Vulkan-Treiber:

/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

Unter Android 7.0 und höher umschließt die Vulkan-hw_module_t-Ableitung ein einzelnes hw_module_t-Objekt. Es wird nur ein Treiber unterstützt und der konstante String HWVULKAN_DEVICE_0 wird an open() übergeben.

Das Vulkan-hw_device_t-Derivat entspricht einem einzelnen Treiber, der mehrere physische Geräte unterstützen kann. Die hw_device_t-Struktur kann erweitert werden, um vkGetGlobalExtensionProperties()-, vkCreateInstance()- und vkGetInstanceProcAddr()-Funktionen zu exportieren. Das Ladeprogramm kann alle anderen VkInstance()-, VkPhysicalDevice()- und vkGetDeviceProcAddr()-Funktionen finden, indem es die vkGetInstanceProcAddr() der hw_device_t-Struktur aufruft.

Ebenenerkennung und -ladevorgang

Der Vulkan-Ladeprogramm unterstützt das Auflisten und Laden von Schichten, die zusätzliche Erweiterungen bereitstellen und API-Kernaufrufe auf dem Weg zum Treiber abfangen können. Android enthält keine Ebenen im System-Image. Apps können jedoch Ebenen in ihrem APK enthalten.

Beachten Sie bei der Verwendung von Ebenen, dass sich das Sicherheitsmodell und die Richtlinien von Android erheblich von anderen Plattformen unterscheiden. Insbesondere erlaubt Android nicht, externen Code in einen nicht debuggbaren Prozess auf Produktionsgeräten (nicht gerootet) zu laden. Außerdem ist es nicht möglich, mit externem Code den Arbeitsspeicher, den Status usw. des Prozesses zu prüfen oder zu steuern. Dazu gehört auch das Verbot, Coredumps, API-Traces usw. zur späteren Prüfung auf dem Laufwerk zu speichern. Nur Ebenen, die im Rahmen nicht debugbarer Apps bereitgestellt werden, sind auf Produktionsgeräten aktiviert. Treiber dürfen keine Funktionen bereitstellen, die gegen diese Richtlinien verstoßen.

Anwendungsfälle für Ebenen:

  • Ebenen zur Entwicklungszeit: Validierungsebenen und Shims für Tracing-, Profiling- und Debugging-Tools sollten nicht auf dem System-Image von Produktionsgeräten installiert werden. Validierungsschichten und Shims für Tools zum Überwachen, Profilieren und Entwickeln sollten ohne System-Image aktualisierbar sein. Entwickler, die eine dieser Ebenen während der Entwicklung verwenden möchten, können das App-Paket ändern, indem sie beispielsweise dem Verzeichnis der nativen Bibliotheken eine Datei hinzufügen. IHV- und OEM-Entwickler, die Fehler bei der Bereitstellung nicht veränderbarer Apps diagnostizieren möchten, haben Zugriff auf nicht produktionsreife (gerootete) Builds des System-Images, es sei denn, diese Apps sind debugbar. Weitere Informationen finden Sie unter Vulkan-Validierungsebenen auf Android-Geräten.
  • Dienstebenen: Diese Ebenen stellen Erweiterungen bereit, z. B. eine Ebene, die einen Speichermanager für den Gerätespeicher implementiert. Entwickler wählen die Ebenen und Versionen dieser Ebenen für ihre App aus. Unterschiedliche Apps, die dieselbe Ebene verwenden, können jedoch unterschiedliche Versionen verwenden. Entwickler wählen aus, welche dieser Ebenen in ihrem App-Paket versendet werden.
  • Eingefügte (implizite) Ebenen: Dazu gehören Ebenen wie Overlays für Framerate, soziale Netzwerke und Game Launcher, die vom Nutzer oder einer anderen App ohne Wissen oder Einwilligung der App bereitgestellt werden. Sie verstoßen gegen die Sicherheitsrichtlinien von Android und werden nicht unterstützt.

Bei nicht debuggbaren Apps sucht der Loader nur im nativen Bibliotheksverzeichnis der App nach Ebenen und versucht, jede Bibliothek mit einem Namen zu laden, der einem bestimmten Muster entspricht (z. B. libVKLayer_foo.so).

Bei debugfähigen Apps sucht der Loader in /data/local/debug/vulkan nach Ebenen und versucht, alle Bibliotheken zu laden, die einem bestimmten Muster entsprechen.

Mit Android können Schichten mit Änderungen an der Build-Umgebung zwischen Android und anderen Plattformen portiert werden. Weitere Informationen zur Schnittstelle zwischen Schichten und dem Loader finden Sie unter Architektur der Vulkan-Ladeschnittstellen. Die von Khronos verwalteten Validierungsebenen werden in Vulkan-Validierungsebenen gehostet.

Vulkan API-Versionen und -Funktionen

In der folgenden Tabelle sind die Vulkan API-Versionen für verschiedene Android-Releases aufgeführt.
Android-Version Vulkan-Version
Android 13 Vulkan 1.3
Android 9 Vulkan 1.1
Android 7 Vulkan 1.0

Vulkan 1.3 – Funktionsübersicht

In Vulkan 1.3 werden eine Reihe zuvor optionaler Erweiterungen in die Vulkan-Kernfunktionen aufgenommen. Ein Großteil dieser Funktionen wird genutzt, um die Kontrolle und den Detaillierungsgrad der Vulkan-Programmierschnittstelle zu verbessern. Für Instanzen von Einzeldurchlauf-Renderpasses sind keine Renderpass-Objekte oder Framebuffer mehr erforderlich. Die Gesamtzahl der Pipelinestatusobjekte kann reduziert werden und die Synchronisierung innerhalb der API wird überarbeitet. Vulkan 1.3 hat dieselben Hardwareanforderungen wie Vulkan 1.2, 1.1 und 1.0. Der Großteil der Implementierung befindet sich im SoC-spezifischen Grafiktreiber und nicht im Framework.

Die wichtigsten Vulkan 1.3-Funktionen für Android:

  • Unterstützung für Instanzen von Renderpasses mit nur einem Durchlauf
  • Unterstützung für die sofortige Beendigung einer Shaderausführung
  • Detailliertere Kontrolle über das Erstellen, Freigeben und Verwalten von Pipelines

Vulkan 1.3 enthält außerdem mehrere kleinere Funktionen und Verbesserungen an der API-Nutzerfreundlichkeit. Alle Änderungen an der Vulkan-API mit der Minor-Version 1.3 finden Sie unter Core Revisions (Vulkan 1.3).

Vulkan 1.2 – Funktionsübersicht

Vulkan 1.2 bietet eine Reihe von Funktionen und Erweiterungen, die die API-Oberfläche vereinfachen. Dazu gehören ein einheitliches Speichermodell und zusätzliche Informationen, die von einem Gerätetreiber abgefragt werden können. Vulkan 1.2 hat dieselben Hardwareanforderungen wie Vulkan 1.0 und 1.1. Die gesamte Implementierung erfolgt im SoC-spezifischen Grafiktreiber, nicht im Framework.

Die wichtigste Vulkan 1.2-Funktion für Android ist die Unterstützung von 8‑Bit-Speicher.

Vulkan 1.2 enthält außerdem mehrere kleinere Funktionen und Verbesserungen an der API-Nutzerfreundlichkeit. Alle Änderungen an der Vulkan-Kern-API mit der Minor-Version 1.2 finden Sie unter Core Revisions (Vulkan 1.2).

Vulkan 1.1 – Funktionsübersicht

Vulkan 1.1 unterstützt die Interoperabilität von Arbeitsspeicher/Synchronisierung, wodurch OEMs Vulkan 1.1 auf Geräten unterstützen können. Außerdem können Entwickler dank der Interoperabilität von Speicher/Synchronisierung feststellen, ob Vulkan 1.1 auf einem Gerät unterstützt wird, und es dann effektiv nutzen. Vulkan 1.1 hat dieselben Hardwareanforderungen wie Vulkan 1.0, aber der Großteil der Implementierung befindet sich im SOC-spezifischen Grafiktreiber, nicht im Framework.

Die wichtigsten Vulkan 1.1-Funktionen für Android:

  • Unterstützung für den Import und Export von Zwischenspeichern und Synchronisierungsobjekten außerhalb von Vulkan (für Interoperabilität mit Kamera, Codecs und GLES)
  • Unterstützung für YCbCr-Formate

Vulkan 1.1 enthält außerdem mehrere kleinere Funktionen und Verbesserungen der API-Nutzerfreundlichkeit. Alle Änderungen, die an der Kern-Vulkan API mit Nebenversion 1.1 vorgenommen wurden, sind unter Core Revisions (Vulkan 1.1) verfügbar.

Vulkan-Unterstützung auswählen

Android-Geräte sollten die fortschrittlichsten verfügbaren Vulkan-Funktionen unterstützen, sofern sie ein 64‑Bit-ABI unterstützen und nicht zu wenig Arbeitsspeicher haben.

Geräte, die mit Android 13 und höher auf den Markt gebracht werden, sollten Vulkan 1.3 unterstützen.

Geräte, die über Android 10 gestartet werden, sollten Vulkan 1.1 unterstützen.

Andere Geräte können optional Vulkan 1.3, 1.2 und 1.1 unterstützen.

Vulkan-Version unterstützen

Ein Android-Gerät unterstützt eine Vulkan-Version, wenn die folgenden Bedingungen erfüllt sind:

  1. Füge neben den zusätzlichen CDD-Anforderungen der Android-Version einen Vulkan-Treiber hinzu, der die betreffende Vulkan-Version unterstützt (es muss die Vulkan-Version 1.3, 1.1 oder 1.0 sein). Alternativ können Sie einen vorhandenen Vulkan-Treiber mit einer niedrigeren Vulkan-Versionsnummer aktualisieren.
  2. Für Vulkan 1.3 oder 1.1 muss die vom Paketmanager zurückgegebene Systemfunktion true für die richtige Vulkan-Version zurückgeben.
    • Bei Vulkan 1.3 ist dies PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x403000).
    • Bei Vulkan 1.1 lautet die Funktion PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x401000).
    Der Paketmanager gibt true für Vulkan 1.3 und Vulkan 1.1 zurück, indem einer entsprechenden device.mk-Datei eine Regel wie unten gezeigt hinzugefügt wird.
    • Fügen Sie für Vulkan 1.3 Folgendes hinzu:
      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
      
    • Fügen Sie für Vulkan 1.1 Folgendes hinzu:
      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
      

Android-Baseline-Profil (ABP)

Wir empfehlen, dass alle Android-Geräte dem aktuellen Android Baseline 2022-Profil entsprechen, wie im Leitfaden für das Android Baseline-Profil beschrieben.

Jedes Gerät, das Android 14 oder höher sowie die Vulkan API unterstützt, muss alle im Android Baseline 2021-Profil definierten Funktionen erfüllen. Die vollständige Liste der erforderlichen Funktionen findest du in der Datei json des Vulkan-Profils. Zu den erforderlichen Funktionen gehören:

  • Komprimierte Texturen über ASTC und ETC.
  • Variable Farbräume über VK_EXT_swapchain_colorspace
  • Beispielschatten und Multisample-Interpolation über sampleRateShading

Windows-Systemintegration (WSI)

In libvulkan.so implementiert der Treiber die folgenden WSI-Erweiterungen (Window System Integration):

  • VK_KHR_surface
  • VK_KHR_android_surface
  • VK_KHR_swapchain
  • VK_KHR_driver_properties, nur für Vulkan 1.1 in Android 10 implementiert
  • VK_GOOGLE_display_timing, implementiert für jede Vulkan-Version in Android 10

Die VkSurfaceKHR- und VkSwapchainKHR-Objekte und alle Interaktionen mit ANativeWindow werden von der Plattform verarbeitet und sind für Fahrer nicht sichtbar. Die WSI-Implementierung basiert auf der Erweiterung VK_ANDROID_native_buffer, die vom Treiber unterstützt wird. Sie wird nur von der WSI-Implementierung verwendet und ist nicht für Anwendungen zugänglich.

Gralloc-Nutzungs-Flags

Bei Vulkan-Implementierungen müssen Swapchain-Buffer möglicherweise mit implementierungsdefinierten privaten Gralloc-Nutzungsflags zugewiesen werden. Beim Erstellen einer Swapchain fordert Android den Treiber auf, die angeforderten Format- und Image-Nutzungs-Flags in Gralloc-Nutzungs-Flags zu übersetzen. Dazu ruft Android Folgendes auf:

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
);

Die Parameter format und imageUsage werden aus der Struktur VkSwapchainCreateInfoKHR übernommen. Der Treiber sollte *grallocConsumerUsage und *grallocProducerUsage mit den für das Format und die Verwendung erforderlichen Gralloc-Nutzungsflags füllen. Die vom Treiber zurückgegebenen Nutzungsflags werden mit den Nutzungsflags kombiniert, die vom Swapchain-Nutzer beim Zuweisen von Buffers angefordert werden.

Android 7.x ruft eine frühere Version von VkSwapchainImageUsageFlagsANDROID() namens vkGetSwapchainGrallocUsageANDROID() auf. Mit Android 8.0 und höher wird vkGetSwapchainGrallocUsageANDROID() eingestellt. Es wird jedoch weiterhin vkGetSwapchainGrallocUsageANDROID() aufgerufen, wenn vkGetSwapchainGrallocUsage2ANDROID() nicht vom Treiber bereitgestellt wird:

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

vkGetSwapchainGrallocUsageANDROID() unterstützt keine Flags für die Swapchain-Nutzung und keine erweiterten Flags für die Gralloc-Nutzung.

Bilder mit Gralloc-Back-up

VkNativeBufferANDROID ist eine vkCreateImage-Erweiterungsstruktur zum Erstellen eines Bildes, das von einem Gralloc-Puffer unterstützt wird. VkNativeBufferANDROID wird in der Strukturkette VkImageCreateInfo für vkCreateImage() bereitgestellt. Anrufe an vkCreateImage() mit VkNativeBufferANDROID erfolgen während des Anrufs an vkCreateSwapchainKHR. Die WSI-Implementierung weist die Anzahl der für den Swapchain angeforderten nativen Buffers zu und erstellt dann für jeden eine VkImage:

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;

Beim Erstellen eines Gralloc-gestützten Bilds enthält VkImageCreateInfo die folgenden Daten:

  .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

Unter Android 8.0 und höher stellt die Plattform eine VkSwapchainImageCreateInfoKHR-Erweiterungsstruktur in der VkImageCreateInfo-Kette bereit, die an vkCreateImage übergeben wird, wenn Flags für die Verwendung von Swapchain-Images für den Swapchain erforderlich sind. Die Erweiterungsstruktur enthält die Flags für die Verwendung des Swapchain-Bilds:

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

    VkSwapchainImageUsageFlagsANDROID      usage;
} VkSwapchainImageCreateInfoANDROID;

Unter Android 10 und höher unterstützt die Plattform VK_KHR_swapchain v70. Die Vulkan-App kann also einen VkImage erstellen, der vom Swapchain-Speicher unterstützt wird. Die Anwendung ruft zuerst vkCreateImage mit einer VkImageSwapchainCreateInfoKHR-Struktur auf, die mit der VkImageCreateInfo-Struktur verkettet ist. Anschließend ruft die App vkBindImageMemory2(KHR) mit einer VkBindImageMemorySwapchainInfoKHR-Struktur auf, die an die VkBindImageMemoryInfo-Struktur angehängt ist. imageIndex muss ein gültiger Swapchain-Bildindex sein.VkBindImageMemorySwapchainInfoKHR Die Plattform stellt der VkBindImageMemoryInfo-Kette eine VkNativeBufferANDROID-Erweiterungsstruktur mit den entsprechenden Gralloc-Pufferinformationen zur Verfügung, damit der Treiber weiß, mit welchem Gralloc-Puffer die VkImage verknüpft werden soll.

Bilder aufnehmen

vkAcquireImageANDROID übernimmt die Inhaberschaft eines Swapchain-Bilds und importiert eine extern signalisierte native Barriere sowohl in ein vorhandenes VkSemaphore-Objekt als auch in ein vorhandenes VkFence-Objekt:

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

vkAcquireImageANDROID() wird während vkAcquireNextImageKHR aufgerufen, um einen nativen Zaun in die von der App bereitgestellten VkSemaphore- und VkFence-Objekte zu importieren. In diesem Aufruf sind jedoch sowohl Semaphore- als auch Fence-Objekte optional. Der Treiber kann diese Gelegenheit auch nutzen, um externe Änderungen am Gralloc-Pufferstatus zu erkennen und zu verarbeiten. Bei vielen Treibern ist hier jedoch nichts zu tun. Durch diesen Aufruf werden VkSemaphore und VkFence in denselben ausstehenden Status versetzt, als wäre dies durch vkQueueSubmit signalisiert worden. So können Warteschlangen auf die Semaphore und die App auf den Fence warten.

Beide Objekte werden signalisiert, wenn das zugrunde liegende native Fence-Signal gesendet wird. Wenn das native Fence bereits signalisiert wurde, befindet sich das Semaphore im Status „Signalisiert“, wenn diese Funktion zurückgegeben wird. Der Fahrer übernimmt die Inhaberschaft des Fence-Dateideskriptors und schließt den Fence-Dateideskriptor, wenn er nicht mehr benötigt wird. Der Treiber muss dies auch dann tun, wenn weder ein Semaphore- noch ein Fence-Objekt bereitgestellt wird oder wenn vkAcquireImageANDROID fehlschlägt und einen Fehler zurückgibt. Wenn fenceFd = -1 ist, wird der native Zaun bereits signalisiert.

Bilder veröffentlichen

vkQueueSignalReleaseImageANDROID bereitet ein Swapchain-Image für die externe Verwendung vor, erstellt eine native Barriere und plant, dass die native Barriere signalisiert wird, nachdem die Eingabe-Semaphoren signalisiert wurden:

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

vkQueuePresentKHR() ruft vkQueueSignalReleaseImageANDROID() in der angegebenen Warteschlange auf. Der Fahrer muss einen nativen Zaun erzeugen, der erst dann ein Signal sendet, wenn alle waitSemaphoreCount-Semaphoren im pWaitSemaphores-Signal und alle zusätzlichen Arbeiten erforderlich sind, um image für die Präsentation vorzubereiten.

Wenn die Wartesemaphoren (falls vorhanden) bereits signalisiert werden und queue bereits inaktiv ist, kann der Treiber *pNativeFenceFd auf -1 anstelle eines tatsächlichen nativen Fence-Dateideskriptors setzen. Dadurch wird angegeben, dass nichts gewartet werden muss. Der Aufrufer ist Inhaber des in *pNativeFenceFd zurückgegebenen Dateideskriptors und schließt ihn.

Viele Treiber können den Bildparameter ignorieren, einige müssen jedoch möglicherweise CPU-seitige Datenstrukturen vorbereiten, die mit einem Gralloc-Puffer verknüpft sind, um sie von externen Bildverbrauchern verwenden zu lassen. Die Vorbereitung des Zwischenspeicherinhalts für die Verwendung durch externe Nutzer sollte asynchron im Rahmen der Umstellung des Images auf VK_IMAGE_LAYOUT_PRESENT_SRC_KHR erfolgen.

Wenn das Image mit VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID erstellt wurde, muss der Treiber zulassen, dass vkQueueSignalReleaseImageANDROID() wiederholt aufgerufen wird, ohne dass dazwischen Aufrufe von vkAcquireImageANDROID() erfolgen.

Unterstützung für freigegebene Bilder

Auf einigen Geräten kann die Inhaberschaft eines einzelnen Bildes zwischen der Displaypipeline und der Vulkan-Implementierung geteilt werden, um die Latenz zu minimieren. Unter Android 9 und höher bewirbt der Lader die VK_KHR_shared_presentable_image-Erweiterung bedingt, basierend auf der Antwort des Treibers auf einen Aufruf von vkGetPhysicalDeviceProperties2.

Wenn der Treiber weder Vulkan 1.1 noch die Erweiterung VK_KHR_physical_device_properties2 unterstützt, gibt der Loader keine Unterstützung für freigegebene, darstellbare Bilder an. Andernfalls fragt der Lader die Treiberfunktionen ab, indem er vkGetPhysicalDeviceProperties2() aufruft und die folgende Struktur in die VkPhysicalDeviceProperties2::pNext-Kette einfügt:

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

Wenn der Treiber die Eigentumsrechte an einem Bild mit dem Anzeigesystem teilen kann, wird das Mitglied sharedImage auf VK_TRUE gesetzt.

Zertifizierungsstufe

OEMs können ihre Vulkan-Implementierung mit CTS testen. Dazu gehören:

  • Khronos Vulkan-Konformitätstests im CtsDeqpTestCases-Modul, einschließlich funktionaler API-Tests für Vulkan 1.0, 1.1, 1.2 und 1.3.
  • Das CtsGraphicsTestCases-Modul, mit dem geprüft wird, ob das Gerät für die unterstützten Vulkan-Funktionen richtig konfiguriert ist.

Vulkan-Feature-Flag

Für die Freigabe eines Feature-Flags (android.software.vulkan.deqp.level) ist ein Gerät erforderlich, das Android 11 oder höher und die Vulkan API unterstützt. Der Wert dieses Feature-Flags ist ein Datum, das als Ganzzahl codiert ist. Hier wird das Datum der Vulkan-dEQP-Tests angegeben, die das Gerät angeblich bestanden hat.

Ein Datum im Format JJJJ-MM-TT wird wie folgt als 32-Bit-Ganzzahl codiert:

  • 0–15 Bits pro Jahr
  • In den Bits 16–23 wird der Monat gespeichert.
  • 24–31 Bits

Der Mindestwert für das Funktions-Flag ist 0x07E30301. Dieser Wert entspricht dem 01.03.2019, dem Datum, das den Vulkan-dEQP-Tests für Android 10 zugeordnet ist. Wenn das Funktions-Flag mindestens diesen Wert hat, gibt das Gerät an, alle Android 10-Vulkan dEQP-Tests bestanden zu haben.

Der Wert 0x07E40301 entspricht dem Datum 01.03.2020, also dem Datum, das den Vulkan-dEQP-Tests für Android 11 zugeordnet ist. Wenn das Flag für die Funktion mindestens diesen Wert hat, soll das Gerät alle Vulkan-dEQP-Tests von Android 11 bestehen.

Der Wert 0x07E60301 entspricht dem Datum 01.03.2022, das mit den Vulkan-dEQP-Tests für Android 13 verknüpft ist. Wenn das Feature-Flag mindestens diesen Wert hat, wird angegeben, dass das Gerät alle Android 13-Vulkan-dEQP-Tests besteht.

Ein Gerät, das ein bestimmtes Funktionsflag (z. B. 0x07E30301, 0x07E40301, 0x07E60301) anzeigt, soll alle Android Vulkan dEQP-Tests für dieses Funktionsflag bestehen (Android 10, Android 11, Android 13). Dieses Gerät kann Vulkan-dEQP-Tests aus einer neueren Android-Version bestehen.

Vulkan dEQP ist Teil der CTS von Android. Ab Android 11 erkennt die dEQP-Test-Runner-Komponente der CTS das android.software.vulkan.deqp.level-Funktionsflag und überspringt alle Vulkan-dEQP-Tests, die das Gerät gemäß diesem Funktionsflag nicht unterstützt. Solche Tests werden als trivial bestanden gemeldet.