Signatur
Beschreibung
popDebugGroup() schließt die zuletzt geöffnete Debug-Gruppe auf einem GPURenderBundleEncoder. Debug-Gruppen fassen mehrere aufgezeichnete Befehle, etwa setPipeline(), setBindGroup() oder draw(), unter einem Namen zusammen. Das Rendering selbst ändert sich dadurch nicht. Werkzeuge wie Chrome DevTools, PIX, RenderDoc oder der Xcode-GPU-Debugger zeigen die Befehle dann in dieser Gruppierung an. Auch in WebGPU-Validierungsfehlern können die Gruppen auftauchen, sodass du Fehler schneller einordnen kannst.
Debug-Gruppen verhalten sich wie ein Stapel: Jedes pushDebugGroup(label) legt eine Gruppe oben auf, jedes popDebugGroup() entfernt die oberste wieder. Gruppen lassen sich beliebig tief verschachteln. Vor dem Aufruf von GPURenderBundleEncoder.finish() muss der Stapel aber wieder leer sein.
Setze die Methode vor allem beim Aufbau wiederverwendbarer Render-Bundles ein, zum Beispiel für statische Szenenteile oder UI-Ebenen. Dort werden viele Zeichenbefehle einmal aufgezeichnet und später mit GPURenderPassEncoder.executeBundles() immer wieder ausgeführt. Mit sauber benannten Gruppen findest du dich bei der Fehlersuche in solchen Bundles viel leichter zurecht.
Rückgabewert
undefined).Beispiele
Einfache Debug-Gruppe in einem Render-Bundle
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const format = navigator.gpu.getPreferredCanvasFormat();
const module = device.createShaderModule({
code: `
@vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
var p = array<vec2f, 3>(vec2f(0, 0.5), vec2f(-0.5, -0.5), vec2f(0.5, -0.5));
return vec4f(p[i], 0, 1);
}
@fragment fn fs() -> @location(0) vec4f { return vec4f(1, 0.4, 0, 1); }
`
});
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: { module, entryPoint: 'vs' },
fragment: { module, entryPoint: 'fs', targets: [{ format }] }
});
const bundleEncoder = device.createRenderBundleEncoder({ colorFormats: [format] });
bundleEncoder.pushDebugGroup('Dreieck zeichnen');
bundleEncoder.setPipeline(pipeline);
bundleEncoder.draw(3);
bundleEncoder.popDebugGroup(); // Gruppe schließen
const bundle = bundleEncoder.finish({ label: 'Dreieck-Bundle' });
console.log(bundle.label);
Verschachtelte Gruppen für Szenenteile
// Annahme: device, format, terrainPipeline, treePipeline und bindGroup existieren bereits
const encoder = device.createRenderBundleEncoder({
colorFormats: [format],
depthStencilFormat: 'depth24plus'
});
encoder.pushDebugGroup('Statische Szene');
encoder.pushDebugGroup('Terrain');
encoder.setPipeline(terrainPipeline);
encoder.setBindGroup(0, bindGroup);
encoder.draw(6000);
encoder.popDebugGroup(); // schließt 'Terrain'
encoder.pushDebugGroup('Bäume (instanziert)');
encoder.setPipeline(treePipeline);
encoder.draw(36, 500);
encoder.popDebugGroup(); // schließt 'Bäume (instanziert)'
encoder.popDebugGroup(); // schließt 'Statische Szene'
const sceneBundle = encoder.finish();
Hilfsfunktion, die jedes push mit einem pop abschließt
// Schließt die Gruppe auch dann, wenn beim Aufzeichnen eine Ausnahme auftritt
const withDebugGroup = (encoder, label, record) => {
encoder.pushDebugGroup(label);
try {
record(encoder);
} finally {
encoder.popDebugGroup();
}
};
const encoder = device.createRenderBundleEncoder({ colorFormats: [format] });
withDebugGroup(encoder, 'UI-Overlay', (e) => {
e.setPipeline(uiPipeline);
e.draw(6, widgetCount);
});
const uiBundle = encoder.finish();
// Später im Frame
pass.executeBundles([uiBundle]);
// Wichtig · Fallstricke
- Stapel muss ausgeglichen sein: Ein
popDebugGroup()bei leerem Stapel ist ein Validierungsfehler. Er wirft keine JavaScript-Ausnahme. Stattdessen wird der Encoder ungültig, und das späterefinish()erzeugt ein ungültiges Bundle. Den Fehler bekommst du überdevice.pushErrorScope('validation')oder das Ereignisuncapturederrormit. - Offene Gruppen beim Abschließen: Sind beim Aufruf von
finish()noch Gruppen offen, ist das ebenfalls ein Validierungsfehler. Achte deshalb auch in Fehlerpfaden auf ein passendespopfür jedespush, zum Beispiel mittry/finally. - Gruppen gelten nur innerhalb des Bundles: Debug-Gruppen aus einem Render-Bundle reichen nicht in den umgebenden
GPURenderPassEncoderhinein. Umgekehrt kann eine im Render-Pass geöffnete Gruppe nicht im Bundle geschlossen werden. - Nach finish(): Rufst du die Methode nach
finish()auf, ist der Encoder bereits geschlossen, und der Aufruf erzeugt einen Validierungsfehler. - Performance: Debug-Gruppen kosten kaum etwas. Wenn du es ganz schlank willst, kannst du sie in Produktions-Builds hinter einem Debug-Schalter ausschalten.
- Kompatibilität: WebGPU gibt es nur in sicheren Kontexten. Chrome/Edge unterstützen es ab Version 113, Safari ab 26, Firefox ab 141 (zunächst nur unter Windows). Prüfe vorher mit
if (!navigator.gpu), ob WebGPU verfügbar ist.