WebGPU: sblocco dell'accesso alle GPU moderne nel browser

Scopri come WebGPU sblocca la potenza della GPU per un rendimento più rapido del machine learning e un rendering grafico migliore.

Corentin Wallez
Corentin Wallez
François Beaufort
François Beaufort

La nuova API WebGPU consente enormi incrementi delle prestazioni nei carichi di lavoro di grafica e machine learning. Questo articolo illustra in che modo WebGPU rappresenta un miglioramento rispetto alla soluzione attuale di WebGL, con un'anteprima degli sviluppi futuri. Prima però, forniamo un po' di contesto sul motivo per cui è stato sviluppato WebGPU.

Contesto su WebGPU

WebGL è stato introdotto in Chrome nel 2011. Consentendo alle applicazioni web di sfruttare le GPU, WebGL offre esperienze straordinarie sul web, da Google Earth ai video musicali interattivi, ai tour virtuali di immobili e altro ancora. WebGL si basa sulla famiglia di API OpenGL sviluppata per la prima volta nel 1992. È successo tanto tempo fa. E puoi immaginare che l'hardware GPU sia evoluto notevolmente da allora.

Per stare al passo con questa evoluzione, è stata sviluppata una nuova generazione di API per interagire in modo più efficiente con l'hardware GPU moderno. API come Direct3D 12, Metal e Vulkan. Queste nuove API hanno supportato casi d'uso nuovi e impegnativi per la programmazione GPU, come l'esplosione del machine learning e i progressi degli algoritmi di rendering. WebGPU è il successore di WebGL e porta sul web i progressi di questa nuova classe di API moderne.

WebGPU sblocca molte nuove possibilità di programmazione GPU nel browser. Riflette meglio il funzionamento dell'hardware GPU moderno, gettando al contempo le basi per funzionalità GPU più avanzate in futuro. L'API è in fase di sviluppo nel gruppo "GPU per il web" del W3C dal 2017 ed è frutto della collaborazione di molte aziende come Apple, Google, Mozilla, Microsoft e Intel. Ora, dopo 6 anni di lavoro, siamo lieti di annunciare che una delle più grandi aggiunte alla piattaforma web è finalmente disponibile.

WebGPU è già disponibile in Chrome 113 su ChromeOS, macOS e Windows e sarà presto disponibile su altre piattaforme. Un enorme grazie agli altri collaboratori di Chromium e in particolare a Intel che hanno contribuito a realizzare tutto questo.

Ora diamo un'occhiata ad alcuni dei fantastici casi d'uso abilitati da WebGPU.

Sfrutta nuovi carichi di lavoro GPU per il rendering

Le funzionalità WebGPU, come gli shader di calcolo, consentono di eseguire il porting di nuove classi di algoritmi sulla GPU. Ad esempio, algoritmi che possono aggiungere dettagli più dinamici alle scene, simulare fenomeni fisici e altro ancora. Esistono persino carichi di lavoro che in precedenza potevano essere eseguiti solo in JavaScript, ma che ora possono essere spostati sulla GPU.

Il seguente video mostra l'algoritmo marching cubes utilizzato per triangolare la superficie di queste metaball. Nei primi 20 secondi del video, l'algoritmo, quando viene eseguito in JavaScript, fatica a tenere il passo con la pagina che funziona a soli 8 FPS, con il risultato di un'animazione a scatti. Per mantenere le prestazioni in JavaScript, dovremmo abbassare notevolmente il livello di dettagli.

C'è una differenza abissale quando spostiamo lo stesso algoritmo in un compute shader, come si vede nel video dopo 20 secondi. Il rendimento migliora notevolmente, poiché la pagina ora funziona a 60 FPS fluidi e c'è ancora molto spazio per altri effetti. Inoltre, il loop JavaScript principale della pagina viene completamente liberato per altre attività, garantendo che le interazioni con la pagina rimangano reattive.

La demo delle metaball

WebGPU consente inoltre di utilizzare effetti visivi complessi che prima non erano pratici. Nell'esempio seguente, creato nella popolare libreria Babylon.js, la superficie dell'oceano viene simulata interamente sulla GPU. Le dinamiche realistiche vengono create dall'aggiunta di molte onde indipendenti. Tuttavia, simulare direttamente ogni onda sarebbe troppo costoso.

La demo dell'oceano

Ecco perché la demo utilizza un algoritmo avanzato chiamato trasformata di Fourier veloce. Anziché rappresentare tutte le onde come dati di posizione complessi, vengono utilizzati i dati spettrali, che sono molto più efficienti per eseguire i calcoli. Poi ogni frame utilizza la trasformata di Fourier per convertire i dati spettrali in dati di posizione che rappresentano l'altezza delle onde.

Inferenza ML più rapida

