Wat is er nieuw in WebGPU (Chrome 121)

François Beaufort
François Beaufort

Ondersteuning voor WebGPU op Android

Het Chrome-team is verheugd te kunnen melden dat WebGPU nu standaard is ingeschakeld in Chrome 121 op apparaten met Android 12 en hoger, aangestuurd door Qualcomm- en ARM-GPU's.

De ondersteuning wordt geleidelijk uitgebreid naar een breder scala aan Android-apparaten, waaronder apparaten die in de nabije toekomst op Android 11 draaien. Deze uitbreiding is afhankelijk van verdere tests en optimalisatie om een ​​naadloze ervaring te garanderen voor een breder scala aan hardwareconfiguraties. Zie probleem chromium:1497815 .

Schermafbeelding van WebGPU-voorbeeld dat draait op Chrome voor Android.
WebGPU-voorbeeld uitgevoerd op Chrome voor Android.

Gebruik DXC in plaats van FXC voor shadercompilatie op Windows

Chrome maakt nu gebruik van de kracht van DXC (DirectX Compiler) om shaders te compileren op Windows D3D12-computers met SM6+ grafische hardware. Voorheen vertrouwde WebGPU op FXC (FX Compiler) voor shadercompilatie op Windows. Hoewel FXC functioneel was, miste het de functieset en prestatieoptimalisaties van DXC.

Uit eerste tests blijkt dat de compilatiesnelheid van compute shaders gemiddeld met 20% toeneemt bij gebruik van DXC in vergelijking met FXC.

Tijdstempelquery's in compute- en renderpassen

Met tijdstempelquery's kunnen WebGPU-applicaties nauwkeurig (tot op de nanoseconde) meten hoeveel tijd hun GPU-opdrachten nodig hebben om compute- en renderpasses uit te voeren. Ze worden veel gebruikt om inzicht te krijgen in de prestaties en het gedrag van GPU-workloads.

Wanneer de functie "timestamp-query" beschikbaar is in een GPUAdapter , kunt u nu de volgende dingen doen:

  • Vraag een GPUDevice aan met de functie "timestamp-query" .
  • Maak een GPUQuerySet van het type "timestamp" .
  • Gebruik GPUComputePassDescriptor.timestampWrites en GPURenderPassDescriptor.timestampWrites om te definiëren waar tijdstempelwaarden in GPUQuerySet moeten worden geschreven.
  • Los tijdstempelwaarden op in een GPUBuffer met resolveQuerySet() .
  • Lees tijdstempelwaarden terug door de resultaten van de GPUBuffer naar de CPU te kopiëren.
  • Decodeer tijdstempelwaarden als een BigInt64Array .

Zie het volgende voorbeeld en geef dawn:1800 op.

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

Vanwege zorgen over timingaanvallen worden tijdstempelquery's gekwantiseerd met een resolutie van 100 microseconden, wat een goed compromis biedt tussen precisie en beveiliging. In de Chrome-browser kunt u tijdstempelkwantisering uitschakelen door de vlag 'WebGPU Developer Features' in te schakelen via chrome://flags/#enable-webgpu-developer-features tijdens de ontwikkeling van uw app. Zie Kwantisering van tijdstempelquery's voor meer informatie.

Omdat GPU's de tijdstempelteller af en toe opnieuw kunnen instellen, wat kan resulteren in onverwachte waarden zoals negatieve delta's tussen tijdstempels, raad ik u aan de wijzigingen in git diff te bekijken die ondersteuning voor tijdstempelquery's toevoegen aan het volgende Compute Boids -voorbeeld.

Schermafbeelding van Compute Boids-voorbeeld met tijdstempelquery.
Bereken Boids-voorbeeld met tijdstempelquery.

Standaard toegangspunten tot shadermodules

Om de ontwikkelaarservaring te verbeteren, kunt u nu het entryPoint van uw shadermodule weglaten bij het maken van een compute- of renderpipeline. Als er geen uniek entrypoint voor de shaderstage in de shadercode wordt gevonden, wordt een GPUValidationError geactiveerd. Zie het volgende voorbeeld en issue 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 }] },
});

Ondersteuning display-p3 als GPUExternalTexture-kleurruimte

U kunt nu de bestemmingskleurruimte "display-p3" instellen bij het importeren van een GPUExternalTexture uit HDR-video's met importExternalTexture() . Bekijk hoe WebGPU omgaat met kleurruimten . Zie het volgende voorbeeld en geef chromium:1330250 op.

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

Geheugenstapels info

Om u te helpen anticiperen op geheugenbeperkingen bij het toewijzen van grote hoeveelheden geheugen tijdens de ontwikkeling van uw app, geeft requestAdapterInfo() nu memoryHeaps informatie weer, zoals de grootte en het type van de geheugenheaps die beschikbaar zijn op de adapter. Deze experimentele functie is alleen toegankelijk wanneer de vlag 'WebGPU Developer Features' op chrome://flags/#enable-webgpu-developer-features is ingeschakeld. Zie het volgende voorbeeld en issue 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)   { /* ... */ }
}
Schermafbeelding van https://webgpureport.org met geheugenheaps in adapterinfo.
Adapter info geheugen heaps weergegeven op https://webgpureport.org .

Dawn-updates

De methoden HasWGSLLanguageFeature en EnumerateWGSLLanguageFeatures op wgpu::Instance zijn toegevoegd om WGSL-taalfuncties te verwerken. Zie issue dawn:2260 .

Met de niet-standaardfunctie wgpu::Feature::BufferMapExtendedUsages kunt u een GPU-buffer maken met wgpu::BufferUsage::MapRead of wgpu::BufferUsage::MapWrite en elke andere wgpu::BufferUsage . Zie het volgende voorbeeld en geef dawn:2204 op.

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

De volgende functies zijn gedocumenteerd: ANGLE Texture Sharing , D3D11 multithread protected , Impliciete apparaatsynchronisatie , Norm16-textuurformaten , Timestamp Query Inside Passes , Pixel Local Storage , Shader Features en Multi Planar Formats .

Het Chrome-team heeft een officiële GitHub-repository voor Dawn gemaakt.

Dit behandelt slechts enkele van de belangrijkste hoogtepunten. Bekijk de volledige lijst met commits .

Wat is er nieuw in WebGPU

Een lijst met alles wat in de serie Wat is er nieuw in WebGPU is behandeld.

Chroom 140

Chroom 139

Chroom 138

Chroom 137

Chroom 136

Chroom 135

Chroom 134

Chroom 133

Chroom 132

Chroom 131

Chroom 130

Chroom 129

Chroom 128

Chroom 127

Chroom 126

Chroom 125

Chroom 124

Chroom 123

Chroom 122

Chroom 121

Chroom 120

Chroom 119

Chroom 118

Chroom 117

Chroom 116

Chroom 115

Chroom 114

Chroom 113