Prestazioni WebGL
WebGL ha una cattiva reputazione: si pensa che WebGL sia lento e incapace di renderizzare grafica 3D complessa. Molti esempi dimostrano che non è vero, eppure l’esperienza degli sviluppatori continua a rafforzare questa idea.
L’hardware che esegue il codice WebGL non è limitato per i browser. Allora perché gli sviluppatori credono che sia impossibile renderizzare grafica 3D veloce sul web?
Questo articolo ti guiderà attraverso le prestazioni di WebGL e come anche tu puoi ottenere un rendering 3D veloce sul web.
CPU vs GPU
In un’applicazione 3D, parte del codice viene eseguito sulla CPU e parte su hardware accelerato, la GPU.
WebGL è progettato per permettere l’uso della GPU per accelerare le applicazioni grafiche sul web, quindi si può capire come una serie di funzioni che inviano lavoro all’hardware grafico e ne recuperano il risultato.
Il codice che crea lavoro per la GPU viene eseguito sulla CPU e lo controlliamo tramite JavaScript.
Sovraccarico del Browser
Poiché uno degli obiettivi del browser è proteggere l’utente da potenziali siti web dannosi, verificherà la sicurezza di ogni chiamata WebGL fatta dal sito tramite JavaScript. Deve anche isolare il processo che esegue il codice del sito e qualsiasi chiamata da e verso questo processo deve essere convertita in un formato inviabile, chiamato “marshalling”.
Sia il marshalling che la verifica delle chiamate WebGL del sito comportano un lavoro che aggiunge un costo in termini di prestazioni rispetto alla stessa chiamata in un ambiente nativo.
Evitare le Chiamate WebGL
Per ottenere prestazioni WebGL, dovremmo quindi evitare di utilizzare chiamate che hanno un alto sovraccarico. Scoprirete facilmente quali chiamate sono particolarmente costose profilando la vostra applicazione WebGL.
Le seguenti sono alcune delle chiamate che risultano inaspettatamente costose:
Un ottimo modo per evitare queste chiamate è fare il tracking dello stato WebGL e ridurre il controllo degli errori nelle build di produzione della tua applicazione WebGL.
Evitare le Chiamate di Disegno
Il segreto per eccellenti prestazioni WebGL è avere il minor numero possibile di chiamate di disegno. Una chiamata di disegno è qualsiasi funzione che utilizza una delle seguenti funzioni WebGL:
- drawArrays()
- drawElements()
- drawArraysInstanced()
- drawElementsInstanced()
- drawBuffers()
- drawRangeElements()
Ci sono molti modi per farlo. Usare una chiamata che disegna molti oggetti piuttosto che chiamare una funzione molte volte per disegnare gli stessi oggetti, ad esempio. Puoi usare il “instancing” per renderizzare una grande quantità dello stesso mesh, o il WEBGL_multi_draw per renderizzare molti oggetti diversi con lo stesso shader.
I motori 3D hanno spesso una funzione chiamata “batching”, che unisce molte chiamate in una singola chiamata WebGL. Wonderland Engine porta questo a un livello estremo, dove scene con decine di migliaia di oggetti dinamici vengono renderizzate in meno di dieci chiamate di disegno automaticamente.
Le prestazioni WebGL su mobile sono particolarmente influenzate dalle chiamate di disegno.
WebGL su Safari
Su Safari (sia iOS che MacOS), ci sono altre chiamate WebGL che comportano una quantità sorprendentemente grande di sovraccarico, ad esempio:
Fai attenzione all’uso dei Buffer di Uniformi quando ottimizzi per Safari.
JavaScript
Il linguaggio utilizzato per interfacciarsi con le API del browser, come WebGL, è JavaScript. Il principale colpevole delle prestazioni con JavaScript è il Garbage Collection, che trova e rimuove automaticamente la memoria che non è più necessaria.
Il processo di Garbage Collection può rendere le prestazioni delle applicazioni WebGL imprevedibili e inaffidabili, poiché non hai controllo su quando avverrà. Di conseguenza, spesso si verifica in momenti che possono causare balbuzie nel rendering, dando l’impressione di scarse prestazioni, anche se il codice è ben ottimizzato.
Per ottenere framerate stabili, adotta un approccio rigoroso nello scrivere JavaScript senza garbage.
Safari su iOS e Memoria
Le app WebGL che funzionano bene su Safari sono rare. Le prestazioni di WebGL su Safari aggiungono delle sfide aggiuntive. Abbiamo scritto un intero post sul blog su come ottimizzare per Safari.
Limiti della Memoria
Su iOS si presenta un’altra sfida: le schede del browser hanno memoria molto limitata, soprattutto sui dispositivi iPhone più vecchi. Se superi i limiti di memoria, la scheda potrebbe ricaricarsi o bloccarsi. Poiché gli iPhone utilizzano memoria unificata, la RAM per CPU e GPU è condivisa e sia la texture che i dati del buffer, così come la memoria JavaScript o WebAssembly, contribuiranno al limite.