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 です。issue 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」のいずれかになります。issue dawn:2112issue dawn:2107 をご覧ください。

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

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

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

タイムスタンプ クエリを使用すると、アプリケーションは GPU コマンドの実行時間をナノ秒の精度で測定できます。ただし、WebGPU 仕様では、タイミング攻撃の懸念があるため、タイムスタンプ クエリはオプションになっています。Chrome チームは、解像度を 100 マイクロ秒に下げることで、タイムスタンプ クエリの量子化が精度とセキュリティのバランスをうまく取れると考えています。issue 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 149-150

Chrome 147-148

Chrome 146

Chrome 145

Chrome 144

Chrome 143

Chrome 142

Chrome 141

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