WebGPU: odblokowywanie dostępu do nowoczesnego GPU w przeglądarce

Dowiedz się, jak WebGPU wykorzystuje moc GPU, aby przyspieszyć działanie systemów uczących się i lepsze renderowanie grafiki.

Nowy interfejs WebGPU API umożliwia ogromny wzrost wydajności grafiki i zadań związanych z systemami uczącymi się. W tym artykule omawiamy, dlaczego WebGPU stanowi ulepszenie w stosunku do obecnego rozwiązania WebGL i jak wygląda jego zapowiedź w przyszłości. Najpierw jednak wyjaśnijmy, dlaczego stworzyliśmy technologię WebGPU.

Kontekst w WebGPU

W 2011 r. pojawiła się przeglądarka WebGL w Chrome. Umożliwiając aplikacjom internetowym korzystanie z procesorów graficznych, WebGL umożliwia niesamowite wrażenia w sieci – od Google Earth, przez interaktywne teledyski, po pokazy po nieruchomości w 3D i nie tylko. WebGL opracowano na podstawie rodziny interfejsów API OpenGL, które zostały opracowane w 1992 roku. To dawno temu! Można sobie wyobrazić, że od tego czasu sprzęt GPU znacząco się zmienił.

Aby nadążyć za tą ewolucją, opracowaliśmy nową wersję interfejsów API, które umożliwiają bardziej efektywną interakcję z nowoczesnym sprzętem GPU. interfejsy API takie jak Direct3D 12, Metal i Vulkan. Te nowe interfejsy API obsługiwały nowe i wymagające przypadki użycia programowania GPU, takie jak eksplozja systemów uczących się i postępy w algorytmach renderowania. WebGPU to następca WebGL, który udostępnia w internecie rozwój tej nowej klasy nowoczesnych interfejsów API.

WebGPU daje wiele nowych możliwości programowania GPU w przeglądarce. Lepiej odzwierciedla sposób działania nowoczesnego GPU, a jednocześnie tworzy podstawy dla bardziej zaawansowanych funkcji GPU w przyszłości. Interfejs ten działa od 2017 roku w ramach grupy „GPU for the Web” firmy W3C i jest wynikiem współpracy między wieloma firmami, takimi jak Apple, Google, Mozilla, Microsoft i Intel. Teraz, po 6 latach pracy, z przyjemnością ogłaszamy, że w końcu pojawiła się jedna z największych dodatków do platformy internetowej.

Interfejs WebGPU jest już dostępny w Chrome 113 na urządzeniach z ChromeOS, macOS i Windows. Wkrótce zostaną udostępnione inne platformy. Serdecznie dziękujemy innym współtwórcom Chromium i w szczególności firmie Intel, którzy przyczynili się do osiągnięcia tego celu.

Przyjrzyjmy się teraz niektórym przypadkom użycia, jakie daje WebGPU.

Wykorzystanie nowych zadań GPU do renderowania

Funkcje WebGPU, takie jak shaki obliczeniowe, umożliwiają przenoszenie do GPU nowych klas algorytmów. Na przykład algorytmy, które mogą dodawać do sceny więcej dynamicznych szczegółów czy symulować zjawiska fizyczne. Są nawet zadania, które wcześniej można było wykonywać tylko w języku JavaScript, a teraz można je przenieść do GPU.

Poniższy film przedstawia algorytm marszu kostek używany do triangulowania powierzchni tych metakul. W ciągu pierwszych 20 sekund filmu algorytm podczas działania w JavaScripcie nie nadąża za tym, by strona działała z szybkością 8 FPS, co skutkuje zakłóceniami w animacji. Aby nadal działała w języku JavaScript, musielibyśmy znacznie obniżyć poziom szczegółów.

Gdy przenosimy ten sam algorytm do programu Compute, który pojawia się po 20 sekundach filmu, zmienia się noc i dzień. Strona działa teraz płynnie z prędkością 60 FPS, a poza tym jest jeszcze sporo do wykorzystania w przypadku innych efektów. Ponadto główna pętla JavaScript strony jest całkowicie wolna od innych zadań, dzięki czemu interakcje ze stroną pozostają responsywne.

Wersja demonstracyjna metaballów

WebGPU umożliwia też obsługę złożonych efektów wizualnych, które wcześniej nie były dostępne w praktyce. W poniższym przykładzie utworzonym w popularnej bibliotece Babylon.js powierzchnia oceanu jest w całości symulowana przez GPU. Realistyczna dynamika powstała z dodawania do siebie wielu niezależnych fal. Bezpośrednia symulacja każdej fali byłaby jednak zbyt kosztowna.

Demonstracja oceaniczna

