Raccolta del pacing del frame Parte del Android Game Development Kit.
La libreria Android Frame Pacing, nota anche come CHANGEpy, fa parte delle AGDK Libraries. Consente ai giochi OpenGL e Vulkan di ottenere un rendering fluido e il pacing dei frame corretto su Android. Questo documento definisce il pacing dei frame, descrive situazioni in cui è necessario il pacing dei frame e mostra in che modo la libreria queste situazioni. Se vuoi passare direttamente all'implementazione del pacing frame gioco, consulta la sezione Passaggio successivo.
Premessa
Il pacing dei frame è la sincronizzazione della logica di un gioco e del ciclo di rendering con il sottosistema di visualizzazione di un sistema operativo e l'hardware di visualizzazione sottostante. Android Il sottosistema display è stato progettato per evitare artefatti visivi (noti come tealing) che possono verificarsi quando l'hardware del display passa parzialmente a una nuova cornice tramite un aggiornamento. Per evitare questi artefatti, il sottosistema Display esegue le seguenti:
- Memorizza internamente i frame oltre i frame
- Rileva gli invii tardivi di frame
- Ripete la visualizzazione dei frame precedenti quando vengono rilevati frame finali
Un gioco informa
SurfaceFlinger
il compositore all'interno del sottosistema display, deve aver inviato
necessarie per un frame (chiamando eglSwapBuffers
o vkQueuePresentKHR
).
SurfaceFlinger segnala la disponibilità di un fotogramma all'hardware del display utilizzando una
chiavistello. L'hardware del display mostra quindi il frame in questione. L'hardware del display
a una frequenza costante, ad esempio 60 Hz, e se non c'è un nuovo fotogramma quando
l'hardware ne ha bisogno, l'hardware visualizza di nuovo il frame precedente.
Spesso si verificano tempi di frame incoerenti quando il loop di rendering di un gioco esegue il rendering diversa rispetto all'hardware del display nativo. Se un gioco viene eseguito a 30 f/s tenta di eseguire il rendering su un dispositivo che supporta in modo nativo i 60 FPS, il rendering del gioco non rileva che un frame ripetuto rimane sullo schermo per altri 16 millisecondi. Questa disconnessione di solito crea notevoli incoerenze nell'inquadratura volte, ad esempio 49 millisecondi, 16 millisecondi, 33 millisecondi. Eccessiva scene complesse aggravano ulteriormente il problema, poiché causano la perdita di frame che si verificano.
Soluzioni non ottimali
In passato, i giochi hanno adottato le seguenti soluzioni per il pacing dei frame e spesso comportano tempi di frame incoerenti e una maggiore latenza di input.
Invia frame con la velocità consentita dall'API di rendering
Questo approccio collega un gioco all'attività variabile di SurfaceFlinger e introduce una frame di latenza aggiuntivo. La pipeline di visualizzazione contiene una coda di frame, tipicamente di dimensione 2, che si riempie se il gioco cerca di presentare anche dei frame rapidamente. Senza più spazio nella coda, viene avviato il ciclo di gioco (o almeno thread di rendering) è bloccato da una chiamata OpenGL o Vulkan. Il gioco è quindi costretto ad attendere che l'hardware del display mostri una cornice e questa sincronizza i due componenti. Questa situazione è nota come buffer-stuffing o coda in eccesso. Processo del renderer non si rende conto di cosa stia succedendo, quindi l'incoerenza della frequenza fotogrammi peggiora. Se input di campioni di gioco prima del frame, la latenza di input peggiora.
Utilizzare Android Choreographer da solo
Per la sincronizzazione viene usato anche Android Choreographer. Questo componente, disponibile in Java dall'API 16 e in C++ dall'API 24, offre tick regolari la stessa frequenza del sottosistema display. Ci sono ancora sottigliezze quando questo segno di spunta viene fornito rispetto all'effettivo VSYNC hardware e questi che variano in base al dispositivo. Il buffer-stuffing potrebbe comunque verificarsi per i frame lunghi.
Vantaggi della libreria di pacing del frame
La libreria Pacing frame utilizza Android Choreographer per la sincronizzazione e che gestisce la variabilità dell'invio dei segni di graduazione. Utilizza la presentazione i timestamp per assicurarti che i frame siano presentati al momento giusto e sincronizzare le barriere per evitare il buffering. La libreria utilizza NDK Choreographer, se disponibile e torna a Java Choreographer se non lo è.
La libreria gestisce più frequenze di aggiornamento se sono supportate dal dispositivo, il che offre a un gioco maggiore flessibilità nel presentare un frame. Ad esempio, per un dispositivo che supporta una frequenza di aggiornamento a 60 Hz e a 90 Hz, un gioco che non a 60 frame al secondo possono scendere a 45 FPS anziché 30 FPS per liscia. La raccolta rileva la frequenza fotogrammi del gioco prevista e regola automaticamente il frame di presentazione di conseguenza. La libreria di pacing del frame migliora anche la batteria poiché evita aggiornamenti non necessari del display. Ad esempio, se un gioco viene rendering a 60 f/s ma il display si aggiorna a 120 Hz, lo schermo aggiornati due volte per ogni frame. La libreria di pacing del frame evita questo problema impostando la frequenza di aggiornamento al valore supportato dal dispositivo più vicino al target frequenza fotogrammi.
Come funziona
Le seguenti sezioni mostrano in che modo la libreria di pacing del frame gestisce le offerte di tipo lungo e frame di gioco brevi per ottenere un corretto pacing dei frame.
Frequenza fotogrammi corretta a 30 Hz
Quando si esegue il rendering a 30 Hz su un dispositivo a 60 Hz, la situazione ideale su Android è come mostrato nella figura 1. SurfaceFlinger blocca i nuovi buffer grafici, se presenti (NB in Il diagramma indica "nessun buffer" attuale e la precedente si ripete).
Figura 1. Ritmo di frame ideale a 30 Hz su un dispositivo a 60 Hz
I fotogrammi dei giochi brevi causano lo stuttering
Sulla maggior parte dei dispositivi moderni, i motori di gioco si basano sul coreografo della piattaforma l'invio di tic per favorire l'invio dei frame. Tuttavia, c'è ancora possibilità di un pacing di frame non corretto a causa di frame brevi, come mostrato nella Figura 2. I frame brevi seguiti da frame lunghi vengono percepiti dal player come stuttering.
Figura 2. Il frame C di un gioco breve fa sì che il frame B presenti un solo frame, seguiti da più frame C.
La libreria Pacing del frame risolve questo problema utilizzando i timestamp della presentazione. La
utilizza le estensioni timestamp della presentazione
EGL_ANDROID_presentation_time
e
VK_GOOGLE_display_timing
in modo che i frame non vengano presentati per tempo, come si vede nella figura 3.
Figura 3. Il frame di gioco B è stato presentato due volte per un display più fluido
I frame lunghi causano stuttering e latenza
Quando il carico di lavoro della visualizzazione richiede più tempo di quello dell'applicazione, vengono applicate vengono aggiunti a una coda. Questo porta, ancora una volta, a stuttering e potrebbe anche a un ulteriore frame di latenza dovuto al riempimento del buffer (vedi figura 4). La oltre a rimuovere lo stuttering e i frame di latenza aggiuntivi.
Figura 4. Il frame lungo B restituisce un pacing errato per due frame: A e B
La libreria risolve questo problema usando le barriere di sincronizzazione
(EGL_KHR_fence_sync
)
e
VkFence
)
inserire tempi di attesa nell'applicazione che consentano alla pipeline di visualizzazione di rilevare
piuttosto che aumentare la pressione negativa. Il frame A presenta comunque
frame aggiuntivo, ma il frame B ora si presenta correttamente, come mostrato nella figura 5.
Figura 5. I frame C e D attendono la presentazione
Modalità operative supportate
Puoi configurare la libreria di pacing del frame in modo che funzioni in uno dei tre seguenti modalità:
- Modalità automatica disattivata + pipeline
- Modalità automatica attivata + pipeline
- Modalità automatica attivata + modalità pipeline automatica (pipeline/non pipeline)
Modalità consigliata
Puoi sperimentare sia le modalità automatica che quelle pipeline, ma inizia attivando e includere quanto segue dopo l'inizializzazione di Spotpy:
swappyAutoSwapInterval(false);
swappyAutoPipelineMode(false);
swappyEnableStats(false);
swappySwapIntervalNS(1000000000L/yourPreferredFrameRateInHz);
Modalità pipeline
Per coordinare i carichi di lavoro del motore, la libreria in genere utilizza un modello di pipeline che separa i carichi di lavoro di CPU e GPU oltre i confini VSYNC.
Figura 6. Modalità pipeline
Modalità non pipeline
In generale, questo approccio si traduce in una schermata di input più bassa e più prevedibile una latenza di pochi millisecondi. Nei casi in cui la durata frame di un gioco è molto ridotta, sia la CPU che la GPU possono rientrare in un singolo intervallo di scambio. In questo caso, uno stato non pipeline otterrebbe effettivamente una latenza inferiore nella schermata di input.
Figura 7. Modalità non pipeline
Modalità Automatica
La maggior parte dei giochi non sa come scegliere l'intervallo di scambio, che è la durata ogni frame (ad esempio, 33,3 ms per 30 Hz). Su alcuni dispositivi, il rendering di un gioco può essere eseguito a 60 FPS, mentre su un altro potrebbe essere necessario scendere a un livello inferiore valore. La modalità automatica misura i tempi di CPU e GPU per:
- Seleziona automaticamente intervalli di scambio: giochi che hanno una frequenza di 30 Hz in alcuni casi. e 60 Hz in altri possono consentire alla libreria di regolare questo intervallo in modo dinamico.
- Disattiva le pipeline per frame ultraveloci: consente di ottimizzare latenza della schermata di input in tutti i casi.
Più frequenze di aggiornamento
I dispositivi che supportano diverse frequenze di aggiornamento offrono una maggiore flessibilità scegliendo un intervallo di scambio uniforme:
- Su dispositivi a 60 Hz: 60 f/s/30 f/s/20 f/s
- Su dispositivi a 60 Hz + 90 Hz: 90 f/s/60 f/s/45 f/s/30 f/s
- Su dispositivi a 60 Hz + 90 Hz + 120 Hz: 120 f/s/90 f/s/60 f/s/45 f/s/ 40 f/s/30 f/s
La libreria sceglie la frequenza di aggiornamento che meglio corrisponde al rendering effettivo dei frame di un gioco, per una migliore esperienza visiva.
Per ulteriori informazioni sul pacing di frame con frequenza di aggiornamento multipla, consulta Rendering con frequenza di aggiornamento elevata su Android post del blog.
Statistiche cornice
La libreria Pacing del frame offre le seguenti statistiche per il debug e finalità di profilazione:
- Un istogramma del numero di schermate aggiorna un frame aspettato nel del compositore al termine del rendering.
- Un istogramma del numero di aggiornamenti dello schermo passati tra le richieste di presentazione e il momento attuale.
- Un istogramma del numero di aggiornamenti dello schermo passati tra due aggiornamenti consecutivi i frame.
- Un istogramma del numero di aggiornamenti dello schermo trascorso tra l'inizio di per questo frame e per il tempo attuale effettivo.
Passaggio successivo
Consulta una delle seguenti guide per integrare la libreria di pacing del frame Android nel tuo gioco:
- Integrare il pacing frame Android nel renderer OpenGL
- Integrare il pacing frame Android nel renderer Vulkan