Implementieren Sie Vulkan

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

Um Vulkan erfolgreich zu implementieren, muss ein Gerät Folgendes enthalten:

  • Der Vulkan-Loader, bereitgestellt von Android.
  • Ein Vulkan-Treiber, der von SoCs wie GPU-IHVs bereitgestellt wird und die Vulkan-API implementiert. Um die Vulkan-Funktionalität zu unterstützen, 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 Treiberunterstützung anzufordern.

Wenn ein Gerät einen Vulkan-Treiber enthält, muss das Gerät die Systemfunktionen FEATURE_VULKAN_HARDWARE_LEVEL und FEATURE_VULKAN_HARDWARE_VERSION deklarieren, mit Versionen, die die Fähigkeiten des Geräts genau widerspiegeln. Dadurch wird sichergestellt, dass das Gerät dem Compatibility Definition Document (CDD) entspricht.

Vulkan-Loader

Der Vulkan-Loader platform/frameworks/native/vulkan ist die primäre Schnittstelle zwischen Vulkan-Apps und dem Vulkan-Treiber eines Geräts. Der Vulkan-Loader ist unter /system/lib[64]/libvulkan.so installiert. Der Loader stellt die zentralen Einstiegspunkte der Vulkan-API, die Einstiegspunkte der für das 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 Aufzählen und Laden von Ebenen, die zusätzliche Erweiterungen verfügbar machen und Kern-API-Aufrufe auf ihrem Weg zum Treiber abfangen können.

Das NDK enthält eine Stub libvulkan.so Bibliothek zum Verknüpfen. Die Bibliothek exportiert dieselben Symbole wie der Loader. 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 Ebene oder den entsprechenden Treiber weiterleiten. Der vkGet*ProcAddr() -Aufruf gibt die Funktionszeiger zurück, an die die Trampoline weiterleiten (d. h. er ruft direkt den Kern-API-Code auf). Der Aufruf über die Funktionszeiger statt über die exportierten Symbole ist effizienter, da Trampolin und Dispatch übersprungen werden.

Treiberaufzählung und -laden

Wenn das Systemabbild erstellt wird, erwartet Android, dass das System weiß, welche GPUs verfügbar sind. Der Loader 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 sind:

/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

In Android 7.0 und höher umschließt das Vulkan-Derivat hw_module_t eine einzelne hw_module_t Struktur; Es wird nur ein Treiber unterstützt und die konstante Zeichenfolge HWVULKAN_DEVICE_0 wird an open() übergeben.

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

Layer-Erkennung und -Laden

Der Vulkan-Loader unterstützt das Aufzählen und Laden von Schichten, die zusätzliche Erweiterungen verfügbar machen und Kern-API-Aufrufe auf ihrem Weg zum Treiber abfangen können. Android fügt keine Ebenen in das Systemabbild ein; 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 denen anderer Plattformen unterscheiden. Insbesondere erlaubt Android nicht das Laden von externem Code in einen nicht debuggbaren Prozess auf Produktionsgeräten (nicht gerootet) und erlaubt auch nicht, dass externer Code den Speicher, den Status usw. des Prozesses überprüft oder steuert. Dazu gehört das Verbot, Core-Dumps, API-Traces usw. zur späteren Überprüfung auf der Festplatte zu speichern. Auf Produktionsgeräten sind nur Ebenen aktiviert, die als Teil nicht debuggbarer Apps bereitgestellt werden, und Treiber dürfen keine Funktionen bereitstellen, die gegen diese Richtlinien verstoßen.

