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 Machine-Learning-Arbeitslasten. In diesem Artikel wird erläutert, inwiefern WebGPU eine Verbesserung gegenüber der aktuellen Lösung WebGL darstellt. Außerdem erhalten Sie einen Einblick in zukünftige Entwicklungen. Aber zuerst wollen wir uns ansehen, warum WebGPU entwickelt wurde.

WebGPU

WebGL wurde 2011 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, wurden neue APIs entwickelt, die eine effizientere Interaktion mit moderner GPU-Hardware ermöglichen. APIs wie Direct3D 12, Metal und Vulkan. Diese neuen APIs unterstützen neue und anspruchsvolle Anwendungsfälle für die GPU-Programmierung, wie die Explosion des maschinellen Lernens und Fortschritte bei 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 ab sofort in Chrome 113 für ChromeOS, macOS und Windows verfügbar. Weitere Plattformen folgen bald. 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. Dazu gehören beispielsweise Algorithmen, mit denen Szenen dynamischere Details hinzugefügt und physikalische Phänomene simuliert werden können. Es gibt sogar Arbeitslasten, die bisher nur in JavaScript ausgeführt werden konnten, die jetzt auf die GPU verschoben werden können.

Im folgenden Video wird der Marching-Cubes-Algorithmus verwendet, um die Oberfläche dieser Metakugeln zu triangulieren. In den ersten 20 Sekunden des Videos kann der Algorithmus, wenn er in JavaScript ausgeführt wird, nicht mit der Seite mit nur 8 FPS Schritt halten, was zu einer ruckeligen Animation 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 verbessert sich dramatisch, da die Seite jetzt mit 60 fps flüssig läuft und noch viel Leistungsspielraum für andere Effekte vorhanden ist. 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.

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

Die Ozean-Demo

Deshalb wird in der Demo ein fortschrittlicher Algorithmus namens Fast Fourier Transform verwendet. Anstatt alle Wellen als komplexe Positionsdaten darzustellen, werden die Spektraldaten verwendet, die für Berechnungen viel effizienter sind. Anschließend wird für jeden Frame die Fourier-Transformation verwendet, um von Spektraldaten in die Positionsdaten zu konvertieren, die die Höhe der Wellen darstellen.

Schnellere ML-Inferenz

WebGPU ist auch nützlich, um maschinelles Lernen zu beschleunigen, was in den letzten Jahren zu einem wichtigen Einsatz von GPUs geworden ist.

Schon lange verwenden kreative Entwickler die Rendering-API von WebGL für nicht Rendering-bezogene Vorgänge wie z. B. 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 um eine frühe Version handelt, sind wir der Meinung, dass sowohl WebGPU als auch TensorFlow.js noch verbessert werden können. 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 Mobilgeräten 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 entwickelt, die über ein Jahrzehnt von Entwicklern geleistet wurde, 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 Entfernen von Fehlern in WebGL-Anwendungen mühsam ist. Deshalb bietet 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 gesprächig, sodass Sie mit weniger Funktionsaufrufen mehr erreichen. 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 Kunstgalerieszene etwa 500 Mal pro Sekunde zu rendern. Das ist ziemlich gut.

Die Kunstgalerie

Der WebGPU-Renderer ermöglicht jedoch eine Funktion, die als Snapshot-Rendering bezeichnet wird. Diese Funktion basiert auf WebGPU-Render-Bundles und ermöglicht es, dieselbe Szene mehr als zehnmal schneller einzureichen. Durch diesen deutlich reduzierten Overhead können mit WebGPU komplexere Szenen gerendert werden. Außerdem können Anwendungen parallel mehr mit JavaScript tun.

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. Für Funktionen wie das Laden von Bildern und Videos werden vorhandene Funktionen der Webplattform genutzt. Außerdem werden bekannte JavaScript-Muster wie Promises für asynchrone Vorgänge verwendet. 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 wird die Unterstützung für WebGPU derzeit implementiert oder ist bereits abgeschlossen. In einigen Fällen ist es sogar möglich, die Vorteile von WebGPU zu nutzen, indem nur ein einziges Flag geändert wird.

Babylon.js, Construct 3, Google Earth, Google Meet, PlayCanvas, Sketchfab, Three.JS, TensorFlow.js und Unity.
Frameworks, Anwendungen und Bibliotheken mit abgeschlossenen 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. Auch in Firefox und WebKit sind Implementierungen in Arbeit.

Außerdem werden bereits neue Funktionen im W3C entwickelt, die genutzt werden können, sobald 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 die Vorteile allgemein beschreiben. 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. In diesem Codelab werden Sie Schritt für Schritt durch den Prozess geführt. Sie können es also auch ausprobieren, wenn Sie noch keine Erfahrung mit der GPU-Entwicklung haben.

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 Compute-Pipelines, die eine Vielzahl von Techniken demonstrieren. Weitere Informationen finden Sie in unseren Ressourcen.