GPUs gain quite a bit of their performance because, by and large, once you tell them what to do, they go do their stuff without further intervention. As the programmer, you do not care that a frame has not yet completed. All you are interested in is that the user sees the frame when it is ready.

There are certain things that the user can do which will cause this perfect asynchronous activity to come to a screeching halt. These are called synchronization events.

OpenGL is defined to allow asynchronous behavior; commands that you give do not have to be completed when the function ends (for the most part). However, OpenGL defines this by saying that if there is asynchronous behavior, the user cannot be made aware of it. That is, if you call glDrawArrays, the effect of this command should be based solely on the current state of OpenGL. This means that, if the glDrawArrays command is executed later, the OpenGL implementation must do whatever it takes to prevent later changes from impacting the results.

Therefore, if you make a glDrawArrays call that pulls from some buffer object, and then immediately call glBufferSubData on that buffer object, the OpenGL implementation may have to pause the CPU in the glBufferSubData call until the glDrawArrays has at least finished vertex processing. However, the implementation may also simply copy the data you are trying to transfer into some memory it allocates, to be uploaded to the buffer once the glDrawArrays completes. There is no way to be sure which will happen.

Synchronization events usually include changing data objects. That is, changing the contents of buffer objects or textures. Usually, changing simple state of objects, like what attributes a VAO provides or texture parameters, does not cause synchronization issues. Changing global OpenGL state also does not cause synchronization problems.

There are ways to allow you to modify data objects that still let the GPU be asynchronous. But any discussion of these is well beyond the bounds of this book. Just be aware that data objects that are in active use should probably not have their data modified.

Fork me on GitHub