6
$\begingroup$

gl.drawArrays()/gl.drawElements() initiates a drawing and returns immediately. There is also (non-recommended) gl.finish() that (theoretically) blocks execution until rendering is complete.

Is there a way to receive event when rendering is complete, or other ways to track status of rendering, without blocking execution of the main thread? If there are, how well they work with Offscreen rendering (to a buffer)?

$\endgroup$

1 Answer 1

3
$\begingroup$

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);
$\endgroup$
7
  • $\begingroup$ For some reason glClientWaitSync always fails for me, if timeout is non-0. Even if it's 1, then there's console warning: WebGL: INVALID_OPERATION: clientWaitSync: timeout > MAX_CLIENT_WAIT_TIMEOUT_WEBGL $\endgroup$
    – metalim
    Apr 7, 2017 at 11:59
  • $\begingroup$ Did you verify that you're using WebGL 2.0? $\endgroup$
    – vallentin
    Apr 7, 2017 at 21:54
  • $\begingroup$ Of course, context is WebGL2RenderingContext, and I use other WebGL2.0-only features. $\endgroup$
    – metalim
    Apr 8, 2017 at 0:10
  • $\begingroup$ Check whether sync is 0 or null. Also check whether your browser supports it. $\endgroup$
    – vallentin
    Apr 8, 2017 at 0:13
  • 1
    $\begingroup$ @metalim it seems that, for many implementations as of this writing, the maximum time that the client is allowed to wait is 0. You may check the value with gl.getParameter(gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL). That MAX_CLIENT_WAIT_TIMEOUT_WEBGL is an enum and not a value is not well presented in the documentation which was (for me at least) a source of confusion. $\endgroup$
    – WuTangTan
    Nov 13, 2017 at 16:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.