WebGPU è utile anche per accelerare il machine learning, che è diventato un uso importante delle GPU negli ultimi anni.

Per molto tempo, gli sviluppatori di creatività hanno riutilizzato l'API di rendering di WebGL per eseguire operazioni non di rendering come i calcoli di machine learning. Tuttavia, questo richiede di disegnare i pixel dei triangoli per avviare i calcoli e imballare e sballare con attenzione i dati tensori nella texture anziché accedere alla memoria per scopi più generali.

Un'illustrazione delle inefficienze in un'esecuzione di un singolo operatore ML con WebGL, inclusi carichi di memoria ridondanti, calcoli ridondanti e pochi valori scritti per thread.
Un'unica esecuzione di un operatore ML con WebGL.

L'utilizzo di WebGL in questo modo richiede agli sviluppatori di adeguare in modo imbarazzante il proprio codice alle aspettative di un'API progettata solo per il disegno. Se a questo aggiungiamo la mancanza di funzionalità di base come l'accesso alla memoria condivisa tra i calcoli, si ottiene un lavoro duplicato e prestazioni non ottimali.

Gli shader di calcolo sono la nuova funzionalità principale di WebGPU e rimuovono questi problemi. Gli shader di calcolo offrono un modello di programmazione più flessibile che sfrutta la natura altamente parallela della GPU senza essere vincolato dalla struttura rigida delle operazioni di rendering.

I vari miglioramenti dell'efficienza negli shader di calcolo WebGPU, inclusi i caricamenti della memoria condivisa, i calcoli condivisi e le scritture flessibili nella memoria.
Efficienze degli shader di calcolo WebGPU.

Gli shader di calcolo offrono maggiori opportunità per condividere dati e risultati di calcolo all'interno di gruppi di lavoro degli shader per una maggiore efficienza. Ciò può portare a vantaggi significativi rispetto ai tentativi precedenti di utilizzare WebGL per lo stesso scopo.

Come esempio degli incrementi di efficienza che questo può comportare, una porta iniziale di un modello di diffusione di immagini in TensorFlow.js mostra un incremento del rendimento di 3 volte su una serie di hardware quando si passa da WebGL a WebGPU. Su alcuni degli hardware testati, l'immagine è stata visualizzata in meno di 10 secondi. Poiché si tratta di una versione iniziale, riteniamo che siano possibili ulteriori miglioramenti sia in WebGPU che in TensorFlow.js. Consulta l'articolo Novità dell'AI su web nel 2023. Sessione Google I/O.

Ma WebGPU non si limita a portare le funzionalità della GPU sul web.

Progettato per JavaScript

Le funzionalità che consentono questi casi d'uso sono disponibili da tempo per gli sviluppatori di app mobile e desktop specifici della piattaforma ed è stata la nostra sfida esporle in modo che sembrino una parte naturale della piattaforma web.

WebGPU è stato sviluppato con il vantaggio di oltre un decennio di lavoro straordinario degli sviluppatori con WebGL. Abbiamo raccolto i problemi riscontrati, i colli di bottiglia e i problemi segnalati e li abbiamo inseriti in questa nuova API.

Abbiamo notato che il modello di stato globale di WebGL rendeva difficile e fragile la creazione di librerie e applicazioni composibili e robuste. Pertanto, WebGPU riduce drasticamente la quantità di stato che gli sviluppatori devono monitorare durante l'invio dei comandi GPU.

Ci è stato detto che il debug delle applicazioni WebGL era un problema, quindi WebGPU include meccanismi di gestione degli errori più flessibili che non influiscono sulle prestazioni. Inoltre, ci siamo adoperati per garantire che ogni messaggio che ricevi dall'API sia facile da comprendere e da mettere in pratica.

Abbiamo anche notato che spesso l'overhead di effettuare troppe chiamate JavaScript rappresentava un collo di bottiglia per le applicazioni WebGL complesse. Di conseguenza, l'API WebGPU è meno chiacchierona, quindi puoi fare di più con meno chiamate di funzione. Ci concentriamo sull'esecuzione anticipata di una convalida complessa, mantenendo il ciclo di disegno critico il più snello possibile. Offriamo anche nuove API come Render Bundles, che ti consentono di registrare in anticipo un numero elevato di comandi di disegno e riprodurli con una singola chiamata.

Per dimostrare la differenza significativa che può fare una funzionalità come i bundle di rendering, ecco un'altra demo di Babylon.js. Il loro renderer WebGL 2 può eseguire tutte le chiamate JavaScript per eseguire il rendering di questa scena della galleria d'arte circa 500 volte al secondo. Il che è abbastanza buono.

La galleria d'arte