Zu den Anwendungsfällen für Ebenen gehören:

  • Entwicklungszeitschichten – Validierungsschichten und Shims für Tracing-/Profiling-/Debugging-Tools sollten nicht auf dem Systemabbild von Produktionsgeräten installiert werden. Validierungsebenen und Shims für Tracing-/Profiling-/Debugging-Tools sollten ohne Systemabbild aktualisierbar sein. Entwickler, die eine dieser Ebenen während der Entwicklung verwenden möchten, können das App-Paket ändern, indem sie beispielsweise eine Datei zu ihrem nativen Bibliotheksverzeichnis hinzufügen. Von IHV- und OEM-Ingenieuren, die Fehler beim Versand nicht veränderbarer Apps diagnostizieren möchten, wird davon ausgegangen, dass sie Zugriff auf nicht produktive (gerootete) Builds des Systemabbilds haben, es sei denn, diese Apps sind debuggbar. Weitere Informationen finden Sie unter Vulkan-Validierungsebenen auf Android .
  • Utility-Schichten – Diese Schichten stellen Erweiterungen bereit, beispielsweise eine Schicht, die einen Speichermanager für den Gerätespeicher implementiert. Entwickler wählen Ebenen und Versionen dieser Ebenen aus, die sie in ihrer App verwenden möchten. Verschiedene Apps, die dieselbe Ebene verwenden, können dennoch unterschiedliche Versionen verwenden. Entwickler wählen aus, welche dieser Ebenen in ihrem App-Paket enthalten sein sollen.
  • Injizierte (implizite) Ebenen – Umfasst Ebenen wie Bildrate, soziale Netzwerke und Game-Launcher-Overlays, die vom Benutzer oder einer anderen App ohne Wissen oder Zustimmung der App bereitgestellt werden. Diese 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 ).

Für debuggbare Apps sucht der Loader nach Ebenen in /data/local/debug/vulkan und versucht, jede Bibliothek zu laden, die einem bestimmten Muster entspricht.

Android ermöglicht die Portierung von Ebenen mit Änderungen der Build-Umgebung zwischen Android und anderen Plattformen. Einzelheiten zur Schnittstelle zwischen Schichten und dem Loader finden Sie unter Architektur der Vulkan-Loader-Schnittstellen . Die von Khronos verwalteten Validierungsschichten werden in Vulkan Validation Layers gehostet.

Vulkan-API-Versionen und -Funktionen

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

Funktionsübersicht von Vulkan 1.3

Vulkan 1.3 kanonisiert eine Reihe bisher optionaler Erweiterungen der Vulkan-Kernfunktionalität. Ein Großteil dieser Funktionalität ist mit der Absicht enthalten, die Kontrolle und Granularität über die Vulkan-Programmierschnittstelle zu erhöhen. Single-Pass-Renderpass-Instanzen benötigen keine Renderpass-Objekte oder Framebuffer mehr. Die Gesamtzahl der Pipeline-Statusobjekte kann reduziert werden und die Synchronisierung innerhalb der API wird überarbeitet. Vulkan 1.3 hat die gleichen Hardwareanforderungen wie Vulkan 1.2, 1.1 und 1.0, wobei der Großteil der Implementierung im SoC-spezifischen Grafiktreiber und nicht im Framework erfolgt.

Die wichtigsten Vulkan 1.3-Funktionen für Android sind:

  • Unterstützung für Single-Pass-Render-Pass-Instanzen
  • Unterstützung für das sofortige Beenden eines Shader-Aufrufs
  • Feinere Granularität bei der Erstellung, Freigabe und Steuerung von Pipelines

Vulkan 1.3 enthält außerdem mehrere kleinere Funktionen und Verbesserungen der API-Benutzerfreundlichkeit. Alle Änderungen, die mit der Nebenversion 1.3 an der Kern-Vulkan-API vorgenommen wurden, finden Sie unter Kernrevisionen (Vulkan 1.3) .

Funktionsübersicht von Vulkan 1.2

Vulkan 1.2 fügt eine Reihe von Funktionen und Erweiterungen hinzu, 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 die gleichen Hardwareanforderungen wie Vulkan 1.0 und 1.1; Die gesamte Implementierung erfolgt im SoC-spezifischen Grafiktreiber, nicht im Framework.

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

Vulkan 1.2 enthält außerdem mehrere kleinere Funktionen und Verbesserungen der API-Benutzerfreundlichkeit. Alle Änderungen, die mit der Nebenversion 1.2 an der Kern-Vulkan-API vorgenommen wurden, finden Sie unter „Kernrevisionen (Vulkan 1.2)“ .

Funktionsübersicht von Vulkan 1.1

Vulkan 1.1 bietet Unterstützung für Speicher-/Synchronisations-Interop, wodurch OEMs Vulkan 1.1 auf Geräten unterstützen können. Darüber hinaus ermöglicht die Speicher-/Synchronisations-Interop den Entwicklern, festzustellen, ob Vulkan 1.1 auf einem Gerät unterstützt wird, und es effektiv zu nutzen, wenn dies der Fall ist. Vulkan 1.1 hat die gleichen Hardwareanforderungen wie Vulkan 1.0, der Großteil der Implementierung erfolgt jedoch im SOC-spezifischen Grafiktreiber und nicht im Framework.

