Start · Sprachen · JavaScript · Referenz · GPUCommandEncoder.clearBuffer()

GPUCommandEncoder.clearBuffer()

Methode

Kodiert einen Befehl in den Command-Encoder, der einen Bereich eines <code>GPUBuffer</code> auf der GPU mit Nullen füllt.

seit JavaScript WebGPU – Chrome/Edge 113+, Safari 26+, Firefox 141 Kategorie: webapi

Signatur

GPUCommandEncoder.prototype.clearBuffer(buffer, offset, size)

Beschreibung

clearBuffer() fügt dem GPUCommandEncoder einen Befehl hinzu, der einen Bereich eines GPUBuffer mit Null-Bytes überschreibt. Der Befehl läuft nicht sofort: Er wird erst ausgeführt, wenn der mit finish() erzeugte GPUCommandBuffer über device.queue.submit() an die GPU geschickt wird.

Typische Einsatzfälle sind das Zurücksetzen von Zählern, Histogrammen, atomaren Akkumulatoren oder Indirect-Draw-Argumenten vor einem Compute- oder Render-Pass. Gegenüber queue.writeBuffer() mit einem Null-Array spart clearBuffer() den Upload von der CPU: Es wird kein Speicher im Hauptprozess angelegt und nichts übertragen. Der Befehl ordnet sich außerdem sauber in die Befehlsfolge des Encoders ein, lässt sich also zwischen zwei Passes platzieren.

Ohne offset und size wird der ganze Puffer geleert. Mit offset allein wird alles ab dieser Position geleert. Beide Werte müssen Vielfache von 4 sein. Der Puffer muss mit dem Verwendungs-Flag GPUBufferUsage.COPY_DST angelegt worden sein.

Parameter

Name Typ Default Beschreibung
$buffer Pflicht GPUBuffer Der Puffer, der geleert werden soll. Er muss mit GPUBufferUsage.COPY_DST erstellt worden sein.
$offset number 0 Startposition in Bytes ab Pufferanfang. Muss ein Vielfaches von 4 sein.
$size number buffer.size - offset Anzahl der zu leerenden Bytes. Muss ein Vielfaches von 4 sein, und offset + size darf buffer.size nicht überschreiten.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Der Befehl wird nur im Encoder aufgezeichnet.

Beispiele

Ganzen Puffer leeren und das Ergebnis prüfen

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

// Quellpuffer mit Testdaten, muss COPY_DST (für clearBuffer) und COPY_SRC haben
const data = device.createBuffer({
  size: 16,
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
});
device.queue.writeBuffer(data, 0, new Uint32Array([1, 2, 3, 4]));

// Lesepuffer zum Zurücklesen auf die CPU
const readback = device.createBuffer({
  size: 16,
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
});

const encoder = device.createCommandEncoder();
encoder.clearBuffer(data); // kompletter Puffer auf 0
encoder.copyBufferToBuffer(data, 0, readback, 0, 16);
device.queue.submit([encoder.finish()]);

await readback.mapAsync(GPUMapMode.READ);
console.log(new Uint32Array(readback.getMappedRange()));
readback.unmap();
Uint32Array(4) [0, 0, 0, 0]

Nur einen Teilbereich leeren

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

const buf = device.createBuffer({
  size: 16,
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
});
device.queue.writeBuffer(buf, 0, new Uint32Array([10, 20, 30, 40]));

const readback = device.createBuffer({
  size: 16,
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
});

const encoder = device.createCommandEncoder();
// Bytes 4 bis 11 leeren, also die Elemente 1 und 2
encoder.clearBuffer(buf, 4, 8);
encoder.copyBufferToBuffer(buf, 0, readback, 0, 16);
device.queue.submit([encoder.finish()]);

await readback.mapAsync(GPUMapMode.READ);
console.log(new Uint32Array(readback.getMappedRange()));
readback.unmap();
Uint32Array(4) [10, 0, 0, 40]

Atomaren Zähler vor jedem Compute-Pass zurücksetzen

// Setzt voraus: device, pipeline und bindGroup existieren bereits.
// Der Shader zählt mit atomicAdd in counterBuffer.
const counterBuffer = device.createBuffer({
  size: 4,
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
});

const runFrame = () => {
  const encoder = device.createCommandEncoder();

  // Muss AUSSERHALB eines Passes stehen
  encoder.clearBuffer(counterBuffer);

  const pass = encoder.beginComputePass();
  pass.setPipeline(pipeline);
  pass.setBindGroup(0, bindGroup);
  pass.dispatchWorkgroups(64);
  pass.end();

  device.queue.submit([encoder.finish()]);
  requestAnimationFrame(runFrame);
};
requestAnimationFrame(runFrame);

// Wichtig · Fallstricke

  • Ausrichtung: offset und size müssen Vielfache von 4 sein. Andernfalls entsteht ein Validierungsfehler, und der Encoder wird ungültig. Das zeigt sich erst beim Aufruf von finish() bzw. submit() und nicht als JavaScript-Exception. Fehler fangen Sie mit device.pushErrorScope('validation') / popErrorScope() oder über das Ereignis uncapturederror.
  • Verwendungs-Flag: Fehlt GPUBufferUsage.COPY_DST beim Anlegen des Puffers, ist der Aufruf ungültig.
  • Grenzen: offset + size darf buffer.size nicht überschreiten.
  • Kein aktiver Pass: clearBuffer() darf nicht zwischen beginRenderPass()/beginComputePass() und end() stehen, solange ein Pass offen ist.
  • Der Puffer darf zum Zeitpunkt von submit() nicht gemappt sein.
  • Neu erstellte GPUBuffer sind laut Spezifikation schon mit Nullen gefüllt. clearBuffer() brauchen Sie also nur zum erneuten Zurücksetzen.
  • Kompatibilität: WebGPU ist noch nicht überall verfügbar. Prüfen Sie vorher mit if (!navigator.gpu) und planen Sie einen Ersatzweg ein. Die API gibt es nur in sicheren Kontexten und unter anderem auch in Web Workern.