You can utilize ARB_sync or in other words sync objects which have been core since 3.2.
From the point-of-view of OpenGL then right after issuing a specific command (you want to know whether has finished), you'd insert a fence.
Say you want to check if a glDrawArrays()
call has been executed.
glDrawArrays(...);
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
Note that if glFenceSync()
fails it will return 0
.
You can now check whether it has finished by doing:
GLint signaled = 0;
glGetSynciv(sync, GL_SYNC_STATUS, 1, NULL, &signaled);
if (signaled == GL_SIGNALED)
// Done
else
// Not done
You can then of course repeatably call glGetSynciv()
and check when you receive GL_SIGNALED
.
If you want to completely block until it's done then you can do:
GLenum status = glClientWaitSync(sync, 0, 0);
if (status == GL_CONDITION_SATISFIED)
// Done
It blocks and waits for up to timeout
nanoseconds (the last parameter).
Remember to delete the sync object again:
glDeleteSync(sync);
When it comes to WebGL. Then note that sync objects are not supported in WebGL 1.0. They are however in WebGL 2.0 in the form of WebGLSync.
The equivalent to the above code in WebGL 2.0 would be the following:
var sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
var signaled = gl.getSyncParameter(sync, gl.SYNC_STATUS);
if (signaled == gl.SIGNALED)
// Done
else
// Not done
var status = gl.clientWaitSync(sync, 0, 0);
if (status == gl.CONDITION_SATISFIED)
// Done
gl.deleteSync(sync);