|
|
|
|
@ -422,6 +422,74 @@ See also @ref Attribute::DataType enum for additional type options.
|
|
|
|
|
@ref Magnum::Matrix4x2 "Matrix4x2", @ref Magnum::Matrix3x4 "Matrix3x4" and |
|
|
|
|
@ref Magnum::Matrix4x3 "Matrix4x3") are not available in WebGL 1.0. |
|
|
|
|
|
|
|
|
|
@section GL-AbstractShaderProgram-async Asynchronous shader compilation and linking |
|
|
|
|
|
|
|
|
|
The workflow described @ref GL-AbstractShaderProgram-subclassing "at the very top" |
|
|
|
|
compiles and links the shader directly in a constructor. While that's fine for |
|
|
|
|
many use cases, with heavier shaders, many shader combinations or on |
|
|
|
|
platforms that translate GLSL to other APIs such as HLSL or MSL, the |
|
|
|
|
compilation and linking can take a significant portion of application startup |
|
|
|
|
time. |
|
|
|
|
|
|
|
|
|
To mitigate this problem, nowadays drivers implement *asynchronous compilation* |
|
|
|
|
--- when shader compilation or linking is requested, the driver offloads the |
|
|
|
|
work to separate worker threads, and serializes it back to the application |
|
|
|
|
thread only once the application wants to retrieve the result of the operation. |
|
|
|
|
Which means, the ideal way to spread the operation over more CPU cores is to |
|
|
|
|
first submit compilation & linking of several shaders at once and only then ask |
|
|
|
|
for operation result. That allows the driver to perform compilation/linking of |
|
|
|
|
multiple shaders at once. Furthermore, the |
|
|
|
|
@gl_extension{KHR,parallel_shader_compile} extension adds a possibility to |
|
|
|
|
query whether the operation was finished for a particular shader. That allows |
|
|
|
|
the application to schedule other work in the meantime. |
|
|
|
|
|
|
|
|
|
Async compilation and linking can be implemented by using |
|
|
|
|
@ref Shader::submitCompile() and @ref submitLink(), followed by |
|
|
|
|
@ref checkLink() (and optionally @ref Shader::checkCompile()), instead of |
|
|
|
|
@ref Shader::compile() and @ref link(). Calling the submit functions will |
|
|
|
|
trigger a (potentially async) compilation and linking, calling the check |
|
|
|
|
functions will check the operation result, potentially stalling if the async |
|
|
|
|
operation isn't finished yet. |
|
|
|
|
|
|
|
|
|
The @ref Shader::isCompileFinished() and |
|
|
|
|
@ref isLinkFinished() APIs then provide a way to query if the submitted |
|
|
|
|
operation finished. If @gl_extension{KHR,parallel_shader_compile} is not |
|
|
|
|
available, those two implicitly return @cpp true @ce, thus effectively causing |
|
|
|
|
a stall if the operation isn't yet done at the time you call |
|
|
|
|
@ref Shader::checkCompile() / @ref checkLink() --- but compared to the linear |
|
|
|
|
workflow you still get the benefits from submitting multiple operations at |
|
|
|
|
once. |
|
|
|
|
|
|
|
|
|
A common way to equip an @ref AbstractShaderProgram subclass with async |
|
|
|
|
creation capability while keeping also the simple constructor is the following: |
|
|
|
|
|
|
|
|
|
1. An internal @ref NoInit constructor for the subclass is added, which only |
|
|
|
|
creates the @ref AbstractShaderProgram base but does nothing else. |
|
|
|
|
2. A @cpp CompileState @ce inner class is defined as a subclass of |
|
|
|
|
@cpp MyShader @ce. Besides that it holds all temporary state needed to |
|
|
|
|
finish the construction --- in particular all @ref Shader instances. |
|
|
|
|
3. A @cpp static CompileState compile(…) @ce function does everything until |
|
|
|
|
and including linking as the original constructor did, except that it calls |
|
|
|
|
@ref Shader::submitCompile() and @ref submitLink() instead of |
|
|
|
|
@ref Shader::compile() and @ref link(), and returns a populated |
|
|
|
|
@cpp CompileState @ce instance. |
|
|
|
|
4. A @cpp MyShader(CompileState&&) @ce constructor then takes over the base |
|
|
|
|
of @cpp CompileState @ce by delegating it into the move constructor. Then |
|
|
|
|
it calls @ref checkLink() (and if that fails also @ref Shader::checkCompile() |
|
|
|
|
to provide more context) and then performs any remaining post-link steps |
|
|
|
|
such as uniform setup. |
|
|
|
|
5. The original @cpp MyShader(…) @ce constructor now only passes the result of |
|
|
|
|
@cpp compile() @ce to @cpp MyShader(CompileState&&) @ce. |
|
|
|
|
|
|
|
|
|
@snippet MagnumGL.cpp AbstractShaderProgram-async |
|
|
|
|
|
|
|
|
|
Usage-wise, it can look for example like below, with the last line waiting for |
|
|
|
|
linking to finish and making the shader ready to use. On drivers that don't |
|
|
|
|
perform any async compilation this will behave the same as if the construction |
|
|
|
|
was done the usual way. |
|
|
|
|
|
|
|
|
|
@snippet MagnumGL.cpp AbstractShaderProgram-async-usage |
|
|
|
|
|
|
|
|
|
@section GL-AbstractShaderProgram-performance-optimization Performance optimizations |
|
|
|
|
|
|
|
|
|
The engine tracks currently used shader program to avoid unnecessary calls to |
|
|
|
|
@ -1259,13 +1327,18 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject {
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Non-blocking linking status check |
|
|
|
|
* @return @cpp true @ce if linking finished, @cpp false @ce otherwise |
|
|
|
|
* |
|
|
|
|
* On some drivers this might return false even after |
|
|
|
|
* @ref checkLink() reported successful linking. |
|
|
|
|
* @brief Whether a @ref submitLink() operation has finished |
|
|
|
|
* @m_since_latest |
|
|
|
|
* |
|
|
|
|
* @see @fn_gl_keyword{GetProgram} with |
|
|
|
|
* Has to be called only if @ref submitLink() was called before, and |
|
|
|
|
* before @ref checkLink(). If returns @cpp false @ce, a subsequent |
|
|
|
|
* @ref checkLink() call will block until the linking is finished. If |
|
|
|
|
* @gl_extension{KHR,parallel_shader_compile} is not available, the |
|
|
|
|
* function always returns @cpp true @ce --- i.e., as if the linking |
|
|
|
|
* was done synchronously. See @ref GL-AbstractShaderProgram-async for |
|
|
|
|
* more information. |
|
|
|
|
* @see @ref Shader::isCompileFinished(), |
|
|
|
|
* @fn_gl_keyword{GetProgram} with |
|
|
|
|
* @def_gl_extension{COMPLETION_STATUS,KHR,parallel_shader_compile} |
|
|
|
|
*/ |
|
|
|
|
bool isLinkFinished(); |
|
|
|
|
@ -1453,32 +1526,36 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject {
|
|
|
|
|
/**
|
|
|
|
|
* @brief Link the shader |
|
|
|
|
* |
|
|
|
|
* Calls @ref submitLink(), then @ref checkLink(). |
|
|
|
|
* If possible, prefer to link multiple shaders at once using |
|
|
|
|
* @ref link(std::initializer_list<Containers::Reference<AbstractShaderProgram>>) |
|
|
|
|
* for improved performance, see its documentation for more |
|
|
|
|
* information. |
|
|
|
|
* Calls @ref submitLink(), immediately followed by @ref checkLink(), |
|
|
|
|
* passing back its return value. See documentation of those two |
|
|
|
|
* functions for details. |
|
|
|
|
* @see @ref Shader::compile() |
|
|
|
|
*/ |
|
|
|
|
bool link(); |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Submit for linking |
|
|
|
|
* |
|
|
|
|
* The attached shaders must be compiled with @ref Shader::compile() |
|
|
|
|
* or @ref Shader::submitCompile() before linking. |
|
|
|
|
* @brief Submit the shader for linking |
|
|
|
|
* @m_since_latest |
|
|
|
|
* |
|
|
|
|
* The attached shaders must be at least submitted for compilation |
|
|
|
|
* with @ref Shader::submitCompile() or @ref Shader::compile() before |
|
|
|
|
* linking. Call @ref isLinkFinished() or @ref checkLink() after, see |
|
|
|
|
* @ref GL-AbstractShaderProgram-async for more information. |
|
|
|
|
* @see @fn_gl_keyword{LinkProgram} |
|
|
|
|
*/ |
|
|
|
|
void submitLink(); |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Check link status and await completion |
|
|
|
|
* @brief Check shader linking status and await completion |
|
|
|
|
* @m_since_latest |
|
|
|
|
* |
|
|
|
|
* Has to be called only if @ref submitLink() was called before. |
|
|
|
|
* Returns @cpp false @ce if linking failed, @cpp true @ce on success. |
|
|
|
|
* Linker message (if any) is printed to error output. This function |
|
|
|
|
* must be called only after @ref submitLink(). |
|
|
|
|
* |
|
|
|
|
* @see @fn_gl_keyword{GetProgram} with |
|
|
|
|
* Linker message (if any) is printed to error output. The function |
|
|
|
|
* will stall until a (potentially async) linking operation finishes, |
|
|
|
|
* you can use @ref isLinkFinished() to check the status instead. See |
|
|
|
|
* @ref GL-AbstractShaderProgram-async for more information. |
|
|
|
|
* @see @ref Shader::checkCompile(), @fn_gl_keyword{GetProgram} with |
|
|
|
|
* @def_gl{LINK_STATUS} and @def_gl{INFO_LOG_LENGTH}, |
|
|
|
|
* @fn_gl_keyword{GetProgramInfoLog} |
|
|
|
|
*/ |
|
|
|
|
|