WebGPU 的新变化 (Chrome 121)

François Beaufort
François Beaufort

在 Android 上支持 WebGPU

Chrome 团队很高兴地宣布,在搭载 Android 12 及更高版本且由 Qualcomm 和 ARM GPU 提供支持的设备上,Chrome 121 现已默认启用 WebGPU。

支持范围将逐步扩大,以便在不久的将来涵盖更广泛的 Android 设备,包括搭载 Android 11 的设备。此扩展将取决于进一步的测试和优化,以确保在更广泛的硬件配置中获得无缝体验。请参阅问题 chromium:1497815

在 Chrome for Android 上运行的 WebGPU 示例的屏幕截图。
在 Chrome for Android 上运行的 WebGPU 示例。

在 Windows 上使用 DXC 而非 FXC 进行着色器编译

Chrome 现在使用 DXC (DirectX Compiler) 的强大功能在配备 SM6+ 图形硬件的 Windows D3D12 机器上编译着色器。以前,WebGPU 依赖于 FXC (FX Compiler) 在 Windows 上进行着色器编译。虽然 FXC 功能正常,但缺少 DXC 中提供的特征集和性能优化。

初始测试表明,与 FXC 相比,使用 DXC 时计算着色器编译速度平均提高了 20%。

计算和渲染通道中的时间戳查询

借助时间戳查询,WebGPU 应用可以精确测量(精确到纳秒)其 GPU 命令执行计算和渲染通道所需的时间。它们被广泛用于深入了解 GPU 工作负载的性能和行为。

"timestamp-query" 功能在 GPUAdapter 中可用时,您现在可以执行以下操作:

请参阅以下示例和问题 dawn:1800

const adapter = await navigator.gpu.requestAdapter();
if (!adapter.features.has("timestamp-query")) {
  throw new Error("Timestamp query feature is not available");
}
// Explicitly request timestamp query feature.
const device = await adapter.requestDevice({
  requiredFeatures: ["timestamp-query"],
});
const commandEncoder = device.createCommandEncoder();

// Create a GPUQuerySet which holds 2 timestamp query results: one for the
// beginning and one for the end of compute pass execution.
const querySet = device.createQuerySet({ type: "timestamp", count: 2 });
const timestampWrites = {
  querySet,
  beginningOfPassWriteIndex: 0, // Write timestamp in index 0 when pass begins.
  endOfPassWriteIndex: 1, // Write timestamp in index 1 when pass ends.
};
const passEncoder = commandEncoder.beginComputePass({ timestampWrites });
// TODO: Set pipeline, bind group, and dispatch work to be performed.
passEncoder.end();

// Resolve timestamps in nanoseconds as a 64-bit unsigned integer into a GPUBuffer.
const size = 2 * BigInt64Array.BYTES_PER_ELEMENT;
const resolveBuffer = device.createBuffer({
  size,
  usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC,
});
commandEncoder.resolveQuerySet(querySet, 0, 2, resolveBuffer, 0);

// Read GPUBuffer memory.
const resultBuffer = device.createBuffer({
  size,
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
});
commandEncoder.copyBufferToBuffer(resolveBuffer, 0, resultBuffer, 0, size);

// Submit commands to the GPU.
device.queue.submit([commandEncoder.finish()]);

// Log compute pass duration in nanoseconds.
await resultBuffer.mapAsync(GPUMapMode.READ);
const times = new BigInt64Array(resultBuffer.getMappedRange());
console.log(`Compute pass duration: ${Number(times[1] - times[0])}ns`);
resultBuffer.unmap();

出于对 时序攻击 的担忧,时间戳查询以 100 微秒的分辨率进行量化,这在精确度和安全性之间取得了良好的平衡。在 Chrome 浏览器中,您可以在开发应用期间通过在 chrome://flags/#enable-webgpu-developer-features 处启用“WebGPU 开发者功能” 标志来停用时间戳量化。如需了解详情,请参阅时间戳查询量化

由于 GPU 可能会偶尔重置时间戳计数器,这可能会导致出现意外值(例如时间戳之间的负增量),因此我建议您查看 git diff 更改,这些更改会将时间戳查询支持添加到以下 Compute Boids 示例中。

