Start · Sprachen · JavaScript · Referenz · WebGLRenderingContext.flush()

WebGLRenderingContext.flush()

Methode

Leert die internen Befehls-Puffer des WebGL-Kontexts und sorgt dafür, dass alle bisher abgesetzten GL-Befehle möglichst schnell an die GPU übergeben werden.

seit JavaScript WebGL 1.0 – Baseline: alle Browser Kategorie: webapi

Signatur

WebGLRenderingContext.prototype.flush()

Beschreibung

WebGL-Aufrufe wie drawArrays() oder clear() werden nicht sofort auf der GPU ausgeführt. Der Browser sammelt sie in Befehls-Puffern und schickt sie in Blöcken an den Grafiktreiber weiter. flush() veranlasst, dass alle bisher gesammelten Befehle ohne weitere Verzögerung übergeben werden. Die Methode wartet aber nicht, bis die GPU fertig ist. Sie kehrt sofort zurück.

Normalerweise brauchen Sie flush() nicht. Wenn ein Frame endet und der Browser das Canvas darstellt, wird ohnehin geleert. Sinnvoll ist ein expliziter Aufruf in Sonderfällen:

  • Sie haben viele Befehle abgesetzt und warten danach länger, etwa auf ein setTimeout oder ein Netzwerk-Ergebnis, ohne dass der Frame endet.
  • Sie nutzen in WebGL 2 Sync-Objekte (fenceSync()) oder asynchrone Abfragen. Diese können nur signalisiert werden, wenn die Befehle wirklich an die GPU gegangen sind.
  • Sie arbeiten in einem Worker mit OffscreenCanvas ohne regelmäßige Frame-Grenzen.

Im Gegensatz dazu blockiert finish(), bis alle Befehle vollständig ausgeführt sind. Das kostet viel Leistung. flush() ist die günstige, nicht blockierende Variante.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Einfacher Aufruf nach dem Zeichnen

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');

gl.clearColor(0.1, 0.2, 0.3, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

// Befehle sofort an die GPU übergeben, ohne zu warten
gl.flush();
console.log('Befehle übergeben');
Befehle übergeben

WebGL 2: Fence-Sync nicht blockierend abfragen

const gl = document.querySelector('canvas').getContext('webgl2');

// ... aufwendiges Rendering in einen Framebuffer ...
gl.clear(gl.COLOR_BUFFER_BIT);

const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
// Ohne flush() wird der Fence womöglich nie signalisiert
gl.flush();

const waitForGpu = () => new Promise((resolve) => {
  const check = () => {
    const status = gl.clientWaitSync(sync, 0, 0);
    if (status === gl.ALREADY_SIGNALED || status === gl.CONDITION_SATISFIED) {
      gl.deleteSync(sync);
      resolve();
    } else {
      setTimeout(check, 1);
    }
  };
  check();
});

await waitForGpu();
console.log('GPU ist fertig – jetzt readPixels ohne Stall möglich');
GPU ist fertig – jetzt readPixels ohne Stall möglich

Rendering in einem Worker mit OffscreenCanvas

// worker.js
self.onmessage = ({ data }) => {
  const gl = data.canvas.getContext('webgl');
  gl.clearColor(1, 0, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);
  // Arbeit anstoßen, bevor der Worker auf die nächste Nachricht wartet
  gl.flush();
  self.postMessage('gerendert');
};

// Wichtig · Fallstricke

  • Keine Synchronisation: flush() garantiert nicht, dass die Befehle beim Rückkehren schon ausgeführt sind. Um auf das Ende zu warten, nutzen Sie finish() (blockiert) oder besser in WebGL 2 fenceSync() zusammen mit clientWaitSync().
  • Leistung: Wenn Sie flush() in jedem Draw-Call oder mehrmals pro Frame aufrufen, erzeugt das unnötigen Aufwand im Treiber und kann die Bildrate senken. Im normalen requestAnimationFrame-Ablauf ist die Methode überflüssig.
  • Verlorener Kontext: Ist der Kontext verloren (webglcontextlost), bewirkt der Aufruf nichts.
  • Kompatibilität: Die Methode wird von allen modernen Browsern unterstützt und steht auch auf WebGL2RenderingContext zur Verfügung.