<p>You can utilize <a href="https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_sync.txt" rel="nofollow noreferrer">ARB_sync</a> or in other words <a href="https://www.khronos.org/opengl/wiki/Sync_Object" rel="nofollow noreferrer">sync objects</a> which have been core since 3.2.</p>

<p>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.</p>

<p><em>Say you want to check if a <code>glDrawArrays()</code> call has been executed.</em></p>

<pre><code>glDrawArrays(...);
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
</code></pre>

<p><em>Note that if <code>glFenceSync()</code> fails it will return <code>0</code>.</em></p>

<p>You can now check whether it has finished by doing:</p>

<pre><code>GLint signaled = 0;
glGetSynciv(sync, GL_SYNC_STATUS, 1, NULL, &amp;signaled);

if (signaled == GL_SIGNALED)
    // Done
else
    // Not done
</code></pre>

<p>You can then of course repeatably call <code>glGetSynciv()</code> and check when you receive <code>GL_SIGNALED</code>.</p>

<p>If you want to completely block until it's done then you can do:</p>

<pre><code>GLenum status = glClientWaitSync(sync, 0, 0);

if (status == GL_CONDITION_SATISFIED)
    // Done
</code></pre>

<p>It blocks and waits for up to <code>timeout</code> nanoseconds (the last parameter).</p>

<p>Remember to delete the <a href="https://www.khronos.org/opengl/wiki/Sync_Object" rel="nofollow noreferrer">sync object</a> again:</p>

<pre><code>glDeleteSync(sync);
</code></pre>

<p>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 <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGLSync" rel="nofollow noreferrer">WebGLSync</a>.</p>

<p><em>The equivalent to the above code in WebGL 2.0 would be the following:</em></p>

<pre><code>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);
</code></pre>

CC BY-SA 3.0
2017-04-07T11:59:24.640Z
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
metalim
CC BY-SA 3.0
2017-04-07T21:54:48.370Z
Did you verify that you're using WebGL 2.0?
vallentin
CC BY-SA 3.0
2017-04-08T00:10:38.807Z
Of course, context is WebGL2RenderingContext, and I use other WebGL2.0-only features.
metalim
CC BY-SA 3.0
2017-04-08T00:13:30.870Z
Check whether `sync` is `0` or `null`. Also [check whether your browser supports it](https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/fenceSync#Browser_compatibility).
vallentin
CC BY-SA 3.0
2017-04-08T10:25:07.883Z
`sync` works fine, I can get it's status with `getSyncParameter`. It is only the `clientWaitSync` that has issues. Chrome 57 in macOS 10.12.4 on MacBook mid-2012.
metalim
CC BY-SA 3.0
2017-04-08T16:46:35.120Z
Try and check `gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL` maybe `gl.clientWaitSync()` just isn't allowed in Chrome on MacOS.
vallentin
CC BY-SA 3.0
2017-11-13T16:59:00.170Z
@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.
WuTangTan
CC BY-SA 3.0
2017-04-06T18:09:07.647Z
2017-04-06T23:45:22.017Z
2017-04-06T23:45:22.017Z
vallentin
<p>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.</p>

<p>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)?</p>

<rendering><webgl>
How to know when rendering is complete in WebGL?
metalim
# How to know when rendering is complete in WebGL?

(Asked by: username_0 on 2017-04-06)

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)?

**Tags:** rendering, webgl


---

## 1 answers

### Answer by username_1 on 2017-04-06. Score: 3 | Accepted answer

You can utilize [ARB\_sync](https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_sync.txt) or in other words [sync objects](https://www.khronos.org/opengl/wiki/Sync_Object) 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](https://www.khronos.org/opengl/wiki/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](https://developer.mozilla.org/en-US/docs/Web/API/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);

```

> **Comments:**
> **username_0**: 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  
> **username_1**: Did you verify that you're using WebGL 2.0?  
> **username_0**: Of course, context is WebGL2RenderingContext, and I use other WebGL2.0-only features.  
> **username_1**: Check whether `sync` is `0` or `null`. Also [check whether your browser supports it](https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/fenceSync#Browser_compatibility).  
> **username_0**: `sync` works fine, I can get it's status with `getSyncParameter`. It is only the `clientWaitSync` that has issues. Chrome 57 in macOS 10.12.4 on MacBook mid-2012.  
> **username_1**: Try and check `gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL` maybe `gl.clientWaitSync()` just isn't allowed in Chrome on MacOS.  
> **username_2**: @username_0 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.  

---

