Signatur
Beschreibung
Mit insertDebugMarker() markierst du einen einzelnen Punkt in der Befehlsfolge eines GPURenderPassEncoder mit einem Text-Label. Die Markierung hat keinen Einfluss auf das Rendering. Sie ist nur für Entwicklerwerkzeuge gedacht, etwa für Frame-Capture-Werkzeuge wie RenderDoc, PIX oder Xcode GPU Frame Capture und teilweise auch für Fehlermeldungen der WebGPU-Implementierung.
Anders als bei pushDebugGroup()/popDebugGroup(), die einen Bereich von Befehlen einrahmen, entsteht hier nur ein einzelner Punkt ohne Dauer. Das passt z. B. vor einem bestimmten draw()-Aufruf, nach einem Pipeline-Wechsel oder an der Stelle, an der ein bestimmtes Objekt gezeichnet wird.
Die Methode steht über das Mixin GPUDebugCommandsMixin auch in GPUCommandEncoder, GPUComputePassEncoder und GPURenderBundleEncoder bereit. Das Verhalten ist dort gleich.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $markerLabel Pflicht | string | Text der Markierung, wie er in Debugging-Werkzeugen angezeigt wird. Wähle ihn möglichst aussagekräftig, z. B. "Draw: Spieler-Mesh". |
Rückgabewert
undefined).Beispiele
Marker vor einem Draw-Aufruf setzen
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const context = document.querySelector('canvas').getContext('webgpu');
const format = navigator.gpu.getPreferredCanvasFormat();
context.configure({ device, format });
const module = device.createShaderModule({
code: `
@vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
var p = array(vec2f(0.0, 0.5), vec2f(-0.5, -0.5), vec2f(0.5, -0.5));
return vec4f(p[i], 0.0, 1.0);
}
@fragment fn fs() -> @location(0) vec4f { return vec4f(1.0, 0.4, 0.0, 1.0); }
`
});
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: { module, entryPoint: 'vs' },
fragment: { module, entryPoint: 'fs', targets: [{ format }] }
});
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [{
view: context.getCurrentTexture().createView(),
clearValue: { r: 0, g: 0, b: 0, a: 1 },
loadOp: 'clear',
storeOp: 'store'
}]
});
pass.setPipeline(pipeline);
pass.insertDebugMarker('Draw: Dreieck');
pass.draw(3);
pass.end();
device.queue.submit([encoder.finish()]);
Marker innerhalb einer Debug-Gruppe für mehrere Objekte
// Annahme: pass, pipeline und meshes (mit vertexBuffer, vertexCount, name) existieren bereits
const drawScene = (pass, pipeline, meshes) => {
pass.pushDebugGroup('Szene');
pass.setPipeline(pipeline);
meshes.forEach((mesh, index) => {
pass.insertDebugMarker(`Mesh #${index}: ${mesh.name}`);
pass.setVertexBuffer(0, mesh.vertexBuffer);
pass.draw(mesh.vertexCount);
});
pass.popDebugGroup();
};
Marker nur im Entwicklungsmodus setzen
const DEBUG = location.hostname === 'localhost';
const mark = (pass, label) => {
if (DEBUG) pass.insertDebugMarker(label);
};
// Verwendung im Render-Loop
mark(pass, 'Nach Pipeline-Wechsel: Transparenz');
pass.setPipeline(transparentPipeline);
pass.draw(6);
// Wichtig · Fallstricke
- Nur im aktiven Pass: Wird die Methode nach
pass.end()aufgerufen, entsteht ein Validierungsfehler, und der Encoder wird ungültig. Beim späterenencoder.finish()kommt dann ein ungültiger Befehlspuffer heraus. Fehler landen nicht als Exception im Code, sondern kommen überdevice.pushErrorScope()bzw. das Ereignisuncapturederror. - Keine Wirkung im Browser selbst: Die Markierungen erscheinen nicht in den normalen DevTools-Konsolen, sondern nur in nativen GPU-Debuggern oder in Fehlermeldungen der Implementierung.
- Performance: Der Aufwand ist gering, aber nicht null. Bei sehr vielen Draw-Aufrufen pro Frame lohnt es sich, Marker in Produktion abzuschalten.
- Kompatibilität: WebGPU gibt es nur in sicheren Kontexten und noch nicht in allen Browsern bzw. auf allen Plattformen. Prüfe vorher
navigator.gpu. - Labels von Objekten (
label-Eigenschaft beim Erstellen) ergänzen Debug-Marker sinnvoll und machen Fehlermeldungen lesbarer.