Design-Richtlinien für Vulkan

Im Gegensatz zu früheren Grafik-APIs führen Vulkan im Gegensatz zu früheren Grafik-APIs bestimmte Optimierungen nicht für Apps durch, z. B. die Wiederverwendung von Pipelines. Stattdessen müssen Apps, die Vulkan verwenden, solche Optimierungen selbst implementieren. Andernfalls haben sie unter Umständen eine schlechtere Leistung als Apps, auf denen OpenGL ES ausgeführt wird.

Wenn Anwendungen diese Optimierungen selbst implementieren, haben sie das Potenzial, dies erfolgreicher als der Treiber zu erreichen, da sie Zugriff auf spezifischere Informationen für einen bestimmten Anwendungsfall haben. Daher kann eine geschickte Optimierung einer App, die Vulkan nutzt, zu einer besseren Leistung führen als mit OpenGL ES.

Auf dieser Seite werden verschiedene Optimierungen vorgestellt, mit denen du deine Android-App implementieren kannst, um die Leistung von Vulkan zu steigern.

Hardwarebeschleunigung

Die meisten Geräte unterstützen Vulkan 1.1 über die Hardwarebeschleunigung, einige wenige Geräte dagegen durch Softwareemulation. Apps können ein softwarebasiertes Vulkan-Gerät mithilfe von vkGetPhysicalDeviceProperties erkennen und das Feld deviceType der zurückgegebenen Struktur prüfen. SwiftShader und andere CPU-basierte Implementierungen haben den Wert VK_PHYSICAL_DEVICE_TYPE_CPU. Apps können eine Prüfung speziell auf SwiftShader durchführen, indem die Felder vendorID und deviceID derselben Struktur auf SwiftShader-spezifische Werte geprüft werden.

Leistungskritische Apps sollten keine softwareemulierten Vulkan-Implementierungen verwenden und stattdessen auf OpenGL ES zurückgreifen.

Displaydrehung während des Renderings anwenden

Wenn die Richtung einer App nach oben nicht mit der Ausrichtung des Gerätebildschirms übereinstimmt, dreht der Compositor die Swapchain-Bilder der App so, dass sie übereinstimmen. Diese Rotation wird während der Anzeige der Bilder durchgeführt, was zu einem höheren Stromverbrauch – teilweise deutlich mehr – führt, als wenn die Bilder nicht gedreht werden würden.

Im Gegensatz dazu führt das Rotieren von Swapchain-Bildern beim Generieren der Bilder zu einem geringen oder gar keinen zusätzlichen Stromverbrauch. Das Feld VkSurfaceCapabilitiesKHR::currentTransform gibt die Drehung an, die der Compositor auf das Fenster anwendet. Nachdem eine App diese Rotation während des Renderings angewendet hat, meldet sie mithilfe des Felds VkSwapchainCreateInfoKHR::preTransform, dass die Rotation abgeschlossen ist.

Renderingdurchläufe pro Frame minimieren

Bei den meisten mobilen GPU-Architekturen ist das Starten und Beenden einer Renderingkarte ein teurer Vorgang. Deine App kann die Leistung verbessern, indem sie Renderingvorgänge in möglichst wenige Renderingdurchläufe einordnet.

Unterschiedliche Vorgänge beim Laden von Anhängen und Speichern von Anhängen bieten unterschiedliche Leistungsniveaus. Wenn Sie beispielsweise den Inhalt eines Anhangs nicht beibehalten müssen, können Sie anstelle von VK_ATTACHMENT_LOAD_OP_LOAD das viel schnellere VK_ATTACHMENT_LOAD_OP_CLEAR oder VK_ATTACHMENT_LOAD_OP_DONT_CARE verwenden. Wenn Sie die endgültigen Werte des Anhangs nicht zur späteren Verwendung in den Speicher schreiben müssen, können Sie mit VK_ATTACHMENT_STORE_OP_DONT_CARE eine viel bessere Leistung als VK_ATTACHMENT_STORE_OP_STORE erzielen.

Außerdem muss deine App bei den meisten Renderingdurchläufen den Tiefen-/Schablonenanhang nicht laden oder speichern. In solchen Fällen können Sie beim Erstellen des Anhangsbilds das Flag VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT verwenden, um zu vermeiden, dass dem Anhang physischen Arbeitsspeicher zugewiesen werden muss. Dieses Bit bietet dieselben Vorteile wie glFramebufferDiscard in OpenGL ES.

Geeignete Arbeitsspeichertypen auswählen

Bei der Zuweisung von Gerätespeicher müssen Apps einen Speichertyp auswählen. Der Speichertyp bestimmt, wie eine Anwendung den Speicher verwenden kann, und beschreibt auch die Caching- und Kohärenzeigenschaften des Arbeitsspeichers. Verschiedene Geräte haben unterschiedliche Speichertypen, die jeweils unterschiedliche Leistungsmerkmale aufweisen.

Eine Anwendung kann mit einem einfachen Algorithmus den besten Speichertyp für eine bestimmte Nutzung auswählen. Dieser Algorithmus wählt den ersten Speichertyp im Array VkPhysicalDeviceMemoryProperties::memoryTypes aus, der zwei Kriterien erfüllt: Der Speichertyp muss für den Zwischenspeicher oder das Image zulässig sein und die Mindesteigenschaften haben, die für die Anwendung erforderlich sind.

Mobile Systeme haben in der Regel keine separaten physischen Arbeitsspeicher-Heaps für CPU und GPU. Auf solchen Systemen ist VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT nicht so wichtig wie bei Systemen mit diskreten GPUs mit eigenem dediziertem Arbeitsspeicher. Eine App sollte nicht davon ausgehen, dass diese Property erforderlich ist.

Gruppendeskriptorsätze nach Häufigkeit

Wenn Sie Ressourcenbindungen haben, die sich in unterschiedlichen Häufigkeiten ändern, verwenden Sie mehrere Deskriptorsätze pro Pipeline, anstatt alle Ressourcen für jede Zeichnung neu zu binden. Sie können beispielsweise einen Satz von Deskriptoren für Bindungen pro Szene, einen anderen für Bindungen pro Material und einen dritten für Bindungen pro Mesh-Instanz verwenden.

Verwenden Sie sofortige Konstanten für die Änderungen mit der höchsten Häufigkeit, z. B. Änderungen, die bei jedem Zeichenaufruf ausgeführt werden.