Start · Sprachen · JavaScript · Referenz · GPUBuffer.mapState

GPUBuffer.mapState

Eigenschaft

Schreibgeschützte Eigenschaft, die angibt, ob ein <code>GPUBuffer</code> gerade nicht gemappt (<code>"unmapped"</code>), im Mapping-Vorgang (<code>"pending"</code>) oder gemappt (<code>"mapped"</code>) ist.

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

Signatur

GPUBuffer.mapState

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ülltes mapAsync() oder weil er mit mappedAtCreation: true erzeugt 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

Typ
"unmapped" | "pending" | "mapped"
Beschreibung
Eine Zeichenkette (Enum 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
unmapped pending mapped 4 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
mapped 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]);
true

// Wichtig · Fallstricke

  • Schreibgeschützt: Den Zustand änderst du nur über mapAsync(), unmap(), destroy() oder mappedAtCreation. Eine Zuweisung an mapState wird ignoriert.
  • Ein zweites mapAsync(), während der Zustand "pending" oder "mapped" ist, führt zu einem Validierungsfehler, und das Promise wird mit einer OperationError-DOMException abgelehnt. Prüfe vorher mapState.
  • Wird unmap() oder destroy() im Zustand "pending" aufgerufen, wird das mapAsync()-Promise mit einer AbortError-DOMException abgelehnt, und der Zustand springt auf "unmapped".
  • Ein gemappter Puffer darf nicht in einer queue.submit() verwendet werden. Sonst gibt es einen Validierungsfehler. Also immer vorher unmap() aufrufen.
  • Nach destroy() meldet mapState "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.