WebGPU: Moderne GPU-Zugriffe im Browser

WebGPU nutzt die Leistung der GPU für eine schnellere Machine-Learning-Leistung und besseres Grafik-Rendering.

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

Die neue WebGPU API ermöglicht enorme Leistungssteigerungen bei Grafik- und ML-Arbeitslasten. In diesem Artikel wird untersucht, wie WebGPU eine Verbesserung gegenüber der aktuellen Lösung von WebGL ist, und bietet einen kleinen Vorgeschmack auf zukünftige Entwicklungen. Aber zuerst wollen wir uns ansehen, warum WebGPU entwickelt wurde.

WebGPU

2011 wurde WebGL in Chrome eingeführt. WebGL ermöglicht es Webanwendungen, GPUs zu nutzen und so beeindruckende Webinhalte zu erstellen – von Google Earth über interaktive Musikvideos bis hin zu 3D-Immobilienbesichtigungen. WebGL basiert auf der OpenGL-API-Familie, die 1992 entwickelt wurde. Das ist schon lange her. Und Sie können sich vorstellen, dass sich die GPU-Hardware seitdem erheblich weiterentwickelt hat.

Um mit dieser Entwicklung Schritt zu halten, wurde eine neue Art von APIs entwickelt, die eine effizientere Interaktion mit moderner GPU-Hardware ermöglichen. APIs wie Direct3D 12, Metal und Vulkan Diese neuen APIs haben neue und anspruchsvolle Anwendungsfälle für die GPU-Programmierung unterstützt, z. B. den explosionsartigen Anstieg des maschinellen Lernens und Fortschritte bei den Rendering-Algorithmen. WebGPU ist der Nachfolger von WebGL und bringt die Vorteile dieser neuen Klasse moderner APIs ins Web.

WebGPU eröffnet viele neue Möglichkeiten für die GPU-Programmierung im Browser. Sie spiegelt besser die Funktionsweise moderner GPU-Hardware wider und legt gleichzeitig den Grundstein für erweiterte GPU-Funktionen in der Zukunft. Die API wird seit 2017 in der W3C-Gruppe „GPU for the Web“ entwickelt und ist eine Zusammenarbeit vieler Unternehmen wie Apple, Google, Mozilla, Microsoft und Intel. Nach sechs Jahren Entwicklungszeit können wir nun eine der größten Erweiterungen der Webplattform ankündigen.

WebGPU ist derzeit in Chrome 113 für ChromeOS, macOS und Windows verfügbar. Weitere Plattformen folgen demnächst. Ein großes Dankeschön an die anderen Chromium-Entwickler und insbesondere an Intel, die dazu beigetragen haben.

Sehen wir uns nun einige der spannenden Anwendungsfälle an, die WebGPU ermöglicht.

Neue GPU-Arbeitslasten für das Rendering freischalten

WebGPU-Funktionen wie Compute Shader ermöglichen es, neue Algorithmenklassen auf die GPU zu portieren. Beispielsweise können Algorithmen dynamische Details zu Szenen hinzufügen, physikalische Phänomene simulieren und vieles mehr. Es gibt sogar Arbeitslasten, die bisher nur in JavaScript ausgeführt werden konnten, die jetzt auf die GPU verschoben werden können.

Das folgende Video zeigt, wie der Algorithmus der Marschwürfel zur Triangulierung der Oberfläche dieser Metabälle verwendet wird. In den ersten 20 Sekunden des Videos hat der Algorithmus, wenn er in JavaScript ausgeführt wird, Schwierigkeiten, mit der Seite Schritt zu halten, die nur bei 8 fps ausgeführt wird, was zu ruckeligen Animationen führt. Um die Leistung in JavaScript aufrechtzuerhalten, müssten wir die Detailgenauigkeit stark reduzieren.

Wenn wir denselben Algorithmus in einen Compute Shader verschieben, ist der Unterschied enorm. Das sehen Sie im Video nach 20 Sekunden. Die Leistung wird dadurch deutlich verbessert. Die Seite läuft jetzt mit flüssigen 60 fps und es bleibt noch viel Leistungsspielraum für andere Effekte. Außerdem ist die Haupt-JavaScript-Schleife der Seite vollständig für andere Aufgaben verfügbar, sodass die Interaktionen mit der Seite reaktionsschnell bleiben.

Metaballs-Demo

WebGPU ermöglicht auch komplexe visuelle Effekte, die bisher nicht praktikabel waren. Im folgenden Beispiel, das in der beliebten Babylon.js-Bibliothek erstellt wurde, wird die Meeresoberfläche vollständig auf der GPU simuliert. Die realistische Dynamik entsteht durch viele unabhängige Wellen, die sich gegenseitig überlagern. Die direkte Simulation jeder Welle wäre jedoch zu teuer.

Demo „The Ocean“

