Neu bei WebGPU (Chrome 121)

François Beaufort
François Beaufort

Unterstützung von WebGPU unter Android

Das Chrome-Team freut sich, bekannt geben zu können, dass die WebGPU in Chrome 121 auf Geräten mit Android 12 und höher, die von Qualcomm- und ARM-GPUs unterstützt werden, jetzt standardmäßig aktiviert ist.

Die Unterstützung wird nach und nach auf weitere Android-Geräte ausgeweitet, einschließlich derjenigen mit Android 11 in naher Zukunft. Diese Erweiterung hängt von weiteren Tests und Optimierungen ab, um eine nahtlose Nutzung über eine breitere Palette von Hardwarekonfigurationen hinweg zu gewährleisten. Siehe issue chromium:1497815.

<ph type="x-smartling-placeholder">
</ph> Screenshot des WebGPU-Beispiels, das in Chrome für Android ausgeführt wird
WebGPU-Beispiel, das mit Chrome für Android ausgeführt wird

DXC anstelle von FXC für die Shader-Kompilierung unter Windows verwenden

Chrome nutzt jetzt DXC (DirectX Compiler), um Shader auf Windows-D3D12-Computern zu kompilieren, die mit SM6+ Grafikhardware ausgestattet sind. Zuvor nutzte WebGPU für die Shader-Kompilierung unter Windows FXC (FX Compiler). Obwohl FXC funktionierte, fehlten die Funktionen und Leistungsoptimierungen von DXC.

Erste Tests ergaben einen durchschnittlichen Anstieg der Kompilierungsgeschwindigkeit von Computing-Shadern um 20% bei Verwendung von DXC im Vergleich zu FXC.

Zeitstempelabfragen in Rechen- und Renderingdurchläufen

Mit Zeitstempelabfragen können WebGPU-Anwendungen bis auf die Nanosekunde genau messen, wie viel Zeit ihre GPU-Befehle für die Ausführung von Rechen- und Renderingläufen benötigen. Sie werden häufig verwendet, um Einblicke in die Leistung und das Verhalten von GPU-Arbeitslasten zu erhalten.

Wenn die Funktion "timestamp-query" in einem GPUAdapter verfügbar ist, haben Sie jetzt folgende Möglichkeiten:

  • Fordern Sie ein GPUDevice mit der Funktion "timestamp-query" an.
  • Erstellen Sie eine GPUQuerySet vom Typ "timestamp".
  • Verwenden Sie GPUComputePassDescriptor.timestampWrites und GPURenderPassDescriptor.timestampWrites, um zu definieren, wo Zeitstempelwerte in GPUQuerySet geschrieben werden sollen.
  • Lösen Sie Zeitstempelwerte mithilfe von resolveQuerySet() in eine GPUBuffer auf.
  • Lesen Sie Zeitstempelwerte zurück, indem Sie die Ergebnisse aus dem GPUBuffer in die CPU kopieren.
  • Decodieren Sie Zeitstempelwerte als BigInt64Array.

Sehen Sie sich das folgende Beispiel an und geben Sie dawn:1800 aus.

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();

Aufgrund von zeitlichen Angriffen werden Zeitstempelabfragen mit einer Auflösung von 100 Mikrosekunden quantisiert, was einen guten Kompromiss zwischen Genauigkeit und Sicherheit darstellt. Im Chrome-Browser können Sie die Quantisierung von Zeitstempeln deaktivieren, indem Sie „WebGPU Developer Features“ aktivieren flag bei der Entwicklung deiner App unter chrome://flags/#enable-webgpu-developer-features. Weitere Informationen finden Sie unter Quantisierung von Zeitstempelabfragen.

Da GPUs den Zeitstempelzähler gelegentlich zurücksetzen, was zu unerwarteten Werten wie negativen Deltas zwischen Zeitstempeln führen kann, sollten Sie sich die Änderungen an Git diff ansehen, durch die Zeitstempelabfragen für das folgende Compute Boids-Beispiel unterstützt werden.

<ph type="x-smartling-placeholder">
</ph> Screenshot des Compute Boids-Beispiels mit Zeitstempelabfrage
Compute Boids-Beispiel mit Zeitstempelabfrage.

Standardeinstiegspunkte für Shader-Module

Zur Verbesserung der Entwicklererfahrung können Sie jetzt beim Erstellen einer Compute- oder Rendering-Pipeline das entryPoint Ihres Shader-Moduls weglassen. Wenn im Shader-Code kein eindeutiger Einstiegspunkt für die Shader-Phase gefunden wird, wird ein GPUValidationError ausgelöst. Sehen Sie sich das folgende Beispiel und issue dawn:2254 an.

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“ als GPUExternalTexture-Farbraum unterstützen

Du kannst jetzt den Zielfarbraum "display-p3" festlegen, wenn du eine GPUExternalTexture aus HDR-Videos mit importExternalTexture() importierst. Weitere Informationen dazu, wie die WebGPU Farbräume handhabt Sehen Sie sich das folgende Beispiel an und geben Sie den Fehler chromium:1330250 an.

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

Informationen zu Arbeitsspeicher-Heaps

Damit Sie Arbeitsspeicherbeschränkungen bei der Zuweisung großer Mengen während der Entwicklung Ihrer App vorhersehen können, macht requestAdapterInfo() jetzt memoryHeaps-Informationen wie die Größe und den Typ der im Adapter verfügbaren Speicher-Heaps verfügbar. Diese experimentelle Funktion ist nur verfügbar, wenn die „WebGPU Developer Features“ flag unter chrome://flags/#enable-webgpu-developer-features ist aktiviert. Sehen Sie sich das folgende Beispiel und issue dawn:2249 an.

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)   { /* ... */ }
}
Screenshot von https://webgpureport.org mit Speicher-Heaps in den Adapterinformationen.
Informationen zu Arbeitsspeicher-Heaps des Adapters unter https://webgpureport.org.

Updates zur Morgendämmerung

Die Methoden HasWGSLLanguageFeature und EnumerateWGSLLanguageFeatures für wgpu::Instance wurden zur Verarbeitung der WGSL-Sprachfunktionen hinzugefügt. Siehe Problem dawn:2260.

Mit der nicht standardmäßigen Funktion wgpu::Feature::BufferMapExtendedUsages können Sie einen GPU-Zwischenspeicher mit wgpu::BufferUsage::MapRead oder wgpu::BufferUsage::MapWrite und einem beliebigen anderen wgpu::BufferUsage erstellen. Sehen Sie sich das folgende Beispiel an und geben Sie dawn:2204 aus.

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);

Die folgenden Funktionen wurden dokumentiert: ANGLE-Texturfreigabe, D3D11-Multithread-geschützt, implizite Gerätesynchronisierung, Norm16-Texturformate, Zeitstempelabfrage in Karten/Tickets, Lokaler Pixel-Speicher, Shader-Funktionen und Multiplanare Formate.

Das Chrome-Team hat ein offizielles GitHub-Repository für Dawn erstellt.

Hier werden nur einige der wichtigsten Vorteile behandelt. Vollständige Liste der Commits

Das ist neu bei WebGPU

Eine Liste aller behandelten Themen der Reihe What's New in WebGPU.

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