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 ビットの浮動小数点値をサポートしているわけではありません。"shader-f16" 機能が GPUAdapter で利用可能になると、この機能を使用して GPUDevice をリクエストし、半精度浮動小数点型 f16 を利用する WGSL シェーダー モジュールを作成できるようになります。この型は、enable f16;f16 WGSL 拡張機能を有効にした場合にのみ、WGSL シェーダー モジュールで使用できます。それ以外の場合、createShaderModule() は検証エラーを生成します。次の最小限の例と issue 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" 機能のサポートに応じて alias を使用して、WGSL シェーダー モジュール コードで f16 型と f32 型の両方をサポートできます。

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 個のリクエストが可能になりました。次の例と issue 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() を呼び出すと、標準以外の type アダプターと backend アダプターの情報属性が利用できるようになりました。type には、「discrete GPU」、「integrated GPU」、「CPU」、「unknown」を指定できます。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 で「安全でない WebGPU サポート」フラグが必要です。

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 140

Chrome 139

Chrome 138

Chrome 137

Chrome 136

Chrome 135

Chrome 134

Chrome 133

Chrome 132

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