WebGLはグラフィックスAPIという位置づけでしたが、WebGPUはグラフィックスに限らず、GPUで処理を行うこと自体を目的としたAPIです。
そのため、WebGPUの初期化は、canvas
要素に何かを描くためのコンテキストの用意だけでなく、GPUに安全にアクセスするための抽象化された手順から始まります。
物理的なGPUと論理的なGPU
実際にハードウェアに搭載されているGPU(物理的なGPU)の数は限られています。
しかし、GPUは同時にたくさんのアプリケーションから使われています。
そのため、GPUを使っている各アプリが他と干渉しないように、安全にGPUを共有する必要があります。
そうしないと、他のアプリの描画を邪魔したり、こっそりデータを読むような悪意ある動作も起きかねません。
多重化 (multiplexing)
多重化とは、1つのリソースを、あたかも複数あるかのように扱い、安全に共有するための仕組みです。
WebGPUには、たとえ1つの物理的なGPUを共有していたとしても、各Webアプリからは、あたかも自分だけが自分専用のGPU(論理的なGPU)を使っているかのように見せる仕組みがあります。論理的には専用に見えても、物理的には共有されているわけです。
WebGPUによる抽象化:アダプタと論理デバイス
WebGPUで何らかの処理を行いたいとき、まずはGPUとやりとりするための窓口を準備する必要があります。
- ハードウェアに搭載されている物理的なGPU(アダプタ)の情報を取得する
- 物理的なGPUから、アプリに割り当てられた論理的なGPU(論理デバイス)を取得する
WebGPUでは、物理的なGPUに対応する概念がアダプタで、論理的なGPUに対応する概念が論理デバイスです。このアダプタと論理デバイスという抽象化によって、GPUへのアクセスを安全に確立することができます。
用語 | ざっくりとした定義 | 使いどころ |
---|---|---|
アダプタ | PCにある物理GPU | どのGPUを使うか選ぶ、性能確認 |
論理デバイス | 選んだGPUを使うためのハンドル | リソースを作る、描画命令を出す、etc. |
アダプタ (Adapter)
パソコンやスマートフォンには、複数のGPU(たとえばCPU内蔵の省電力GPUと、外部の高性能GPU)があることがあります。WebGPUを使うには、まずその中からどのGPUを使うか選ぶ必要があります。
WebGPUのアダプタは、PCに搭載された実際のGPU(物理的なGPU)を表すものです。
OSのネイティブなグラフィックスAPIをWebGPUに翻訳するためのレイヤーともいえます。
アダプタを取得することで、物理的なGPUの名前や性能、対応している機能などがわかります。
アダプタの取得
WebGPUの初期化ではまず、次のようにしてアダプタを取得します。
const adapter = await navigator.gpu.requestAdapter()
requestAdapter()
は、ブラウザに「使えるGPUを教えて」と依頼する処理です。
結果として、使えるGPUに関する情報を持つGPUAdapter
オブジェクトが返ってきます。
アダプタが持つ情報
取得したアダプタからは、そのGPUで処理できるリソースはどれくらいか、どんな機能が使えるか、などの情報がわかります。
adapter.features
→ サポートしている機能(例:depth-clamping
、timestamp-query
など)adapter.limits
→ リソース制限(例:最大テクスチャサイズ、バインディング数など)
アダプタ取得時のオプション
requestAdapter()
には、オプションを渡すこともできます。
const adapter = await navigator.gpu.requestAdapter({
powerPreference: "high-performance" // または "low-power"
})
"high-performance"
:できれば外部GPUを使いたい(高性能)"low-power"
:バッテリー消費を抑えたい(内蔵GPU)
ただしこれは希望を伝えるだけで、必ずその通りになるわけではありません。
論理デバイス (Device)
マシンに搭載された数少ないGPUを、「この時間はアプリA、次はアプリB、…」というように、時間や機能で分けてアプリケーションに割り当てるのは、OSやGPUドライバの仕事です。
OSはブラウザにもGPUを割り当てますが、ブラウザはその中でさらにWebアプリにGPUを割り当てる必要があります。
たとえば、複数のタブでWebGPUを使うWebアプリケーションが開かれているなら、それぞれがまるで個別のGPUを使っているかのようにし、他のタブの影響を受けないようにする必要があるのです。
WebGPUにおける、複数のWebアプリに「それぞれ専用のGPUがあるように見せる」ための仕組みが、論理デバイスです。
WebGPUでは、論理デバイスを取得することで、GPUへの間接的なアクセス権を得ます。
論理デバイスは、GPUとやりとりするための窓口(コントローラ)であり、論理デバイスを通して、実際のGPUに命令を出したり、リソースを作ったりします。
論理デバイスの取得
論理デバイスは、アダプタを介して要求することができます。
const adapter = await navigator.gpu.requestAdapter()
const device = await adapter.requestDevice()
gpu.requestAdapter()
によって使用可能なGPUを探してもらったら、今度はadapter.requestDevice()
によって、そのGPUとのやりとりの開始をリクエストするイメージです。
論理デバイスを使ってできること
GPUとのデータのやりとり、GPUへの命令の送信、そしてそのデータや命令(コマンド)を作成する処理など、論理デバイスは、GPUに任せたい仕事の準備作業を多く担います。
-
バッファ(GPUに送るデータ)を作る
→device.createBuffer(...)
-
シェーダーをコンパイルする
→device.createShaderModule(...)
-
描画や計算のパイプラインを構築する
→device.createRenderPipeline(...)
-
コマンドをまとめるエンコーダーを作る
→device.createCommandEncoder()
-
キューに送信してGPUに実行してもらう
→device.queue.submit([...])