Dlatego w wersji demonstracyjnej zastosowano zaawansowany algorytm zwany szybką transformatą Fouriera. Zamiast przedstawiać wszystkie fale jako złożone dane pozycjonujące, używamy danych widmowych, które są znacznie skuteczniejsze przy obliczeniach. Następnie każda ramka korzysta z przekształcenia Fouriera w celu konwersji danych widmowych na dane pozycjonujące, które reprezentują wysokość fal.

Szybsze wnioskowanie z wykorzystaniem systemów uczących się

WebGPU pomaga też przyspieszyć systemy uczące się, które w ostatnich latach stały się głównym zastosowaniem GPU.

Od dawna twórcy kreacji wykorzystują interfejs API renderowania WebGL do wykonywania operacji, które nie wymagają renderowania, na przykład wykonywania obliczeń przy użyciu systemów uczących się. Wymaga to jednak rysowania pikseli trójkątów jako sposobu na rozpoczęcie obliczeń oraz starannego pakowania i rozpakowywania danych tensorów w teksturze, a nie w celu korzystania z pamięci ogólnego przeznaczenia.

Ilustracja pokazująca nieefektywność wykonania pojedynczego operatora ML z użyciem WebGL, z uwzględnieniem nadmiarowych obciążeń pamięci, nadmiarowych obliczeń i niewielkiej liczby wartości zapisanych w wątku.
Jedno wdrożenie ML dla pojedynczego operatora ML.

Ten sposób korzystania z WebGL wymaga od programistów niezręcznego dostosowania swojego kodu do oczekiwań interfejsu API przeznaczonego wyłącznie do rysowania. W połączeniu z brakiem podstawowych funkcji, takich jak dostęp do pamięci współdzielonej przez obliczenia, prowadzi to do powielania pracy i gorszej wydajności.

Rozwiązania do cieniowania danych to główna nowa funkcja WebGPU, która eliminuje te problemy. Rozwiązania do cieniowania obliczeniowe oferują bardziej elastyczny model programowania, który wykorzystuje faktyczną, równoległą naturę GPU, nie ograniczając się przez ścisłą strukturę operacji renderowania.

Różne wzrosty wydajności w modułach do cieniowania WebGPU, w tym ładowanie pamięci współdzielonej, wspólne obliczenia i elastyczne zapisywanie w pamięci.
Wydajność cieniowania obliczeniowego procesora WebGPU.

Moduły do cieniowania dają większe możliwości udostępniania danych i wyników obliczeń w grupach programów do cieniowania, co zwiększa wydajność. Może to prowadzić do znacznego wzrostu zysków w porównaniu z poprzednimi próbami użycia WebGL do tego samego celu.

Przykładem wzrostu wydajności jest początkowy port modelu dyfuzji obrazu w TensorFlow.js. Po przejściu z WebGPU do WebGPU wykazuje on 3-krotny wzrost wydajności na różnych urządzeniach. Na niektórych testach sprzętowych obraz został wyrenderowany w czasie krótszy niż 10 sekund. Ponieważ była to taka wczesna wersja portów, wierzymy, że zarówno WebGPU, jak i TensorFlow.js można wprowadzić jeszcze więcej ulepszeń. Sprawdź nowości w korzystaniu z Web ML w 2023 roku. podczas sesji Google I/O.

WebGPU to jednak nie tylko wprowadzenie funkcji GPU w internecie.

Najpierw zaprojektowane pod kątem JavaScriptu

Funkcje, które umożliwiają te przypadki użycia, są już od jakiegoś czasu dostępne dla programistów komputerów i urządzeń mobilnych na poszczególnych platformach, a naszym zadaniem było zaprezentować je w sposób, który wydaje się naturalną częścią platformy internetowej.

Platforma WebGPU została opracowana z wykorzystaniem danych od ponad 10 lat programistów pracujących z użyciem WebGL. Udało nam się wykorzystać napotkane problemy, wąskie gardła i problemy zgłaszane przez pracowników i przekierowaliśmy wszystkie zebrane opinie do nowego interfejsu API.

Zauważyliśmy, że globalny model stanu WebGL utrudnił i utrudnił tworzenie solidnych bibliotek i aplikacji kompatybilnych. Dzięki temu interfejs WebGPU znacznie zmniejsza stan, który deweloperzy muszą śledzić podczas wysyłania poleceń GPU.

Słyszeliśmy, że debugowanie aplikacji WebGL jest kłopotliwe, dlatego WebGPU zawiera bardziej elastyczne mechanizmy obsługi błędów, które nie zapewniają odpowiedniej wydajności. Dołożyliśmy wszelkich starań, aby każda wiadomość dostępna w interfejsie API była łatwa do zrozumienia i podejmowania działań.

