WebGPU の新機能(Chrome 120)

François Beaufort
François Beaufort

WGSL での 16 ビット浮動小数点値のサポート

WGSL では、f16は、IEEE-754 binary16(半精度)形式の 16 ビット浮動小数点値のセットです。従来の単精度浮動小数点(f32)では 32 ビットではなく、16 ビットを使用して浮動小数点数を表します。これにより、特に大量のデータを処理する場合に、パフォーマンスが大幅に向上する可能性があります。

比較として、Apple M1 Pro デバイスでは、WebLLM チャットデモで使用されている Llama2 7B モデルf16 実装が f32 実装よりも著しく高速で、次のスクリーンショットに示すようにプレフィル速度が 28%、デコード速度が 41% 向上しています。

f32 と f16 の Llama2 7B モデルを使用した WebLLM チャット デモのスクリーンショット。
f32(左)と f16(右)の Llama2 7B モデルを使用した WebLLM チャット デモ。

すべての GPU が 16 ビットの浮動小数点値をサポートしているわけではありません。GPUAdapter"shader-f16" 機能を使用できるようになりました。この機能を使用して GPUDevice をリクエストし、半精度浮動小数点型 f16 を活用する WGSL シェーダー モジュールを作成できます。この型は、enable f16;f16 WGSL 拡張機能を有効にしている場合にのみ、WGSL シェーダー モジュールで使用できます。それ以外の場合、createShaderModule() は検証エラーを生成します。次の最小限の例と 問題 dawn:1510 をご覧ください。

const adapter = await navigator.gpu.requestAdapter();
if (!adapter.features.has("shader-f16")) {
  throw new Error("16-bit floating-point value support is not available");
}
// Explicitly request 16-bit floating-point value support.
const device = await adapter.requestDevice({
  requiredFeatures: ["shader-f16"],
});

const code = `
  enable f16;

  @compute @workgroup_size(1)
  fn main() {
    const c : vec3h = vec3<f16>(1.0h, 2.0h, 3.0h);
  }
`;

const shaderModule = device.createShaderModule({ code });
// Create a compute pipeline with this shader module
// and run the shader on the GPU...

次のスニペットに示すように、"shader-f16" 機能のサポートに応じて、WGSL シェーダー モジュール コードで f16 型と f32 型の両方を alias でサポートできます。

const adapter = await navigator.gpu.requestAdapter();
const hasShaderF16 = adapter.features.has("shader-f16");

const device = await adapter.requestDevice({
  requiredFeatures: hasShaderF16 ? ["shader-f16"] : [],
});

const header = hasShaderF16
  ? `enable f16;
     alias min16float = f16;`
  : `alias min16float = f32;`;

const code = `
  ${header}

  @compute @workgroup_size(1)
  fn main() {
    const c = vec3<min16float>(1.0, 2.0, 3.0);
  }
`;

限界に挑戦する

すべてのカラー アタッチメントにわたるレンダリング パイプライン出力データの 1 つのサンプル(ピクセルまたはサブピクセル)を保持するために必要な最大バイト数は、デフォルトで 32 バイトです。maxColorAttachmentBytesPerSample の上限を使用して、最大 64 個のリクエストを送信できるようになりました。次の例と 問題 dawn:2036 をご覧ください。

const adapter = await navigator.gpu.requestAdapter();

if (adapter.limits.maxColorAttachmentBytesPerSample < 64) {
  // When the desired limit isn't supported, take action to either fall back to
  // a code path that does not require the higher limit or notify the user that
  // their device does not meet minimum requirements.
}

// Request highest limit of max color attachments bytes per sample.
const device = await adapter.requestDevice({
  requiredLimits: { maxColorAttachmentBytesPerSample: 64 },
});

ステージ間の通信に使用される maxInterStageShaderVariablesmaxInterStageShaderComponents の上限が、すべてのプラットフォームで引き上げられました。詳しくは、問題 dawn:1448 をご覧ください。

シェーダー ステージごとに、パイプライン レイアウト全体でストレージ バッファであるバインディング グループ レイアウト エントリの最大数は、デフォルトで 8 です。maxStorageBuffersPerShaderStage の上限を使用して、最大 10 個のリクエストを送信できるようになりました。問題 dawn:2159 をご覧ください。

