Start · Sprachen · JavaScript · Referenz · GPUDevice.createBuffer()

GPUDevice.createBuffer()

Methode

Erstellt einen <code>GPUBuffer</code> – einen Speicherbereich auf der GPU für Rohdaten wie Vertices, Indizes, Uniforms oder Storage-Daten.

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

Signatur

GPUDevice.prototype.createBuffer(descriptor)

Beschreibung

createBuffer() reserviert auf einem GPUDevice einen linearen GPU-Speicherblock. Solche Puffer sind die Grundlage fast jeder WebGPU-Anwendung: Sie enthalten Vertex- und Indexdaten für Render-Pipelines, Uniform-Werte (z. B. Transformationsmatrizen), Daten für Compute-Shader oder dienen als Zwischenspeicher zum Zurücklesen von Ergebnissen auf die CPU.

Welche Operationen ein Puffer erlaubt, wird beim Erstellen über das Bitfeld usage festgelegt und lässt sich danach nicht mehr ändern. Die Flags stammen aus GPUBufferUsage (z. B. VERTEX, INDEX, UNIFORM, STORAGE, COPY_SRC, COPY_DST, MAP_READ, MAP_WRITE) und werden mit dem bitweisen ODER | kombiniert.

Um Daten in einen Puffer zu bekommen, gibt es drei übliche Wege: mappedAtCreation: true (Puffer ist direkt nach dem Erstellen per getMappedRange() beschreibbar, danach unmap()), GPUQueue.writeBuffer() (bequem für regelmäßig aktualisierte Daten, benötigt COPY_DST) oder ein Kopierbefehl aus einem anderen Puffer. Zum Auslesen auf der CPU nutzt man einen separaten Puffer mit MAP_READ | COPY_DST und mapAsync().

Parameter

Name Typ Default Beschreibung
$descriptor Pflicht GPUBufferDescriptor Objekt, das den Puffer beschreibt, mit folgenden Eigenschaften:
  • size (number, Pflicht): Größe in Bytes. Bei mappedAtCreation: true muss sie ein Vielfaches von 4 sein.
  • usage (number, Pflicht): Bitfeld aus GPUBufferUsage-Flags.
  • mappedAtCreation (boolean, optional, Standard false): Puffer wird sofort gemappt erstellt, damit die CPU ihn befüllen kann.
  • label (string, optional): Name zur Identifikation in Fehlermeldungen und Debugging-Tools.

Rückgabewert

Typ
GPUBuffer
Beschreibung
Ein neues GPUBuffer-Objekt. Bei ungültigem Deskriptor wird ein ungültiger Puffer zurückgegeben und ein Validierungsfehler auf dem Gerät gemeldet (keine Exception).

Beispiele

Vertex-Puffer mit mappedAtCreation befüllen

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

// Drei Eckpunkte eines Dreiecks (x, y)
const vertices = new Float32Array([
   0.0,  0.5,
  -0.5, -0.5,
   0.5, -0.5,
]);

const vertexBuffer = device.createBuffer({
  label: 'Dreieck-Vertices',
  size: vertices.byteLength, // 24 Bytes, Vielfaches von 4
  usage: GPUBufferUsage.VERTEX,
  mappedAtCreation: true,
});

// Daten direkt in den gemappten Bereich kopieren
new Float32Array(vertexBuffer.getMappedRange()).set(vertices);
vertexBuffer.unmap(); // erst jetzt ist der Puffer für die GPU nutzbar

console.log(vertexBuffer.size, vertexBuffer.mapState);
24 unmapped

Uniform-Puffer per writeBuffer aktualisieren

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

const uniformBuffer = device.createBuffer({
  label: 'Frame-Uniforms',
  size: 16, // z. B. vec4<f32>
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
});

const frame = (time) => {
  const data = new Float32Array([time / 1000, 0, 0, 0]);
  device.queue.writeBuffer(uniformBuffer, 0, data);
  // ... Render-Pass mit Bind-Group, die uniformBuffer enthält
  requestAnimationFrame(frame);
};
requestAnimationFrame(frame);

Compute-Ergebnis auf die CPU zurücklesen

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

const size = 4 * 4; // vier Float32-Werte

// Speicher, in den ein Compute-Shader schreibt
const storageBuffer = device.createBuffer({
  size,
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
});
device.queue.writeBuffer(storageBuffer, 0, new Float32Array([1, 2, 3, 4]));

// Lese-Puffer: MAP_READ darf nur mit COPY_DST kombiniert werden
const readBuffer = device.createBuffer({
  size,
  usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
});

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

await readBuffer.mapAsync(GPUMapMode.READ);
const result = new Float32Array(readBuffer.getMappedRange().slice(0));
readBuffer.unmap();
console.log(result);
Float32Array(4) [1, 2, 3, 4]

// Wichtig · Fallstricke

  • Keine Exceptions bei Validierungsfehlern: Ein ungültiger Deskriptor (z. B. MAP_READ zusammen mit etwas anderem als COPY_DST, oder size über device.limits.maxBufferSize) erzeugt einen ungültigen Puffer und einen Fehler, den man per device.pushErrorScope('validation') / popErrorScope() oder über das uncapturederror-Event abfangen kann. Nur eine ungültige usage-Kombination oder ein Fehlschlagen von mappedAtCreation wegen Speichermangel kann einen RangeError auslösen.
  • Vielfache von 4: Bei mappedAtCreation: true muss size durch 4 teilbar sein. writeBuffer() und Kopierbefehle verlangen ebenfalls auf 4 Bytes ausgerichtete Offsets und Größen.
  • Uniform-Layout: WGSL-Uniforms folgen strengen Alignment-Regeln (z. B. vec3<f32> belegt 16 Bytes). Gib lieber zu viel als zu wenig Größe an.
  • Nicht vergessen: unmap() – ein gemappter Puffer darf in keinem eingereichten Befehl verwendet werden.
  • Speicher freigeben: Nicht mehr benötigte Puffer mit buffer.destroy() freigeben, statt auf die Garbage Collection zu warten.
  • Kompatibilität: WebGPU gibt es nur in sicheren Kontexten und noch nicht in allen Browsern bzw. auf allen Plattformen. Vorher 'gpu' in navigator prüfen und beachten, dass requestAdapter() null liefern kann.