Widać też, że zbyt wiele wywołań JavaScriptu powodowało powszechne funkcjonowanie złożonych aplikacji WebGL. W rezultacie interfejs API WebGPU jest mniej gadatliwy i możesz osiągnąć więcej przy mniejszej liczbie wywołań funkcji. Skupiamy się na przeprowadzaniu weryfikacji wagi z góry, tak aby krytyczna pętla pobierania była jak najmniejsza. Oferujemy też nowe interfejsy API, takie jak pakiety renderowania, które umożliwiają rejestrowanie dużej liczby poleceń rysowania z wyprzedzeniem i ich ponowne odtwarzanie za pomocą jednego wywołania.

Aby pokazać, jak ogromną różnicę mogą przynieść takie funkcje jak pakiety renderowania, oto kolejna prezentacja z kodu Babylon.js. Mechanizm renderowania WebGL 2 może wykonać wszystkie wywołania JavaScriptu, aby renderować scenę z galerii sztuki około 500 razy na sekundę. To całkiem niezłe!

Galeria sztuki

Ich mechanizm renderowania WebGPU umożliwia jednak korzystanie z funkcji, którą wywołują renderowanie zrzutów. Ta funkcja, powstała na bazie pakietów renderowania WebGPU, umożliwia ponad 10-krotne szybsze przesyłanie tej samej sceny. Dzięki znacznemu zmniejszeniu nakładu pracy WebGPU może renderować bardziej złożone sceny, a aplikacje mogą robić więcej z równoległym kodem JavaScript.

Nowoczesne interfejsy API do obsługi grafiki słyną ze złożoności, a prostota jest charakterystyczna dla ekstremalnych możliwości optymalizacji. Z kolei WebGPU koncentruje się na zgodności na wielu platformach i w większości przypadków automatycznie obsługuje trudne zagadnienia, takie jak synchronizacja zasobów.

Dzięki temu interfejs WebGPU jest łatwy do opanowania i używania. Opiera się na istniejących funkcjach platformy internetowej do wczytywania obrazów i filmów, a także na znanych wzorcach JavaScriptu, takich jak Promisesja dla operacji asynchronicznych. Pomaga to ograniczyć ilość kodu stałego do minimum. Pierwszy trójkąt możesz umieścić na ekranie w mniej niż 50 wierszach kodu.

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

Podsumowanie

Obserwowanie wszystkich nowych możliwości zapewnianych przez WebGPU na platformie internetowej jest ekscytujące i nie możemy się doczekać wszystkich nowych, ciekawych zastosowań WebGPU.

Wokół WebGL powstał tętniący życiem ekosystem bibliotek i platform, a ten sam ekosystem chętnie zostanie w nim dostępny. Obsługa WebGPU jest w trakcie opracowywania lub jest już ukończona w wielu popularnych bibliotekach WebGL w języku JavaScript, a w niektórych przypadkach wykorzystanie zalet WebGPU może sprowadzać się do zmiany jednej flagi.

Babylon.js, Construct 3, Google Earth, Google Meet, PlayCanvas, Sketchfab, Three.JS, TensorFlow.js i Unity.
Ramki, aplikacje i biblioteki z ukończonymi lub działającymi portami WebGPU.

A pierwsza wersja Chrome 113 to dopiero początek. Chociaż wstępna wersja jest przeznaczona dla systemów Windows, ChromeOS i macOS, planujemy udostępnić w najbliższej przyszłości technologię WebGPU na pozostałych platformach, takich jak Android i Linux.

Nie tylko zespół Chrome pracuje nad wprowadzeniem WebGPU. Trwa również wdrożenia w Firefoksie i WebKit.

Dodatkowo w W3C opracowujemy już nowe funkcje, które można udostępnić, jeśli są dostępne sprzętowo. W Chrome planujemy na przykład włączyć obsługę 16-bitowych liczb zmiennoprzecinkowych w tzw. cieniowaniu i klasę instrukcji DP4a, aby jeszcze bardziej zwiększyć wydajność systemów uczących się.

WebGPU to rozbudowany interfejs API, który zapewnia niesamowitą wydajność, jeśli w nie zainwestujesz. Dzisiaj moglibyśmy omówić jego zalety tylko na poziomie ogólnym, ale jeśli chcesz zacząć korzystać z WebGPU, zapoznaj się z naszym kursem wprowadzającym w programie Twoja pierwsza aplikacja WebGPU. Z tego ćwiczenia w programie utworzysz wersję GPU klasycznej gry w życie Conwaya. Dzięki temu ćwiczeniu w programie przeprowadzisz Cię przez cały proces krok po kroku, nawet jeśli po raz pierwszy zajmujesz się programowaniem GPU.

Dobrym miejscem, w którym można poznać działanie interfejsu API, są też próbki z WebGPU. Obejmują one m.in. tradycyjny „trójkąt witaj” oraz bardziej kompletne potoki renderowania i obliczania, prezentujące różne techniki. Na koniec zapoznaj się z naszymi materiałami.