Start · Sprachen · JavaScript · Referenz · GPURenderPassEncoder.end()

GPURenderPassEncoder.end()

Methode

Beendet die Aufzeichnung der Befehle eines Renderpasses. Danach kann der zugehörige <code>GPUCommandEncoder</code> wieder verwendet oder abgeschlossen werden.

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

Signatur

GPURenderPassEncoder.prototype.end()

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

Typ
undefined
Beschreibung
Kein 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');
Validierungsfehler: ... (Meldung je nach Browser verschieden)

// Wichtig · Fallstricke

  • Genau einmal aufrufen: Ein zweiter Aufruf von end() auf demselben Encoder erzeugt einen Validierungsfehler. Ein beendeter GPURenderPassEncoder lässt sich nicht wiederverwenden. Für jeden Pass brauchen Sie einen neuen beginRenderPass()-Aufruf.
  • Kein Exception-Wurf: WebGPU meldet Fehler asynchron als Validierungsfehler, die Sie mit device.pushErrorScope()/popErrorScope() oder über das Ereignis uncapturederror abfangen. Sie werden nicht als JavaScript-Exception geworfen.
  • Offene Debug-Gruppen: Jede mit pushDebugGroup() geöffnete Gruppe muss vor end() mit popDebugGroup() geschlossen werden, sonst ist der Pass ungültig. Dasselbe gilt für eine offene Occlusion-Query (beginOcclusionQuery() ohne endOcclusionQuery()).
  • Umbenennung: Frühe Entwürfe der Spezifikation nannten die Methode endPass(). Ältere Tutorials verwenden noch diesen Namen, heute gilt nur end().
  • 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.