Signatur
Beschreibung
Die Eigenschaft mapState der Schnittstelle GPUBuffer liefert den aktuellen Zuordnungszustand (Mapping-Zustand) eines GPU-Puffers als Zeichenkette. Ein Puffer muss gemappt sein, damit die CPU über getMappedRange() seinen Inhalt lesen oder beschreiben kann. Solange er gemappt ist, kann die GPU ihn nicht nutzen.
Mögliche Werte:
"unmapped"– Der Puffer ist nicht gemappt und kann in GPU-Befehlen verwendet werden."pending"–mapAsync()wurde aufgerufen, das zurückgegebene Promise ist aber noch nicht erfüllt."mapped"– Der Puffer ist gemappt, entweder durch ein erfülltesmapAsync()oder weil er mitmappedAtCreation: trueerzeugt wurde.getMappedRange()ist jetzt möglich.
Nützlich ist mapState vor allem, um doppelte mapAsync()-Aufrufe zu vermeiden (die einen Validierungsfehler auslösen würden), um bei Pools von Staging-Puffern (Readback/Upload) freie Puffer zu finden und zum Debuggen des Puffer-Lebenszyklus.
Rückgabewert
GPUBufferMapState), die den aktuellen Mapping-Zustand des Puffers beschreibt.Beispiele
Zustandswechsel beim Auslesen eines Puffers verfolgen
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const readBuffer = device.createBuffer({
size: 16,
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
});
console.log(readBuffer.mapState); // unmapped
const promise = readBuffer.mapAsync(GPUMapMode.READ);
console.log(readBuffer.mapState); // pending
await promise;
console.log(readBuffer.mapState); // mapped
const data = new Float32Array(readBuffer.getMappedRange());
console.log(data.length);
readBuffer.unmap();
console.log(readBuffer.mapState); // unmapped
mappedAtCreation: Puffer ist sofort gemappt
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,
});
console.log(vertexBuffer.mapState); // mapped
new Float32Array(vertexBuffer.getMappedRange()).set(vertices);
vertexBuffer.unmap();
console.log(vertexBuffer.mapState); // unmapped
Freien Staging-Puffer aus einem Pool wählen
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const pool = Array.from({ length: 3 }, () =>
device.createBuffer({
size: 256,
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
})
);
// Nur Puffer verwenden, die weder gemappt noch im Mapping sind
const getFreeBuffer = () =>
pool.find((buf) => buf.mapState === 'unmapped') ??
device.createBuffer({
size: 256,
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
});
pool[0].mapAsync(GPUMapMode.READ); // pool[0] ist jetzt "pending"
const free = getFreeBuffer();
console.log(free === pool[1]);
// Wichtig · Fallstricke
- Schreibgeschützt: Den Zustand änderst du nur über
mapAsync(),unmap(),destroy()odermappedAtCreation. Eine Zuweisung anmapStatewird ignoriert. - Ein zweites
mapAsync(), während der Zustand"pending"oder"mapped"ist, führt zu einem Validierungsfehler, und das Promise wird mit einerOperationError-DOMExceptionabgelehnt. Prüfe vorhermapState. - Wird
unmap()oderdestroy()im Zustand"pending"aufgerufen, wird dasmapAsync()-Promise mit einerAbortError-DOMExceptionabgelehnt, und der Zustand springt auf"unmapped". - Ein gemappter Puffer darf nicht in einer
queue.submit()verwendet werden. Sonst gibt es einen Validierungsfehler. Also immer vorherunmap()aufrufen. - Nach
destroy()meldetmapState"unmapped". Der Puffer ist trotzdem unbrauchbar. - Kompatibilität: WebGPU gibt es nur in sicheren Kontexten und noch nicht in allen Browsern bzw. auf allen Plattformen. Prüfe vorher mit
if (!navigator.gpu). In Web Workern ist die API ebenfalls verfügbar.