openglvboopenglcontext

Is calling glFinish necessary when synchronizing resources between OpenGL contexts?


I am using two OpenGL contexts in my application.

The first one is used to render data, the second one to background load and generate VBOs and textures.

When my loading context generates a VBO and sends it to my rendering thread, I get invalid data (all zeroes) in my VBO unless I call glFlush or glFinish after creating the VBO on the loading context.

I think that this is due to my loading context not having any buffer swap or anything to tell the GPU to start working on its command queue and doing nothing (which leads to an empty VBO on the rendering context side).

From what I've seen, this flush is not necessary on Windows (tested with an Nvidia GPU, it works even without the flushes) but is necessary on linux/macOS.

This page on Apple's documentation says that calling glFlush is necessary (https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/OpenGLESApplicationDesign/OpenGLESApplicationDesign.html)

If your app shares OpenGL ES objects (such as vertex buffers or textures) between multiple contexts, you should call the glFlush function to synchronize access to these resources. For example, you should call the glFlush function after loading vertex data in one context to ensure that its contents are ready to be retrieved by another context.

But is calling glFinish or glFlush necessary or is there simpler/lighter commands available to achieve the same result ? (and which is necessary, glFlush or glFinish ?)

Also, is there a documentation or reference somewhere that talks about this ? I couldn't find any mentions and it seems to work differently between implementations.


Solution

  • If you manipulate the contents of any object in thread A, those contents are not visible to some other thread B until two things have happened:

    1. The commands modifying the object have completed. glFlush does not complete commands; you must use glFinish or a sync object to ensure command completion.

      Note that the completion needs to be communicated to thread B, but the synchronization command has to be issued on thread A. So if thread A uses glFinish, it now must use some CPU synchronization to communicate that the thread is finished to thread B. If you use fence sync objects instead, you need to create the fence on thread A, then hand it over to thread B who can test/wait on that fence.

    2. The object must be re-bound to the context of thread B. That is, you have to bind it to that context after the commands have completed (either directly with a glBind* command or indirectly by binding a container object that has this object attached to it).

    This is detailed in Chapter 5 of the OpenGL specification.