84 5.DelayingOpenGLCalls
quire a current OpenGL context. For games with multiple contexts, this can min-
imize bugs caused by incorrect management of the current context. Likewise, if
you are developing an engine that needs to play nice with other libraries using
their own OpenGL context,
Uniform::SetValue() has no context side effects
and can be called anytime, not just when your context is current.
Our technique can also be extended to minimize managed to native code
round-trip overhead when using OpenGL with languages like Java or C#. Instead
of making fine-grained
glUniform1f() calls for each dirty uniform, the list of
dirty uniforms can be passed to native C++ code in a single coarse-grained call.
On the C++ side,
glUniform1f() is called for each uniform, thus eliminating the
per-uniform round trip. This can be taken a step further by making all the re-
quired OpenGL calls for a draw in a single round trip.
5.7ConcludingRemarks
An alternative to our technique is to use direct state access (DSA) [Kilgard
2009], an OpenGL extension that allows updating OpenGL state without previ-
ously setting global state. For example, the following two lines,
glUseProgram(m_handle);
glUniform1f(m_location, value);
can be combined into one:
glProgramUniform1fEXT(m_handle, m_location, m_currentValue);
As of this writing, DSA is not a core feature of OpenGL 3.3, and as such, is not
available on all platforms, although
glProgramUniform*() calls are mirrored in
the separate shader objects extension [Kilgard et al. 2010] which has become
core functionality in OpenGL 4.1.
Delaying selector-based OpenGL calls until draw time has a lot of benefits,
although there are some OpenGL calls that you do not want to delay. It is im-
portant to allow the CPU and GPU to work together in parallel. As such, you
would not want to delay updating a large vertex buffer or texture until draw time
because this could cause the GPU to wait, assuming it is not rendering one or
more frames behind the CPU.
Finally, I’ve had great success using this technique in both commercial and
open source software. I’ve found it quick to implement and easy to debug. An
excellent next step for you is to generalize the code in this chapter to support all