Signatur
Beschreibung
executeBundles() spielt Befehle ab, die vorher mit einem GPURenderBundleEncoder aufgezeichnet und per finish() zu einem GPURenderBundle abgeschlossen wurden. Ein solches Bundle enthält typischerweise setPipeline(), setBindGroup(), setVertexBuffer(), setIndexBuffer() und draw*()-Aufrufe. Die Bundles werden in der übergebenen Reihenfolge ausgeführt.
Render-Bundles sind dafür gedacht, die CPU-Last in JavaScript zu senken: Statt in jedem Frame hunderte Zeichenbefehle neu zu kodieren und zu validieren, zeichnet man sie einmal auf und verwendet sie in beliebig vielen Frames und Render-Passes wieder. Das lohnt sich vor allem bei statischen oder selten veränderten Szenenteilen (Umgebung, Gelände, UI-Hintergründe). Dynamische Daten lassen sich trotzdem ändern, indem man den Inhalt der referenzierten Buffer (z. B. Uniforms) per queue.writeBuffer() aktualisiert.
Wichtig: Nach dem Aufruf wird der Zustand des Render-Pass-Encoders zurückgesetzt – gesetzte Pipeline, Bind-Groups, Vertex- und Index-Buffer gelten danach nicht mehr. Wer im selben Pass weitere normale Zeichenbefehle absetzen will, muss diese Zustände neu setzen. Viewport, Scissor-Rechteck, Blend-Konstante und Stencil-Referenz werden dagegen nicht im Bundle gespeichert, sondern vom Render-Pass übernommen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $bundles Pflicht | Iterable<GPURenderBundle> | Ein Array (oder anderes Iterable) von GPURenderBundle-Objekten, deren aufgezeichnete Befehle in dieser Reihenfolge ausgeführt werden. Ein leeres Array ist erlaubt und setzt lediglich den Encoder-Zustand zurück. |
Rückgabewert
device.pushErrorScope() oder das uncapturederror-Event).Beispiele
Render-Bundle einmal aufzeichnen, jeden Frame ausführen
// Voraussetzung: device, context, pipeline und vertexBuffer existieren bereits
const format = navigator.gpu.getPreferredCanvasFormat();
// 1. Bundle einmalig aufzeichnen
const bundleEncoder = device.createRenderBundleEncoder({
colorFormats: [format] // muss zum Render-Pass passen
});
bundleEncoder.setPipeline(pipeline);
bundleEncoder.setVertexBuffer(0, vertexBuffer);
bundleEncoder.draw(3);
const triangleBundle = bundleEncoder.finish({ label: 'Dreieck-Bundle' });
// 2. In jedem Frame nur noch abspielen
const frame = () => {
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [{
view: context.getCurrentTexture().createView(),
clearValue: { r: 0.1, g: 0.1, b: 0.1, a: 1 },
loadOp: 'clear',
storeOp: 'store'
}]
});
pass.executeBundles([triangleBundle]);
pass.end();
device.queue.submit([encoder.finish()]);
requestAnimationFrame(frame);
};
requestAnimationFrame(frame);
Statische Szene per Bundle, dynamische Objekte direkt zeichnen
// staticBundles: Array von GPURenderBundle für Gelände, Gebäude usw.
const renderScene = (pass, staticBundles, player) => {
// Viewport gilt auch für die Bundles
pass.setViewport(0, 0, canvas.width, canvas.height, 0, 1);
// Statische Objekte in einem Rutsch
pass.executeBundles(staticBundles);
// ACHTUNG: Zustand wurde zurückgesetzt – alles neu setzen!
pass.setPipeline(player.pipeline);
pass.setBindGroup(0, player.bindGroup);
pass.setVertexBuffer(0, player.vertexBuffer);
pass.setIndexBuffer(player.indexBuffer, 'uint16');
pass.drawIndexed(player.indexCount);
};
Formatfehler im Bundle abfangen
device.pushErrorScope('validation');
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass(renderPassDescriptor);
// Bundle wurde mit colorFormats ['rgba8unorm'] erstellt,
// der Pass rendert aber in 'bgra8unorm' → ungültig
pass.executeBundles([mismatchedBundle]);
pass.end();
device.queue.submit([encoder.finish()]);
const error = await device.popErrorScope();
if (error) {
console.warn('Bundle passt nicht zum Pass:', error.message);
}
// Wichtig · Fallstricke
- Zustand wird zurückgesetzt: Nach
executeBundles()sind Pipeline, Bind-Groups sowie Vertex- und Index-Buffer des Passes nicht mehr gesetzt. Folgendedraw()-Aufrufe ohne erneutessetPipeline()sind ungültig. - Kompatibilität der Attachments:
colorFormats,depthStencilFormatundsampleCountdes Bundles müssen exakt zum Render-Pass passen. Wurde das Bundle ohnedepthReadOnly/stencilReadOnlyerstellt, darf der Pass das jeweilige Aspekt nicht schreibgeschützt nutzen. - Bundles erben keinen Zustand vom Pass (außer Viewport, Scissor, Blend-Konstante und Stencil-Referenz) und hinterlassen keinen – jedes Bundle muss seine Pipeline und Bind-Groups selbst setzen.
- Referenzierte Buffer dürfen beim Ausführen nicht zerstört sein; ihr Inhalt kann aber zwischen Frames verändert werden.
- Fehler werden asynchron über das WebGPU-Fehlermodell gemeldet, nicht als JavaScript-Ausnahme.
- Kompatibilität: WebGPU ist nur in sicheren Kontexten (HTTPS) verfügbar und noch nicht in allen Browsern bzw. Plattformen aktiviert – vorher
navigator.gpuprüfen.