Tuttavia, il loro motore di rendering WebGPU attiva una funzionalità chiamata Snapshot Rendering. Basata sui bundle di rendering WebGPU, questa funzionalità consente di inviare la stessa scena più di 10 volte più velocemente. Questo overhead notevolmente ridotto consente a WebGPU di eseguire il rendering di scene più complesse, consentendo al contempo alle applicazioni di fare di più con JavaScript in parallelo.

Le API grafiche moderne hanno la reputazione di essere complesse, perché scambiano la semplicità per opportunità di ottimizzazione estreme. WebGPU, invece, si concentra sulla compatibilità multipiattaforma e gestisce automaticamente nella maggior parte dei casi argomenti tradizionalmente difficili come la sincronizzazione delle risorse.

Il vantaggio è che WebGPU è facile da imparare e utilizzare. Si basa sulle funzionalità esistenti della piattaforma web per operazioni come il caricamento di immagini e video e si basa su pattern JavaScript ben noti come le promesse per le operazioni asincrone. In questo modo, la quantità di codice boilerplate necessaria viene ridotta al minimo. Puoi visualizzare il tuo primo triangolo sullo schermo in meno di 50 righe di codice.

<canvas id="canvas" width="512" height="512"></canvas>
<script type="module">
  const adapter = await navigator.gpu.requestAdapter();
  const device = await adapter.requestDevice();

  const context = canvas.getContext("webgpu");
  const format = navigator.gpu.getPreferredCanvasFormat();
  context.configure({ device, format });

  const code = `
    @vertex fn vertexMain(@builtin(vertex_index) i : u32) ->
      @builtin(position) vec4f {
       const pos = array(vec2f(0, 1), vec2f(-1, -1), vec2f(1, -1));
       return vec4f(pos[i], 0, 1);
    }
    @fragment fn fragmentMain() -> @location(0) vec4f {
      return vec4f(1, 0, 0, 1);
    }`;
  const shaderModule = device.createShaderModule({ code });
  const pipeline = device.createRenderPipeline({
    layout: "auto",
    vertex: {
      module: shaderModule,
      entryPoint: "vertexMain",
    },
    fragment: {
      module: shaderModule,
      entryPoint: "fragmentMain",
      targets: [{ format }],
    },
  });
  const commandEncoder = device.createCommandEncoder();
  const colorAttachments = [
    {
      view: context.getCurrentTexture().createView(),
      loadOp: "clear",
      storeOp: "store",
    },
  ];
  const passEncoder = commandEncoder.beginRenderPass({ colorAttachments });
  passEncoder.setPipeline(pipeline);
  passEncoder.draw(3);
  passEncoder.end();
  device.queue.submit([commandEncoder.finish()]);
</script>

Conclusione

È entusiasmante vedere tutte le nuove possibilità offerte da WebGPU alla piattaforma web e non vediamo l'ora di scoprire tutti i nuovi casi d'uso che troverete per WebGPU.

Intorno a WebGL è stato creato un ecosistema vivace di librerie e framework, che è ansioso di adottare WebGPU. Il supporto di WebGPU è in corso o è già stato completato in molte delle librerie WebGL Javascript più diffuse e, in alcuni casi, sfruttare i vantaggi di WebGPU potrebbe essere semplice come modificare un singolo flag.

Babylon.js, Construct 3, Google Earth, Google Meet, PlayCanvas, Sketchfab, Three.JS, TensorFlow.js e Unity.
Framework, applicazioni e librerie con porte WebGPU completate o in corso.

E questa prima release in Chrome 113 è solo l'inizio. La nostra release iniziale è per Windows, ChromeOS e macOS, ma prevediamo di portare WebGPU alle altre piattaforme come Android e Linux nel prossimo futuro.

E non è solo il team di Chrome a lavorare al lancio di WebGPU. Le implementazioni sono in corso anche in Firefox e WebKit.

Inoltre, al W3C sono già in fase di progettazione nuove funzionalità che possono essere esposte quando sono disponibili nell'hardware. Ad esempio, in Chrome prevediamo di attivare a breve il supporto dei numeri in virgola mobile a 16 bit negli shader e la classe di istruzioni DP4a per ulteriori miglioramenti delle prestazioni del machine learning.

WebGPU è un'API completa che offre prestazioni straordinarie se la investi. Oggi possiamo coprire solo i suoi vantaggi a un livello generale, ma se vuoi iniziare a utilizzare WebGPU, dai un'occhiata al nostro Codelab introduttivo La tua prima app WebGPU. In questo Codelab, creerai una versione GPU del classico Gioco della vita di Conway. Questo codelab illustra la procedura passo passo, quindi puoi provarla anche se è la prima volta che sviluppi per GPU.

Anche gli esempi WebGPU sono un buon punto di partenza per comprendere l'API. Vanno dal tradizionale "triangolo ciao" a pipeline di rendering e calcolo più complete, che dimostrano una serie di tecniche. Infine, consulta le altre nostre risorse.