Start · Sprachen · JavaScript · Referenz · GPUBuffer.unmap()

GPUBuffer.unmap()

Methode

Hebt das Mapping eines <code>GPUBuffer</code> auf, damit die GPU den Puffer wieder nutzen kann. Alle zuvor über <code>getMappedRange()</code> geholten <code>ArrayBuffer</code> werden dabei abgetrennt.

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

Signatur

GPUBuffer.prototype.unmap()

Beschreibung

unmap() beendet den gemappten Zustand eines GPUBuffer. Ein Puffer ist entweder nach einem erfolgreichen mapAsync() gemappt oder direkt nach der Erstellung, wenn mappedAtCreation: true gesetzt war. Solange er gemappt ist, kann nur JavaScript auf seinen Speicher zugreifen, und zwar über getMappedRange(). Die GPU kann ihn in dieser Zeit nicht verwenden. Erst nach unmap() darf der Puffer wieder in Befehlen wie copyBufferToBuffer(), Bind-Groups oder queue.submit() vorkommen.

Beim Aufruf werden alle ArrayBuffer, die getMappedRange() geliefert hat, abgetrennt (detached). Ihre byteLength ist danach 0, und jeder Zugriff über ein Typed Array ergibt nichts mehr. Daten, die du später noch brauchst, musst du also vor dem Aufruf kopieren, zum Beispiel mit slice().

Typische Abläufe:

  • Hochladen: Puffer mit mappedAtCreation: true erstellen, Daten in getMappedRange() schreiben, dann unmap() aufrufen.
  • Zurücklesen: Ergebnis in einen Puffer mit MAP_READ | COPY_DST kopieren, await mapAsync(GPUMapMode.READ) ausführen, Daten kopieren, dann unmap() aufrufen.

Rufst du unmap() auf, während ein mapAsync()-Aufruf noch läuft, wird dessen Promise mit einem AbortError abgelehnt.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Der Zustand des Puffers (buffer.mapState) ist danach "unmapped".

Beispiele

Vertex-Daten mit mappedAtCreation hochladen

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

const vertices = new Float32Array([0, 0.5, -0.5, -0.5, 0.5, -0.5]);

const vertexBuffer = device.createBuffer({
  size: vertices.byteLength,
  usage: GPUBufferUsage.VERTEX,
  mappedAtCreation: true
});

// Daten direkt in den gemappten Bereich schreiben
new Float32Array(vertexBuffer.getMappedRange()).set(vertices);

// Freigeben – ab jetzt darf die GPU den Puffer nutzen
vertexBuffer.unmap();
console.log(vertexBuffer.mapState);
unmapped

Compute-Ergebnis zurücklesen und danach freigeben

// Annahme: device und outputBuffer (usage STORAGE | COPY_SRC) existieren bereits
const size = 16;
const readBuffer = device.createBuffer({
  size,
  usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
});

const encoder = device.createCommandEncoder();
encoder.copyBufferToBuffer(outputBuffer, 0, readBuffer, 0, size);
device.queue.submit([encoder.finish()]);

await readBuffer.mapAsync(GPUMapMode.READ);
// Kopie anlegen, BEVOR unmap() den ArrayBuffer abtrennt
const result = new Float32Array(readBuffer.getMappedRange().slice(0));
readBuffer.unmap();

console.log(result);
Float32Array(4) [ ... Ergebniswerte ... ]

Fallstrick: abgetrennter ArrayBuffer nach unmap()

const buf = device.createBuffer({
  size: 8,
  usage: GPUBufferUsage.COPY_SRC,
  mappedAtCreation: true
});

const view = new Uint32Array(buf.getMappedRange());
view[0] = 42;
buf.unmap();

console.log(view.length);      // Ansicht ist jetzt leer
console.log(view.buffer.byteLength);
0 0

Laufendes mapAsync() abbrechen

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

const pending = staging.mapAsync(GPUMapMode.READ);
staging.unmap(); // bricht das ausstehende Mapping ab

try {
  await pending;
} catch (err) {
  console.log(err.name);
}
AbortError

// Wichtig · Fallstricke

  • Abgetrennte Puffer: Nach unmap() sind alle von getMappedRange() gelieferten ArrayBuffer unbrauchbar. Du bekommst dabei keine Fehlermeldung, die Ansicht ist einfach leer. Brauchst du die Daten weiter, kopiere sie vorher mit slice() oder structuredClone().
  • unmap() nicht vergessen: Wird ein gemappter Puffer in queue.submit(), writeBuffer() oder einer Bind-Group verwendet, entsteht ein Validierungsfehler. Der Befehlspuffer ist dann ungültig und die Befehle werden nicht ausgeführt.
  • Wird unmap() für einen Puffer aufgerufen, der gar nicht gemappt ist, passiert nichts. Es wird keine Ausnahme geworfen.
  • Ist ein Puffer mit mapAsync() im Modus WRITE gemappt, übernimmt erst unmap() die geschriebenen Daten in den GPU-Speicher.
  • Für wiederholte Lesevorgänge solltest du Staging-Puffer wiederverwenden (Map, Kopie, Unmap), statt jedes Mal neue anzulegen. Das spart Speicher und Rechenaufwand.
  • Kompatibilität: WebGPU steht nur in sicheren Kontexten (HTTPS) zur Verfügung. Die Unterstützung ist je nach Browser und Plattform unterschiedlich. Prüfe deshalb vorher, ob navigator.gpu vorhanden ist.