Start · Sprachen · JavaScript · Referenz · GPUQueue.writeBuffer()

GPUQueue.writeBuffer()

Methode

Schreibt Daten aus einem <code>ArrayBuffer</code>, TypedArray oder <code>DataView</code> über die Befehlswarteschlange in einen <code>GPUBuffer</code>.

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

Signatur

GPUQueue.prototype.writeBuffer(buffer, bufferOffset, data, dataOffset, size)

Beschreibung

writeBuffer() ist der einfachste Weg, Daten von der CPU in einen GPUBuffer zu übertragen. Die Methode kopiert den angegebenen Datenbereich sofort bei ihrem Aufruf. Danach kannst du das Quell-Array direkt wiederverwenden oder verändern. Die eigentliche Übertragung zur GPU reiht der Browser in die Queue ein. Sie findet also vor allen Befehlspuffern statt, die du danach mit queue.submit() abschickst.

Typische Anwendungen sind Uniform-Daten, die sich in jedem Frame ändern (Matrizen, Zeit, Mausposition), Teilaktualisierungen von Vertex- oder Storage-Buffern und das erste Befüllen von Buffern, wenn mappedAtCreation zu umständlich ist. Anders als bei mapAsync() brauchst du kein Promise und musst den Buffer nicht zuordnen (mappen) und wieder freigeben.

Der Ziel-Buffer braucht das Nutzungsflag GPUBufferUsage.COPY_DST. bufferOffset und die tatsächlich geschriebene Byteanzahl müssen Vielfache von 4 sein. Wichtig: Ist data ein TypedArray, gibst du dataOffset und size in Elementen an. Bei ArrayBuffer und DataView gibst du beides in Bytes an.

Parameter

Name Typ Default Beschreibung
$buffer Pflicht GPUBuffer Der Ziel-Buffer. Er braucht das Nutzungsflag GPUBufferUsage.COPY_DST und darf beim Ausführen weder gemappt noch zerstört sein.
$bufferOffset Pflicht number Byte-Offset im Ziel-Buffer, ab dem geschrieben wird. Muss ein Vielfaches von 4 sein.
$data Pflicht ArrayBuffer | SharedArrayBuffer | TypedArray | DataView Die Quelldaten, die in den Buffer kopiert werden.
$dataOffset number 0 Startposition in data. Bei TypedArrays in Elementen, sonst in Bytes.
$size number Rest von data ab dataOffset Menge der zu schreibenden Daten. Bei TypedArrays in Elementen, sonst in Bytes. Umgerechnet in Bytes muss der Wert ein Vielfaches von 4 sein.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Die Methode wartet nicht auf die GPU. Die Reihenfolge gegenüber späteren submit()-Aufrufen ist trotzdem garantiert.

Beispiele

Uniform-Buffer in jedem Frame aktualisieren

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

// 4 Floats: Zeit, Breite, Höhe, Padding
const uniformBuffer = device.createBuffer({
  size: 16,
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
});

const uniforms = new Float32Array(4);

const frame = (t) => {
  uniforms[0] = t / 1000;
  uniforms[1] = innerWidth;
  uniforms[2] = innerHeight;
  device.queue.writeBuffer(uniformBuffer, 0, uniforms);
  // ... Render-Pass kodieren und device.queue.submit([...])
  requestAnimationFrame(frame);
};
requestAnimationFrame(frame);

Vertex-Daten teilweise ersetzen (dataOffset/size in Elementen)

const vertices = new Float32Array([
  0.0,  0.5,   // Vertex 0
 -0.5, -0.5,   // Vertex 1
  0.5, -0.5,   // Vertex 2
]);

const vertexBuffer = device.createBuffer({
  size: vertices.byteLength, // 24 Bytes
  usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
});
device.queue.writeBuffer(vertexBuffer, 0, vertices);

// Nur Vertex 1 (Elemente 2 und 3) verschieben
vertices[2] = -0.8;
vertices[3] = -0.8;
// bufferOffset in Bytes (2 * 4 = 8), dataOffset/size in Elementen
device.queue.writeBuffer(vertexBuffer, 8, vertices, 2, 2);

Gemischte Datentypen mit ArrayBuffer (Angaben in Bytes)

const data = new ArrayBuffer(32);
const f32 = new Float32Array(data, 0, 4);
const u32 = new Uint32Array(data, 16, 4);
f32.set([1, 0, 0, 1]);   // Farbe RGBA
u32.set([42, 7, 0, 0]);  // IDs/Flags

const storage = device.createBuffer({
  size: 32,
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
});

// Nur den u32-Teil schreiben: 16 Bytes ab Byte 16
device.queue.writeBuffer(storage, 16, data, 16, 16);

Validierungsfehler abfangen

device.pushErrorScope('validation');

const noCopyDst = device.createBuffer({
  size: 16,
  usage: GPUBufferUsage.UNIFORM, // COPY_DST fehlt!
});
device.queue.writeBuffer(noCopyDst, 0, new Float32Array(4));

const error = await device.popErrorScope();
console.log(error?.constructor.name);
GPUValidationError

// Wichtig · Fallstricke

  • Einheiten verwechselt: bufferOffset gibst du immer in Bytes an. dataOffset und size gibst du bei TypedArrays in Elementen an, bei ArrayBuffer/DataView in Bytes. Das ist die häufigste Fehlerquelle.
  • Ausrichtung: bufferOffset und die geschriebene Byteanzahl müssen Vielfache von 4 sein. Ein Uint8Array mit 3 Bytes führt deshalb zu einem Validierungsfehler.
  • Fehlerverhalten: Liegt der Bereich dataOffset/size außerhalb von data, wirft der Aufruf sofort eine OperationError-DOMException. Andere Fehler meldet die GPU asynchron als GPUValidationError, zum Beispiel ein fehlendes COPY_DST, ein Schreiben über das Buffer-Ende hinaus oder ein gemappter bzw. zerstörter Buffer. Diese Fehler fängst du über pushErrorScope() oder das Ereignis uncapturederror ab.
  • Performance: Jeder Aufruf erzeugt eine interne Kopie. Bei vielen kleinen Updates ist es schneller, die Daten in einem Array zu sammeln und einmal zu schreiben. Für sehr große Datenströme kann ein Staging-Buffer mit mapAsync() und copyBufferToBuffer() günstiger sein.
  • Uniform-Layout: Achte bei WGSL-Structs auf die Ausrichtungsregeln. Ein vec3f belegt zum Beispiel 16 Bytes. Deine JS-Daten müssen das Padding abbilden.
  • Kompatibilität: WebGPU steht nur in sicheren Kontexten zur Verfügung und ist noch nicht überall aktiviert. Prüfe vorher, ob navigator.gpu vorhanden ist.