Deshalb wird in der Demo ein fortschrittlicher Algorithmus namens Fast Fourier Transform verwendet. Anstatt alle Wellen als komplexe Positionsdaten darzustellen, werden hier die spektralen Daten verwendet, sodass Berechnungen viel effizienter durchgeführt werden können. Dann verwendet jeder Frame die Fourier-Transformation, um spektrale Daten in Positionsdaten umzuwandeln, die die Höhe der Wellen darstellen.

Schnellere ML-Inferenz

WebGPU ist außerdem nützlich, um das maschinelle Lernen zu beschleunigen, das in den letzten Jahren zu einer wichtigen Nutzung von GPUs geworden ist.

Schon lange verwenden kreative Entwickler die Rendering-API von WebGL für nicht Rendering-bezogene Vorgänge wie maschinelles Lernen. Dazu müssen jedoch die Pixel der Dreiecke gezeichnet werden, um die Berechnungen zu starten, und Tensordaten müssen sorgfältig in Texturen verpackt und entpackt werden, anstatt allgemeinere Speicherzugriffe zu verwenden.

Eine Abbildung der Ineffizienzen bei der Ausführung eines einzelnen ML-Operators mit WebGL, einschließlich redundanter Speicherladungen, redundanter Berechnungen und weniger geschriebener Werte pro Thread.
Ausführung eines einzelnen ML-Operators mit WebGL.

Wenn WebGL auf diese Weise verwendet wird, müssen Entwickler ihren Code auf komplizierte Weise an die Anforderungen einer API anpassen, die nur zum Zeichnen entwickelt wurde. In Kombination mit dem Fehlen grundlegender Funktionen wie dem gemeinsamen Speicherzugriff zwischen Berechnungen führt dies zu doppelter Arbeit und einer suboptimalen Leistung.

Compute-Shader sind die wichtigste neue Funktion von WebGPU und beseitigen diese Probleme. Compute Shader bieten ein flexibleres Programmiermodell, das die massiv parallele Natur der GPU nutzt, ohne durch die strenge Struktur von Rendering-Vorgängen eingeschränkt zu sein.

Die verschiedenen Effizienzgewinne bei WebGPU-Compute-Shadern, einschließlich gemeinsam genutzter Speicherladungen, gemeinsam genutzter Berechnungen und flexibler Schreibvorgänge in den Arbeitsspeicher.
Effizienz von WebGPU-Compute-Shadern.

Compute Shader bieten mehr Möglichkeiten, Daten und Berechnungsergebnisse innerhalb von Shader-Arbeitsgruppen zu teilen, um die Effizienz zu verbessern. Dies kann zu erheblichen Leistungssteigerungen im Vergleich zu früheren Versuchen führen, WebGL für denselben Zweck zu verwenden.

Als Beispiel für die damit verbundenen Effizienzgewinne: Ein erster Port eines Bilddiffusionsmodells in TensorFlow.js zeigt eine dreifache Leistungssteigerung auf einer Vielzahl von Hardware, wenn es von WebGL zu WebGPU migriert wird. Auf einigen der getesteten Hardware wurde das Bild in weniger als 10 Sekunden gerendert. Da es sich hierbei um einen frühen Port handelt, sind wir überzeugt, dass sowohl bei WebGPU als auch bei TensorFlow.js noch mehr Verbesserungen möglich sind. Weitere Informationen finden Sie unter Was gibt es Neues bei Web ML in 2023? Google I/O-Sitzung

Bei WebGPU geht es aber nicht nur darum, GPU-Funktionen ins Web zu bringen.

JavaScript-first-Design

Die Funktionen, die diese Anwendungsfälle ermöglichen, sind für plattformspezifische Entwickler von Desktop- und Mobilanwendungen schon seit einiger Zeit verfügbar. Unsere Herausforderung bestand darin, sie so zu präsentieren, dass sie sich wie ein natürlicher Bestandteil der Webplattform anfühlen.

WebGPU wurde mit dem Vorteil der Rückschau auf über ein Jahrzehnt Erfahrung von Entwicklern entwickelt, die hervorragende Arbeit mit WebGL geleistet haben. Wir konnten die Probleme, Engpässe und Probleme, die sie gemeldet haben, in diese neue API einfließen lassen.

Wir haben festgestellt, dass das globale Statusmodell von WebGL das Erstellen robuster, kombinierbarer Bibliotheken und Anwendungen schwierig und anfällig macht. So reduziert WebGPU die Menge an Status, die Entwickler beim Senden der GPU-Befehle im Auge behalten müssen, drastisch.

Wir haben gehört, dass das Debugging von WebGL-Anwendungen schwierig war. Daher umfasst WebGPU flexiblere Fehlerbehandlungsmechanismen, die die Leistung nicht beeinträchtigen. Außerdem haben wir uns bemüht, dass jede Nachricht, die Sie von der API erhalten, leicht verständlich und umsetzbar ist.

