Start · Sprachen · JavaScript · Referenz · WebGL2RenderingContext.getSyncParameter()

WebGL2RenderingContext.getSyncParameter()

Methode

Liefert Informationen zu einem <code>WebGLSync</code>-Objekt, z. B. ob der zugehörige Fence auf der GPU schon signalisiert wurde.

seit JavaScript WebGL 2.0 – Baseline: alle modernen Browser (seit Kategorie: webapi

Signatur

WebGL2RenderingContext.prototype.getSyncParameter(sync, pname)

Beschreibung

Die Methode getSyncParameter() fragt Zustandsinformationen eines WebGLSync-Objekts ab. Solche Sync-Objekte entstehen mit gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0) und markieren eine Stelle im GPU-Befehlsstrom. Sobald die GPU alle Befehle bis zu diesem Punkt abgearbeitet hat, wird der Fence signalisiert.

Der wichtigste Anwendungsfall ist das nicht blockierende Abfragen (Polling), ob die GPU fertig ist – etwa bevor man mit gl.getBufferSubData() Daten aus einem Pixel-Buffer-Objekt (PBO) zurückliest. Statt die Hauptschleife mit gl.finish() oder clientWaitSync() mit großem Timeout anzuhalten, prüft man in jedem Frame per getSyncParameter(sync, gl.SYNC_STATUS), ob der Status gl.SIGNALED ist.

Über pname lassen sich vier Eigenschaften abfragen:

  • gl.OBJECT_TYPE – immer gl.SYNC_FENCE
  • gl.SYNC_STATUS – gl.SIGNALED oder gl.UNSIGNALED
  • gl.SYNC_CONDITION – immer gl.SYNC_GPU_COMMANDS_COMPLETE
  • gl.SYNC_FLAGS – immer 0

Parameter

Name Typ Default Beschreibung
$sync Pflicht WebGLSync Das abzufragende Sync-Objekt, erzeugt mit gl.fenceSync().
$pname Pflicht GLenum Die abzufragende Eigenschaft: gl.OBJECT_TYPE, gl.SYNC_STATUS, gl.SYNC_CONDITION oder gl.SYNC_FLAGS.

Rückgabewert

Typ
GLenum | GLbitfield | null
Beschreibung
Je nach pname: gl.SYNC_FENCE, gl.SIGNALED/gl.UNSIGNALED, gl.SYNC_GPU_COMMANDS_COMPLETE oder 0. Bei Fehlern (z. B. ungültiges pname, verlorener Kontext) null.

Beispiele

Status eines Fence abfragen

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

gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
gl.flush(); // Befehle an die GPU übergeben

const status = gl.getSyncParameter(sync, gl.SYNC_STATUS);
console.log(status === gl.SIGNALED ? 'fertig' : 'noch in Arbeit');

console.log(gl.getSyncParameter(sync, gl.OBJECT_TYPE) === gl.SYNC_FENCE);
console.log(gl.getSyncParameter(sync, gl.SYNC_FLAGS));

gl.deleteSync(sync);
noch in Arbeit true 0

Nicht blockierendes Warten mit Promise

const waitForGpu = (gl, sync) => new Promise((resolve) => {
  const check = () => {
    if (gl.getSyncParameter(sync, gl.SYNC_STATUS) === gl.SIGNALED) {
      gl.deleteSync(sync);
      resolve();
    } else {
      requestAnimationFrame(check);
    }
  };
  check();
});

const gl = document.createElement('canvas').getContext('webgl2');
// ... aufwendiges Rendering ...
const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
gl.flush();

await waitForGpu(gl, sync);
console.log('GPU hat alle Befehle abgearbeitet');
GPU hat alle Befehle abgearbeitet

Asynchrones Pixel-Readback über ein PBO

const gl = document.createElement('canvas').getContext('webgl2');
const width = gl.drawingBufferWidth;
const height = gl.drawingBufferHeight;

const pbo = gl.createBuffer();
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo);
gl.bufferData(gl.PIXEL_PACK_BUFFER, width * height * 4, gl.STREAM_READ);

// readPixels schreibt in das PBO, blockiert also nicht
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, 0);
const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
gl.flush();

const poll = () => {
  if (gl.getSyncParameter(sync, gl.SYNC_STATUS) !== gl.SIGNALED) {
    setTimeout(poll, 4);
    return;
  }
  gl.deleteSync(sync);
  const pixels = new Uint8Array(width * height * 4);
  gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo);
  gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, pixels);
  gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
  console.log('Erstes Pixel:', pixels.slice(0, 4));
};
poll();
Erstes Pixel: Uint8Array(4) [0, 0, 0, 0]

// Wichtig · Fallstricke

  • Status ändert sich nicht innerhalb desselben Tasks: Laut WebGL-2-Spezifikation darf der Browser den Wert von SYNC_STATUS erst aktualisieren, nachdem die Kontrolle an die Ereignisschleife zurückgegeben wurde. Eine enge while-Schleife, die ständig abfragt, läuft deshalb endlos – immer über requestAnimationFrame oder setTimeout abfragen.
  • gl.flush() nicht vergessen: Ohne Flush werden die Befehle eventuell nie an die GPU übergeben, und der Fence wird nie signalisiert.
  • Sync-Objekte mit gl.deleteSync() freigeben, sonst sammeln sich Ressourcen an.
  • Ein ungültiges pname erzeugt gl.INVALID_ENUM (prüfbar mit gl.getError()), und die Methode gibt null zurück. Bei verlorenem Kontext ebenfalls null.
  • Nur im webgl2-Kontext verfügbar, nicht in WebGL 1. Wird von allen aktuellen Browsern unterstützt (Safari ab 15).