I'm trying to play around with WebGLSyncs and I'm having a hard time getting a WebGLSync to be signaled.
The following is unsignaled on all browsers supporting WebGL2 (Chrome, Opera, Firefox):
function test() {
let canvas = document.createElement('canvas');
let gl = canvas.getContext('webgl2');
let sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
gl.flush();
gl.finish();
let status = gl.getSyncParameter(sync, gl.SYNC_STATUS);
console.log(sync, status, status === gl.UNSIGNALED); // logs "true"
gl.deleteSync(sync);
}
I'm expecting this to work, since gl.finish() should wait until all GPU commands have been processed - but it looks like the sync fence was not.
I would very much appreciate a minimal, working WebGLSync
example that actually gets signaled. I searched GitHub for such but I found nothing.
EDIT
Based on the answer from pleup, I put together this code sample which works fine in my environment (Windows + Chrome).
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function test() {
let canvas = document.createElement('canvas');
let gl = canvas.getContext('webgl2');
let sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
gl.flush();
while (gl.getSyncParameter(sync, gl.SYNC_STATUS) === gl.UNSIGNALED) {
await sleep(100);
}
let status = gl.getSyncParameter(sync, gl.SYNC_STATUS);
console.log(sync, status, status === gl.SIGNALED);
gl.deleteSync(sync);
}
test()
You have to wait for a tick to see the sync signaled. The sync status will never change during JS execution frame.
https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.14
In order to ensure consistent behavior across platforms, sync objects may only transition to the signaled state when the user agent's event loop is not executing a task. In other words:
A sync object must not become signaled until control has returned to the user agent's main loop. Repeatedly fetching a sync object's SYNC_STATUS parameter in a loop, without returning control to the user agent, must always return the same value.