Compute Boids 示例的屏幕截图,其中显示了时间戳查询。
Compute Boids 示例,其中包含时间戳查询。

着色器模块的默认入口点

为了提升开发者体验,您现在可以在创建计算或渲染流水线时省略着色器模块的 entryPoint。如果在着色器代码中未找到着色器阶段的唯一入口点,系统将触发GPUValidationError。请参阅以下示例和 问题 dawn:2254

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 module = myDevice.createShaderModule({ code });
const format = navigator.gpu.getPreferredCanvasFormat();
const pipeline = await myDevice.createRenderPipelineAsync({
  layout: "auto",
  vertex: { module, entryPoint: "vertexMain" },
  fragment: { module, entryPoint: "fragmentMain", targets: [{ format }] },
  vertex: { module },
  fragment: { module, targets: [{ format }] },
});

支持 display-p3 作为 GPUExternalTexture 色彩空间

您现在可以使用 importExternalTexture() 从 HDR 视频导入 GPUExternalTexture 时设置 "display-p3" 目标色彩空间。了解 WebGPU 如何处理 色彩空间。请参阅以下示例和问题 chromium:1330250

// Create texture from HDR video.
const video = document.querySelector("video");
const texture = myDevice.importExternalTexture({
  source: video,
  colorSpace: "display-p3",
});

内存堆信息

为了帮助您在开发应用期间分配大量内存时预测内存限制,requestAdapterInfo() 现在会公开 memoryHeaps 信息,例如适配器上可用的内存堆的大小和类型。只有在 chrome://flags/#enable-webgpu-developer-features 处启用“WebGPU 开发者功能” 标志后,才能访问此实验性功能。请参阅以下示例和 问题 dawn:2249

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

for (const { size, properties } of adapterInfo.memoryHeaps) {
  console.log(size); // memory heap size in bytes
  if (properties & GPUHeapProperty.DEVICE_LOCAL)  { /* ... */ }
  if (properties & GPUHeapProperty.HOST_VISIBLE)  { /* ... */ }
  if (properties & GPUHeapProperty.HOST_COHERENT) { /* ... */ }
  if (properties & GPUHeapProperty.HOST_UNCACHED) { /* ... */ }
  if (properties & GPUHeapProperty.HOST_CACHED)   { /* ... */ }
}
https://webgpureport.org 的屏幕截图,其中显示了适配器信息中的内存堆。
https://webgpureport.org 上显示的适配器信息内存堆。

Dawn 更新

已添加 wgpu::Instance 上的 HasWGSLLanguageFeatureEnumerateWGSLLanguageFeatures 方法来处理 WGSL 语言功能。请参阅问题 dawn:2260

借助非标准 wgpu::Feature::BufferMapExtendedUsages 功能,您可以使用 wgpu::BufferUsage::MapReadwgpu::BufferUsage::MapWrite 以及任何其他 wgpu::BufferUsage 创建 GPU 缓冲区。请参阅以下示例和问题 dawn:2204

wgpu::BufferDescriptor descriptor = {
  .size = 128,
  .usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::Uniform
};
wgpu::Buffer uniformBuffer = device.CreateBuffer(&descriptor);

uniformBuffer.MapAsync(wgpu::MapMode::Write, 0, 128,
   [](WGPUBufferMapAsyncStatus status, void* userdata)
   {
      wgpu::Buffer* buffer = static_cast<wgpu::Buffer*>(userdata);
      memcpy(buffer->GetMappedRange(), data, sizeof(data));
   },
   &uniformBuffer);

以下功能已记录在文档中:ANGLE 纹理共享D3D11 多线程保护隐式设备同步Norm16 纹理格式通道内时间戳查询像素本地存储着色器功能多平面格式

Chrome 团队已为 Dawn 创建了一个官方 GitHub 代码库

这仅涵盖了一些主要亮点。查看提交的详尽列表

WebGPU 的新变化

WebGPU 新变化系列中涵盖的所有内容的列表。

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