Die wichtigsten Vulkan 1.1-Funktionen für Android sind:

  • Unterstützung für den Import und Export von Speicherpuffern und Synchronisierungsobjekten von außerhalb von Vulkan (für die Zusammenarbeit 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-Benutzerfreundlichkeit. Alle Änderungen, die an der Kern-Vulkan-API mit der Nebenrevision 1.1 vorgenommen wurden, finden Sie unter Core Revisions (Vulkan 1.1) .

Wählen Sie Vulkan-Unterstützung

Android-Geräte sollten den fortschrittlichsten verfügbaren Vulkan-Funktionsumfang unterstützen, vorausgesetzt, sie unterstützen ein 64-Bit-ABI und verfügen nicht über wenig Speicher.

Geräte, die mit Android 13 und höher starten, 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.

Unterstützen Sie eine Vulkan-Version

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

  1. Fügen Sie neben den zusätzlichen CDD-Anforderungen der Android-Version einen Vulkan-Treiber hinzu, der die gewünschte Vulkan-Version unterstützt (dies muss eine der Vulkan-Versionen 1.3, 1.1 oder 1.0 sein). Alternativ können Sie einen vorhandenen Vulkan-Treiber mit einer niedrigeren Vulkan-Versionsnummer aktualisieren.
  2. Stellen Sie für Vulkan 1.3 oder 1.1 sicher, dass die vom Paketmanager zurückgegebene Systemfunktion für die richtige Vulkan-Version „ true zurückgibt.
    • Für Vulkan 1.3 lautet die Funktion PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x403000) .
    • Für Vulkan 1.1 lautet die Funktion PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x401000) .
    Der Paketmanager gibt für Vulkan 1.3 und Vulkan 1.1 true zurück, indem er einer entsprechenden Datei device.mk eine wie folgt dargestellte Regel hinzufügt.
    • Fügen Sie Folgendes für Vulkan 1.3 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 Folgendes für Vulkan 1.1 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 allen Android-Geräten, dem neuesten Android Baseline 2022-Profil zu entsprechen, wie im Android Baseline-Profilleitfaden beschrieben.

Jedes Gerät, das Android 14 oder höher und die Vulkan-API unterstützt, muss alle im Android Baseline 2021-Profil definierten Funktionen erfüllen. Die vollständige Liste der erforderlichen Funktionen ist in der json Datei des Vulkan-Profils aufgeführt, aber eine wichtige Teilmenge der erforderlichen Funktionen umfasst:

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

Fenstersystemintegration (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 Objekte VkSurfaceKHR und VkSwapchainKHR sowie alle Interaktionen mit ANativeWindow werden von der Plattform verarbeitet und sind keinen Treibern ausgesetzt. Die WSI-Implementierung basiert auf der Erweiterung VK_ANDROID_native_buffer , die vom Treiber unterstützt werden muss; Diese Erweiterung wird nur von der WSI-Implementierung verwendet und ist nicht für Apps verfügbar.

Gralloc-Nutzungsflags

Vulkan-Implementierungen erfordern möglicherweise die Zuweisung von Swapchain-Puffer mit durch die Implementierung definierten privaten Gralloc-Nutzungsflags. Beim Erstellen einer Swapchain fordert Android den Treiber auf, die angeforderten Format- und Bildnutzungsflags in Gralloc-Nutzungsflags zu übersetzen, indem es Folgendes aufruft:

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 format und imageUsage Parameter werden der VkSwapchainCreateInfoKHR Struktur entnommen. Der Treiber sollte *grallocConsumerUsage und *grallocProducerUsage mit den Gralloc-Nutzungsflags füllen, die für das Format und die Verwendung erforderlich sind. Die vom Treiber zurückgegebenen Nutzungsflags werden mit den vom Swapchain-Konsumenten beim Zuweisen von Puffern angeforderten Nutzungsflags kombiniert.

Android 7.x ruft eine frühere Version von VkSwapchainImageUsageFlagsANDROID() mit dem Namen vkGetSwapchainGrallocUsageANDROID() auf. Android 8.0 und höher veraltet vkGetSwapchainGrallocUsageANDROID() ruft jedoch weiterhin vkGetSwapchainGrallocUsageANDROID() auf, wenn vkGetSwapchainGrallocUsage2ANDROID() nicht vom Treiber bereitgestellt wird:

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

vkGetSwapchainGrallocUsageANDROID() unterstützt keine Swapchain-Nutzungsflags oder erweiterten Gralloc-Nutzungsflags.

Von Gralloc unterstützte Bilder

VkNativeBufferANDROID ist eine vkCreateImage Erweiterungsstruktur zum Erstellen eines Bildes, das durch einen Gralloc-Puffer unterstützt wird. VkNativeBufferANDROID wird vkCreateImage() in der VkImageCreateInfo Strukturkette bereitgestellt. Aufrufe von vkCreateImage() mit VkNativeBufferANDROID erfolgen während des Aufrufs von vkCreateSwapchainKHR . Die WSI-Implementierung weist die Anzahl der für die Swapchain angeforderten nativen Puffer zu und erstellt dann für jeden ein 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 Bildes verfügt VkImageCreateInfo über 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

In Android 8.0 und höher stellt die Plattform eine VkSwapchainImageCreateInfoKHR -Erweiterungsstruktur in der VkImageCreateInfo Kette bereit, die vkCreateImage bereitgestellt wird, wenn für die Swapchain Swapchain-Image-Nutzungsflags erforderlich sind. Die Erweiterungsstruktur enthält die Swapchain-Image-Nutzungsflags:

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

    VkSwapchainImageUsageFlagsANDROID      usage;
} VkSwapchainImageCreateInfoANDROID;

