Signatur
Beschreibung
end() schließt einen Renderpass ab, den Sie vorher mit GPUCommandEncoder.beginRenderPass() gestartet haben. Alle Befehle, die Sie auf dem GPURenderPassEncoder aufgezeichnet haben, etwa setPipeline(), setBindGroup(), setVertexBuffer() oder draw(), werden damit zum Teil der Befehlsfolge des übergeordneten GPUCommandEncoder.
Solange ein Renderpass offen ist, ist der GPUCommandEncoder gesperrt. Erst nach end() dürfen Sie auf ihm weitere Befehle aufzeichnen (z. B. copyTextureToBuffer(), einen weiteren Renderpass oder einen Compute-Pass) und schließlich mit finish() einen GPUCommandBuffer erzeugen. Rufen Sie finish() auf, während noch ein Pass offen ist, wird der Encoder ungültig.
end() führt selbst nichts auf der GPU aus. Es wird nur aufgezeichnet. Ausgeführt wird erst, wenn Sie den fertigen Befehlspuffer mit device.queue.submit() übergeben.
Rückgabewert
undefined).Beispiele
Einfacher Renderpass: Bildschirm löschen und Dreieck zeichnen
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const canvas = document.querySelector('canvas');
const context = 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.1, g: 0.1, b: 0.1, a: 1 },
loadOp: 'clear',
storeOp: 'store'
}]
});
pass.setPipeline(pipeline);
pass.draw(3);
pass.end(); // Renderpass abschließen
device.queue.submit([encoder.finish()]);
Mehrere Passes nacheinander auf einem Encoder
// Annahme: device, sceneView, postView, scenePipeline, postPipeline, postBindGroup existieren
const encoder = device.createCommandEncoder();
// Pass 1: Szene in eine Offscreen-Textur rendern
const scenePass = encoder.beginRenderPass({
colorAttachments: [{ view: sceneView, loadOp: 'clear', storeOp: 'store', clearValue: [0, 0, 0, 1] }]
});
scenePass.setPipeline(scenePipeline);
scenePass.draw(36);
scenePass.end(); // Muss vor dem nächsten beginRenderPass() erfolgen
// Pass 2: Nachbearbeitung auf dem Canvas
const postPass = encoder.beginRenderPass({
colorAttachments: [{ view: postView, loadOp: 'clear', storeOp: 'store', clearValue: [0, 0, 0, 1] }]
});
postPass.setPipeline(postPipeline);
postPass.setBindGroup(0, postBindGroup);
postPass.draw(3);
postPass.end();
device.queue.submit([encoder.finish()]);
Fehler erkennen: vergessenes end()
// Annahme: device und view existieren
device.pushErrorScope('validation');
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [{ view, loadOp: 'clear', storeOp: 'store' }]
});
// pass.end() fehlt!
const commandBuffer = encoder.finish();
device.queue.submit([commandBuffer]);
const error = await device.popErrorScope();
console.log(error ? `Validierungsfehler: ${error.message}` : 'OK');
// Wichtig · Fallstricke
- Genau einmal aufrufen: Ein zweiter Aufruf von
end()auf demselben Encoder erzeugt einen Validierungsfehler. Ein beendeterGPURenderPassEncoderlässt sich nicht wiederverwenden. Für jeden Pass brauchen Sie einen neuenbeginRenderPass()-Aufruf. - Kein Exception-Wurf: WebGPU meldet Fehler asynchron als Validierungsfehler, die Sie mit
device.pushErrorScope()/popErrorScope()oder über das Ereignisuncapturederrorabfangen. Sie werden nicht als JavaScript-Exception geworfen. - Offene Debug-Gruppen: Jede mit
pushDebugGroup()geöffnete Gruppe muss vorend()mitpopDebugGroup()geschlossen werden, sonst ist der Pass ungültig. Dasselbe gilt für eine offene Occlusion-Query (beginOcclusionQuery()ohneendOcclusionQuery()). - Umbenennung: Frühe Entwürfe der Spezifikation nannten die Methode
endPass(). Ältere Tutorials verwenden noch diesen Namen, heute gilt nurend(). - Kompatibilität: WebGPU steht nur in sicheren Kontexten (HTTPS) zur Verfügung und wird noch nicht von allen Browsern unterstützt. Prüfen Sie vorab mit
if (!navigator.gpu) { … }und sehen Sie einen Ersatzweg vor, z. B. WebGL.