Linee guida per la progettazione di Vulkan

Vulkan è diverso dalle API grafiche precedenti, in quanto i driver non eseguono determinate ottimizzazioni, come il riutilizzo della pipeline, per le app. Le app che usano Vulkan devono invece implementare le ottimizzazioni in modo autonomo. In caso contrario, potrebbero mostrare prestazioni peggiori rispetto alle app che eseguono OpenGL ES.

Quando le app implementano queste ottimizzazioni da soli, hanno il potenziale per farlo con maggiore successo rispetto al conducente, perché hanno accesso a informazioni più specifiche per un determinato caso d'uso. Di conseguenza, ottimizzare abilmente un'app che utilizza Vulkan può garantire prestazioni migliori rispetto a quando l'app utilizza OpenGL ES.

Questa pagina presenta diverse ottimizzazioni che la tua app Android può implementare per migliorare le prestazioni grazie a Vulkan.

Accelerazione hardware

La maggior parte dei dispositivi supporta Vulkan 1.1 tramite accelerazione hardware, mentre un piccolo sottoinsieme lo supporta tramite emulazione software. Le app possono rilevare un dispositivo Vulkan basato su software utilizzando vkGetPhysicalDeviceProperties e controllando il campo deviceType della struttura restituita. SwiftShader e altre implementazioni basate sulla CPU hanno il valore VK_PHYSICAL_DEVICE_TYPE_CPU. Le app possono verificare specificamente la presenza di SwiftShader controllando i campi vendorID e deviceID di questa stessa struttura per verificare la presenza di valori specifici di SwiftShader.

Le app critiche per le prestazioni dovrebbero evitare di utilizzare implementazioni Vulkan emulate a livello software e tornare a OpenGL ES.

Applica la rotazione dello schermo durante il rendering

Quando la direzione rivolta verso l'alto di un'app non corrisponde all'orientamento del display del dispositivo, il compositore ruota le immagini della swapchain dell'app in modo che corrispondano. Esegue questa rotazione mentre visualizza le immagini, con un conseguente consumo energetico, a volte notevolmente superiore, rispetto a quando non le ruotasse.

Al contrario, la rotazione delle immagini di swapchain durante la loro generazione comporta un consumo energetico minimo o superiore. Il campo VkSurfaceCapabilitiesKHR::currentTransform indica la rotazione che il compositore applica alla finestra. Dopo che un'app ha applicato la rotazione durante il rendering, utilizza il campo VkSwapchainCreateInfoKHR::preTransform per segnalare che la rotazione è stata completata.

Riduci al minimo i passaggi di rendering per frame

Nella maggior parte delle architetture di GPU per dispositivi mobili, l'inizio e la fine di un pass di rendering sono operazioni costose. La tua app può migliorare le prestazioni organizzando le operazioni di rendering nel minor numero possibile di passaggi di rendering.

Le diverse operazioni per il caricamento degli allegati e l'archivio degli allegati offrono livelli di prestazioni differenti. Ad esempio, se non hai bisogno di conservare i contenuti di un allegato, puoi utilizzare le versioni molto più veloci di VK_ATTACHMENT_LOAD_OP_CLEAR o VK_ATTACHMENT_LOAD_OP_DONT_CARE invece di VK_ATTACHMENT_LOAD_OP_LOAD. Allo stesso modo, se non devi scrivere in memoria i valori finali dell'allegato per utilizzarli in un secondo momento, puoi utilizzare VK_ATTACHMENT_STORE_OP_DONT_CARE per ottenere prestazioni di gran lunga migliori rispetto a VK_ATTACHMENT_STORE_OP_STORE.

Inoltre, nella maggior parte delle tessere di rendering, l'app non ha bisogno di caricare o archiviare l'allegato di profondità/stencil. In questi casi, puoi evitare di allocare la memoria fisica per il collegamento utilizzando il flag VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT durante la creazione dell'immagine del collegamento. Questo bit offre gli stessi vantaggi di glFramebufferDiscard in OpenGL ES.

Scegli i tipi di memoria appropriati

Per assegnare memoria del dispositivo, le app devono scegliere un tipo di memoria. Il tipo di memoria determina il modo in cui un'app può utilizzare la memoria e descrive anche le proprietà di memorizzazione e coerenza della memoria. Dispositivi diversi dispongono di tipi di memoria differenti; tipi di memoria differenti mostrano caratteristiche prestazionali differenti.

Un'app può utilizzare un semplice algoritmo per scegliere il tipo di memoria migliore per un determinato uso. Questo algoritmo seleziona il primo tipo di memoria nell'array VkPhysicalDeviceMemoryProperties::memoryTypes che soddisfa due criteri: il tipo di memoria deve essere consentito per il buffer o l'immagine e deve avere le proprietà minime richieste dall'app.

In genere, i sistemi mobile non dispongono di heap di memoria fisica separati per CPU e GPU. In questi sistemi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT non è così significativo quanto lo è nei sistemi che hanno GPU discrete con una propria memoria dedicata. Un'app non deve presupporre che questa proprietà sia obbligatoria.

Raggruppa gli insiemi di descrittori per frequenza

Se hai associazioni di risorse che cambiano a frequenze diverse, utilizza più set di descrittori per pipeline anziché riassociare tutte le risorse per ogni estrazione. Ad esempio, puoi avere un insieme di descrittori per le associazioni per scena, un altro per le associazioni per materiale e un terzo per le associazioni per istanza della rete mesh.

Utilizza costanti immediate per le modifiche con la frequenza più elevata, ad esempio le modifiche eseguite a ogni chiamata di disegno.