How to know when rendering is complete in WebGL? 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)?
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, &amp;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);