Signatur
Beschreibung
Die Methode deleteSync() des WebGL2RenderingContext markiert ein WebGLSync-Objekt zum Löschen. Solche Sync-Objekte (auch „Fences“ genannt) entstehen durch gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0). Mit ihnen lässt sich feststellen, ob die GPU alle bis dahin abgesetzten Befehle abgearbeitet hat.
Typische Anwendungsfälle sind das asynchrone Zurücklesen von Pixeldaten über Pixel Buffer Objects (PBO), das Streamen von Texturen und das Vermeiden von Pipeline-Stalls. Sobald ein Fence signalisiert wurde oder nicht mehr gebraucht wird, sollte man ihn mit deleteSync() löschen. Sonst sammeln sich mit jedem Frame weitere Sync-Objekte an.
Wenn noch jemand auf das Sync-Objekt wartet, etwa über clientWaitSync() oder waitSync(), wird es erst gelöscht, wenn kein Wartevorgang mehr daran hängt. Wird null übergeben, passiert nichts.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $sync Pflicht | WebGLSync | null | Das zu löschende Sync-Objekt, das zuvor mit gl.fenceSync() erzeugt wurde. Bei null wird der Aufruf still ignoriert. |
Rückgabewert
undefined).Beispiele
Fence erzeugen, prüfen und löschen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// Fence nach den Zeichenbefehlen setzen
const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
gl.flush();
console.log(gl.isSync(sync)); // true
gl.deleteSync(sync);
console.log(gl.isSync(sync)); // false
Asynchrones Zurücklesen per PBO mit Fence-Polling
const readPixelsAsync = (gl, x, y, w, h) => {
const buf = gl.createBuffer();
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, buf);
gl.bufferData(gl.PIXEL_PACK_BUFFER, w * h * 4, gl.STREAM_READ);
gl.readPixels(x, y, w, h, gl.RGBA, gl.UNSIGNED_BYTE, 0);
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
gl.flush();
return new Promise((resolve, reject) => {
const poll = () => {
const status = gl.clientWaitSync(sync, 0, 0);
if (status === gl.WAIT_FAILED) {
gl.deleteSync(sync);
gl.deleteBuffer(buf);
reject(new Error('clientWaitSync fehlgeschlagen'));
} else if (status === gl.TIMEOUT_EXPIRED) {
requestAnimationFrame(poll);
} else {
// Fence ist signalisiert, wird also nicht mehr gebraucht
gl.deleteSync(sync);
const data = new Uint8Array(w * h * 4);
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, buf);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, data);
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);
gl.deleteBuffer(buf);
resolve(data);
}
};
poll();
});
};
const gl = document.createElement('canvas').getContext('webgl2');
gl.clearColor(1, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
const pixels = await readPixelsAsync(gl, 0, 0, 1, 1);
console.log(pixels);
Aufräumen im Render-Loop, damit sich keine Fences ansammeln
const gl = document.createElement('canvas').getContext('webgl2');
let pendingSync = null;
const frame = () => {
// Fence aus dem vorherigen Frame prüfen
if (pendingSync) {
const signaled = gl.getSyncParameter(pendingSync, gl.SYNC_STATUS) === gl.SIGNALED;
if (signaled) {
gl.deleteSync(pendingSync);
pendingSync = null;
}
}
gl.clear(gl.COLOR_BUFFER_BIT);
if (!pendingSync) {
pendingSync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
}
requestAnimationFrame(frame);
};
requestAnimationFrame(frame);
// Wichtig · Fallstricke
- Nur in WebGL 2: Die Methode gibt es im
WebGL2RenderingContext, nicht imWebGLRenderingContext(WebGL 1). Prüfe also, obcanvas.getContext('webgl2')tatsächlich einen Kontext liefert. Alle modernen Browser unterstützen WebGL 2, Safari erst ab Version 15. - Speicherlecks: Wenn du pro Frame einen Fence mit
fenceSync()anlegst und ihn nie löschst, sammeln sich Treiber-Ressourcen an. RufedeleteSync()auf jedem Codepfad auf, auch bei Fehlern und Timeouts. - Nach dem Löschen: Ein gelöschtes Sync-Objekt darf nicht mehr an
clientWaitSync(),waitSync()odergetSyncParameter()übergeben werden. Das erzeugtINVALID_VALUEbzw.INVALID_OPERATION.isSync()liefert danachfalse. Setze deine Referenz am besten gleich aufnull. - Kontextverlust: Nach einem
webglcontextlost-Event sind alle Sync-Objekte ungültig.deleteSync()ist dann wirkungslos. - Browser signalisieren einen Fence frühestens, nachdem die Kontrolle an die Ereignisschleife zurückgegeben wurde. Synchrones Warten in einer Schleife bringt daher nichts. Frage den Status stattdessen über
requestAnimationFrameodersetTimeoutab.