In Android 10 und höher unterstützt die Plattform VK_KHR_swapchain v70, sodass die Vulkan-App ein VkImage erstellen kann, das durch Swapchain-Speicher unterstützt wird. Die App ruft zunächst 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 mit der VkBindImageMemoryInfo Struktur verkettet ist. Der in der VkBindImageMemorySwapchainInfoKHR -Struktur angegebene imageIndex muss ein gültiger Swapchain-Bildindex sein. In der Zwischenzeit stellt die Plattform eine VkNativeBufferANDROID Erweiterungsstruktur mit den entsprechenden Gralloc-Pufferinformationen für die VkBindImageMemoryInfo Kette bereit, sodass der Treiber weiß, an welchen Gralloc-Puffer das VkImage gebunden werden soll.

Bilder erwerben

vkAcquireImageANDROID erwirbt den Besitz eines Swapchain-Images und importiert einen extern signalisierten nativen Fence 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 (bei diesem Aufruf sind jedoch sowohl Semaphor- als auch Fence-Objekte optional). Der Treiber kann diese Gelegenheit auch nutzen, um externe Änderungen am Gralloc-Pufferstatus zu erkennen und zu verarbeiten. Viele Autofahrer müssen hier nichts tun. Dieser Aufruf versetzt VkSemaphore und VkFence in den gleichen ausstehenden Status, als ob er durch vkQueueSubmit signalisiert würde, sodass Warteschlangen auf dem Semaphor und die App auf dem Fence warten können.

Beide Objekte werden signalisiert, wenn der darunter liegende natürliche Zaun signalisiert; Wenn der native Zaun bereits signalisiert hat, befindet sich das Semaphor im signalisierten Zustand, wenn diese Funktion zurückkehrt. Der Treiber übernimmt den Besitz 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 Semaphor noch ein Zaunobjekt bereitgestellt wird oder wenn vkAcquireImageANDROID fehlschlägt und einen Fehler zurückgibt. Wenn fenceFd -1 ist, ist es so, als ob der native Zaun bereits signalisiert wurde.

Bilder veröffentlichen

vkQueueSignalReleaseImageANDROID bereitet ein Swapchain-Image für die externe Verwendung vor, erstellt einen nativen Zaun und plant die Signalisierung des nativen Zauns, nachdem die Eingabesemaphoren signalisiert haben:

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

vkQueuePresentKHR() ruft vkQueueSignalReleaseImageANDROID() für die bereitgestellte Warteschlange auf. Der Treiber muss einen nativen Zaun erstellen, der kein Signal sendet, bis alle waitSemaphoreCount Semaphoren in pWaitSemaphores signalisieren und alle zusätzlichen Arbeiten, die zur Vorbereitung image für die Präsentation erforderlich sind, abgeschlossen sind.