新しい maxBindGroupsPlusVertexBuffers の上限が追加されました。これは、同時に使用されるバインディング グループと頂点バッファ スロットの最大数で構成され、最大インデックスより下の空のスロットもカウントされます。デフォルト値は 24 です。問題 dawn:1849 をご覧ください。

深度ステンシル状態の変更

デベロッパー エクスペリエンスを改善するため、深度ステンシル状態の depthWriteEnabled 属性と depthCompare 属性が必ずしも必要ではなくなりました。depthWriteEnabled は深度のある形式でのみ必要で、depthCompare は深度のある形式で使用されていない場合は必要ありません。問題 dawn:2132 をご覧ください。

アダプタ情報の更新

ユーザーが chrome://flags/#enable-webgpu-developer-features で「WebGPU デベロッパー機能」フラグを有効にしている場合、requestAdapterInfo() を呼び出すと、標準以外の typebackend のアダプター情報属性が使用できるようになりました。type には、「ディスクトップ GPU」、「統合 GPU」、「CPU」、「不明」のいずれかを指定できます。backend は「WebGPU」、「D3D11」、「D3D12」、「metal」、「vulkan」、「openGL」、「openGLES」、「null」のいずれかです。問題 dawn:2112問題 dawn:2107 をご覧ください。

バックエンドとアダプタのタイプに関する情報が表示された https://webgpureport.org のスクリーンショット。
アダプター情報のバックエンドとタイプは https://webgpureport.org に表示されます。

requestAdapterInfo() の省略可能な unmaskHints リスト パラメータが削除されました。問題 dawn:1427 をご覧ください。

タイムスタンプ クエリの量子化

タイムスタンプ クエリを使用すると、GPU コマンドの実行時間をナノ秒単位の精度で測定できます。ただし、WebGPU 仕様では、タイミング攻撃の懸念から、タイムスタンプ クエリは省略可能です。Chrome チームは、タイムスタンプ クエリを量子化することで解像度を 100 マイクロ秒に減らし、精度とセキュリティのバランスをとることができると考えています。問題 dawn:1800 をご覧ください。

Chrome では、chrome://flags/#enable-webgpu-developer-features で「WebGPU デベロッパー向け機能」フラグを有効にすることで、タイムスタンプの量子化を無効にできます。このフラグだけでは "timestamp-query" 機能は有効になりません。実装はまだ試験運用版であるため、chrome://flags/#enable-unsafe-webgpu で「Unsafe WebGPU Support」フラグが必要です。

Dawn では、新しいデバイス切り替え「timestamp_quantization」が追加され、デフォルトで有効になっています。次のスニペットは、デバイスをリクエストするときに、タイムスタンプの量子化なしで試験運用版の「timestamp-query」機能を許可する方法を示しています。

wgpu::DawnTogglesDescriptor deviceTogglesDesc = {};

const char* allowUnsafeApisToggle = "allow_unsafe_apis";
deviceTogglesDesc.enabledToggles = &allowUnsafeApisToggle;
deviceTogglesDesc.enabledToggleCount = 1;

const char* timestampQuantizationToggle = "timestamp_quantization";
deviceTogglesDesc.disabledToggles = &timestampQuantizationToggle;
deviceTogglesDesc.disabledToggleCount = 1;

wgpu::DeviceDescriptor desc = {.nextInChain = &deviceTogglesDesc};

// Request a device with no timestamp quantization.
myAdapter.RequestDevice(&desc, myCallback, myUserData);

春の大掃除の機能

試験運用版の「timestamp-query-inside-passes」機能の名前が「chromium-experimental-timestamp-query-inside-passes」に変更されました。これは、この機能が試験運用版であり、現時点では Chromium ベースのブラウザでのみ利用可能であることをデベロッパーに明確にするためです。問題 dawn:1193 をご覧ください。

部分的にのみ実装されていた試験運用版の「pipeline-statistics-query」機能は、開発が終了したため削除されました。問題 chromium:1177506 をご覧ください。

以下に、主なハイライトをいくつかご紹介します。コミットの一覧(すべて網羅)をご覧ください。

WebGPU の新機能

WebGPU の新機能シリーズで取り上げられたすべての内容のリスト。

Chrome 131

Chrome 130

Chrome 129

Chrome 128

Chrome 127

Chrome 126

Chrome 125

Chrome 124

Chrome 123

Chrome 122

Chrome 121

Chrome 120

Chrome 119

Chrome 118

Chrome 117

Chrome 116

Chrome 115

Chrome 114

Chrome 113