Außerdem haben wir festgestellt, dass der Overhead zu vieler JavaScript-Aufrufe häufig ein Engpass für komplexe WebGL-Anwendungen war. Daher ist die WebGPU API weniger Chatten, sodass Sie mit weniger Funktionsaufrufen mehr erreichen können. Wir konzentrieren uns darauf, die umfangreiche Validierung im Voraus durchzuführen und die kritische Draw-Schleife so schlank wie möglich zu halten. Außerdem bieten wir neue APIs wie Render-Bundles, mit denen Sie eine große Anzahl von Zeichenbefehlen im Voraus aufzeichnen und mit einem einzigen Aufruf wiedergeben können.

Um zu veranschaulichen, wie dramatisch sich eine Funktion wie Render-Bundles auswirken kann, sehen Sie sich diese weitere Demo von Babylon.js an. Der WebGL 2-Renderer kann alle JavaScript-Aufrufe ausführen, um diese Kunstgalerie etwa 500 Mal pro Sekunde zu rendern. Das ist ziemlich gut.

Kunstgalerie

Der WebGPU-Renderer von Apple ermöglicht jedoch eine Funktion, die als Snapshot-Rendering bezeichnet wird. Diese Funktion basiert auf Rendering-Bundles für WebGPUs und ermöglicht so eine 10-mal schnellere Einreichung derselben Szene. Durch den deutlich reduzierten Aufwand kann WebGPU komplexere Szenen rendern, während Anwendungen gleichzeitig mehr mit JavaScript tun können.

Moderne Grafik-APIs gelten als komplex, da sie Einfachheit gegen extreme Optimierungsmöglichkeiten eintauschen. WebGPU hingegen konzentriert sich auf die plattformübergreifende Kompatibilität und behandelt in den meisten Fällen traditionell schwierige Themen wie die Ressourcensynchronisierung automatisch.

Das hat den angenehmen Nebeneffekt, dass WebGPU einfach zu erlernen und zu verwenden ist. Sie basiert auf vorhandenen Funktionen der Webplattform für das Laden von Bildern und Videos und nutzt bekannte JavaScript-Muster wie Promise-Objekte für asynchrone Vorgänge. So lässt sich der erforderliche Boilerplate-Code auf ein Minimum beschränken. Mit weniger als 50 Codezeilen können Sie Ihr erstes Dreieck auf dem Bildschirm anzeigen.

<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>

Fazit

Es ist spannend, all die neuen Möglichkeiten zu sehen, die WebGPU für die Webplattform bietet. Wir sind gespannt auf die coolen neuen Anwendungsfälle, die Sie für WebGPU finden werden.

Um WebGL herum wurde ein lebendiges Ökosystem von Bibliotheken und Frameworks aufgebaut, das WebGPU mit offenen Armen empfängt. In vielen beliebten JavaScript-WebGL-Bibliotheken ist die Unterstützung für WebGPU in Arbeit oder bereits abgeschlossen. In einigen Fällen ist es sogar möglich, die Vorteile von WebGPU zu nutzen, indem Sie nur ein einziges Flag ändern.

Babylon.js, Construct 3, Google Earth, Google Meet, PlayCanvas, Sketchfab, Three.JS, TensorFlow.js und Unity.
Frameworks, Anwendungen und Bibliotheken mit fertigen oder laufenden WebGPU-Ports

Und diese erste Version in Chrome 113 ist erst der Anfang. Unsere erste Version ist für Windows, ChromeOS und macOS verfügbar. Wir planen jedoch, WebGPU in naher Zukunft auf die übrigen Plattformen wie Android und Linux auszuweiten.

Und nicht nur das Chrome-Team hat an der Einführung von WebGPU gearbeitet. Implementierungen für Firefox und WebKit sind ebenfalls in Arbeit.

Darüber hinaus werden beim W3C bereits neue Funktionen entwickelt, die verfügbar gemacht werden können, wenn sie in der Hardware verfügbar sind. Beispiel: In Chrome planen wir, bald die Unterstützung von 16‑Bit-Gleitkommazahlen in Shadern und die DP4a-Anweisungsklasse zu aktivieren, um die Leistung des maschinellen Lernens weiter zu verbessern.

WebGPU ist eine umfangreiche API, die bei entsprechender Nutzung eine hervorragende Leistung ermöglicht. Heute konnten wir nur einen groben Überblick über die Vorteile von WebGPU geben. Wenn Sie mit WebGPU loslegen möchten, sehen Sie sich unser Einführungs-Codelab Ihre erste WebGPU-App an. In diesem Codelab erstellen Sie eine GPU-Version des klassischen Conway's Game of Life. Dieses Codelab führt Sie Schritt für Schritt durch den Prozess, sodass Sie ihn auch ausprobieren können, wenn Sie zum ersten Mal GPU-Entwicklung betreiben.

Die WebGPU-Beispiele sind auch ein guter Ausgangspunkt, um sich mit der API vertraut zu machen. Sie reichen vom traditionellen „Hallo Dreieck“ bis hin zu umfassenderen Rendering- und Computing-Pipelines, die eine Vielzahl von Techniken demonstrieren. Weitere Informationen findest du in unseren Ressourcen.