Wenn die Warte-Semaphoren (falls vorhanden) bereits signalisiert haben und queue bereits inaktiv ist, kann der Treiber *pNativeFenceFd auf -1 anstelle eines tatsächlichen nativen Fence-Dateideskriptors setzen, um anzuzeigen, dass nichts zu warten ist. Der Aufrufer besitzt und schließt den in *pNativeFenceFd zurückgegebenen Dateideskriptor.

Viele Treiber können den Bildparameter ignorieren, einige müssen jedoch möglicherweise CPU-seitige Datenstrukturen vorbereiten, die einem Gralloc-Puffer zugeordnet sind, für die Verwendung durch externe Bildkonsumenten. Das Vorbereiten von Pufferinhalten für die Verwendung durch externe Verbraucher sollte asynchron im Rahmen des Übergangs des Bildes zu VK_IMAGE_LAYOUT_PRESENT_SRC_KHR erfolgen.

Wenn das Bild 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.

Gemeinsame Unterstützung für vorzeigbare Bilder

Einige Geräte können den Besitz eines einzelnen Bildes zwischen der Anzeigepipeline und der Vulkan-Implementierung teilen, um die Latenz zu minimieren. In Android 9 und höher kündigt der Loader bedingt die Erweiterung VK_KHR_shared_presentable_image an, 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, kündigt der Loader keine Unterstützung für gemeinsam genutzte vorzeigbare Bilder an. Andernfalls fragt der Loader 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 den Besitz eines Bildes mit dem Anzeigesystem teilen kann, legt er das sharedImage Mitglied auf VK_TRUE fest.

Validierung

OEMs können ihre Vulkan-Implementierung mit CTS testen, was Folgendes umfasst:

  • 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, das testet, ob das Gerät für die von ihm unterstützten Vulkan-Funktionen korrekt konfiguriert ist.

Vulkan-Feature-Flag

Ein Gerät, das Android 11 oder höher und die Vulkan-API unterstützt, muss ein Feature-Flag verfügbar machen: android.software.vulkan.deqp.level . Der Wert dieses Feature-Flags ist ein Datum, codiert als ganzzahliger Wert. Es gibt das Datum an, das mit den Vulkan dEQP-Tests verknüpft ist, die das Gerät angeblich bestanden hat.

Ein Datum der Form JJJJ-MM-TT wird wie folgt als 32-Bit-Ganzzahl kodiert:

  • Die Bits 0–15 speichern das Jahr
  • Die Bits 16–23 speichern den Monat
  • Die Bits 24–31 speichern den Tag

Der minimal zulässige Wert für das Feature-Flag ist 0x07E30301 , was dem Datum 2019-03-01 entspricht, dem Datum, das mit den Vulkan dEQP-Tests für Android 10 verknüpft ist. Wenn das Feature-Flag mindestens diesen Wert hat, behauptet das Gerät dies Bestehen Sie alle Android 10 Vulkan dEQP-Tests.

Der Wert 0x07E40301 entspricht dem Datum 01.03.2020, dem Datum, das mit den Vulkan dEQP-Tests für Android 11 verknüpft ist. Wenn das Feature-Flag mindestens diesen Wert aufweist, behauptet das Gerät, alle Vulkan dEQP-Tests für Android 11 zu bestehen.

Der Wert 0x07E60301 entspricht dem Datum 01.03.2022, dem Datum, das mit den Vulkan dEQP-Tests für Android 13 verknüpft ist. Wenn das Feature-Flag mindestens diesen Wert aufweist, behauptet das Gerät, alle Vulkan dEQP-Tests für Android 13 zu bestehen.

Ein Gerät, das ein bestimmtes Feature-Flag offenlegt ( z. B. 0x07E30301 , 0x07E40301 , 0x07E60301 ), behauptet, alle Android Vulkan dEQP-Tests dieses Feature-Flags zu bestehen (Android 10, Android 11 bzw. Android 13). Dieses Gerät besteht möglicherweise die Vulkan dEQP-Tests einer späteren Android-Version.

Vulkan dEQP ist Teil von Android CTS. Ab Android 11 kennt die dEQP-Testläuferkomponente von CTS das Feature-Flag android.software.vulkan.deqp.level und überspringt alle Vulkan-dEQP-Tests, die das Gerät laut diesem Feature-Flag nicht zu unterstützen behauptet. Es wird berichtet, dass solche Tests trivial bestanden werden.