From 48326ac418590fa89a4d5ee21231bb61ad0c865e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 6 Sep 2022 15:19:30 +0200 Subject: [PATCH] Shaders: minor cleanup & document new async compilation APIs. Apart from docs mostly just reordering declaratios, removing usage of auto and providing default arguments where missing. --- doc/snippets/MagnumShaders-gl.cpp | 21 +++ src/Magnum/Shaders/DistanceFieldVectorGL.cpp | 6 +- src/Magnum/Shaders/DistanceFieldVectorGL.h | 68 ++++++-- src/Magnum/Shaders/FlatGL.cpp | 14 +- src/Magnum/Shaders/FlatGL.h | 70 ++++++-- src/Magnum/Shaders/MeshVisualizerGL.cpp | 60 ++++--- src/Magnum/Shaders/MeshVisualizerGL.h | 154 +++++++++++++----- src/Magnum/Shaders/PhongGL.cpp | 13 +- src/Magnum/Shaders/PhongGL.h | 69 ++++++-- .../Test/DistanceFieldVectorGLTest.cpp | 25 ++- src/Magnum/Shaders/Test/FlatGLTest.cpp | 27 +-- .../Shaders/Test/MeshVisualizerGLTest.cpp | 46 +++--- src/Magnum/Shaders/Test/PhongGLTest.cpp | 26 +-- src/Magnum/Shaders/Test/VectorGLTest.cpp | 26 +-- src/Magnum/Shaders/Test/VertexColorGLTest.cpp | 18 +- src/Magnum/Shaders/VectorGL.cpp | 14 +- src/Magnum/Shaders/VectorGL.h | 70 ++++++-- src/Magnum/Shaders/VertexColorGL.cpp | 13 +- src/Magnum/Shaders/VertexColorGL.h | 69 ++++++-- 19 files changed, 531 insertions(+), 278 deletions(-) diff --git a/doc/snippets/MagnumShaders-gl.cpp b/doc/snippets/MagnumShaders-gl.cpp index c1af534c0..5e5de8316 100644 --- a/doc/snippets/MagnumShaders-gl.cpp +++ b/doc/snippets/MagnumShaders-gl.cpp @@ -341,6 +341,27 @@ shader /* [shaders-meshvisualizer] */ } +{ +/* [shaders-async] */ +Shaders::FlatGL3D::CompileState flatState = + Shaders::FlatGL3D::compile(); +Shaders::FlatGL3D::CompileState flatTexturedState = + Shaders::FlatGL3D::compile(Shaders::FlatGL3D::Flag::Textured); +Shaders::MeshVisualizerGL3D::CompileState meshVisualizerState = + Shaders::MeshVisualizerGL3D::compile(DOXYGEN_ELLIPSIS(Shaders::MeshVisualizerGL3D::Flag::Wireframe)); + +while(!flatState.isLinkFinished() || + !flatTexturedState.isLinkFinished() || + !meshVisualizerState.isLinkFinished()) { + // Do other work ... +} + +Shaders::FlatGL3D flat{std::move(flatState)}; +Shaders::FlatGL3D flatTextured{std::move(flatTexturedState)}; +Shaders::MeshVisualizerGL3D meshVisualizer{std::move(meshVisualizerState)}; +/* [shaders-async] */ +} + /* internal compiler error: in gimplify_init_constructor, at gimplify.c:4271 on GCC 4.8 in the [60] array */ #if !defined(CORRADE_TARGET_GCC) || defined(CORRADE_TARGET_CLANG) || __GNUC__ >= 5 diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp index 6c627cf98..eb7b1f45e 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp @@ -162,13 +162,13 @@ template typename DistanceFieldVectorGL::Com return CompileState{std::move(out), std::move(vert), std::move(frag), version}; } -template DistanceFieldVectorGL::DistanceFieldVectorGL(CompileState&& cs): DistanceFieldVectorGL{static_cast(std::move(cs))} { - if (id() == 0) return; +template DistanceFieldVectorGL::DistanceFieldVectorGL(CompileState&& state): DistanceFieldVectorGL{static_cast(std::move(state))} { + if(!id()) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); const GL::Context& context = GL::Context::current(); - const GL::Version version = cs._version; + const GL::Version version = state._version; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.h b/src/Magnum/Shaders/DistanceFieldVectorGL.h index f46773784..c4332e200 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.h +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.h @@ -121,6 +121,8 @@ example. */ template class MAGNUM_SHADERS_EXPORT DistanceFieldVectorGL: public GL::AbstractShaderProgram { public: + class CompileState; + /** * @brief Vertex position * @@ -218,6 +220,34 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector typedef Implementation::DistanceFieldVectorGLFlags Flags; #endif + /** + * @brief Compile asynchronously + * @m_since_latest + * + * Compared to @ref DistanceFieldVectorGL(Flags) can perform an + * asynchronous compilation and linking. See @ref shaders-async for + * more information. + * @see @ref DistanceFieldVectorGL(CompileState&&), + * @ref compile(Flags, UnsignedInt, UnsignedInt) + */ + static CompileState compile(Flags flags = {}); + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Compile for a multi-draw scenario asynchronously + * @m_since_latest + * + * Compared to @ref DistanceFieldVectorGL(Flags, UnsignedInt, UnsignedInt) + * can perform an asynchronous compilation and linking. See + * @ref shaders-async for more information. + * @see @ref DistanceFieldVectorGL(CompileState&&), @ref compile(Flags) + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif + /** * @brief Constructor * @param flags Flags @@ -226,6 +256,7 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector * scenario (without @ref Flag::UniformBuffers set), it's equivalent to * @ref DistanceFieldVectorGL(Flags, UnsignedInt, UnsignedInt) with * @p materialCount and @p drawCount set to @cpp 1 @ce. + * @see @ref compile(Flags) */ explicit DistanceFieldVectorGL(Flags flags = {}); @@ -251,6 +282,7 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector * If @p flags don't contain @ref Flag::UniformBuffers, * @p materialCount and @p drawCount is ignored and the constructor * behaves the same as @ref DistanceFieldVectorGL(Flags). + * @see @ref compile(Flags, UnsignedInt, UnsignedInt) * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. @@ -267,6 +299,16 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector explicit DistanceFieldVectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); #endif + /** + * @brief Finalize an asynchronous compilation + * @m_since_latest + * + * Takes an asynchronous compilation state returned by @ref compile() + * and forms a ready-to-use shader object. See @ref shaders-async for + * more information. + */ + explicit DistanceFieldVectorGL(CompileState&& state); + /** * @brief Construct without creating the underlying OpenGL object * @@ -281,20 +323,6 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector */ explicit DistanceFieldVectorGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} - class CompileState; - - explicit DistanceFieldVectorGL(CompileState&& cs); - - static CompileState compile(Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt materialCount, UnsignedInt drawCount - #endif - ); - - #ifndef MAGNUM_TARGET_GLES2 - static CompileState compile(Flags flags); - #endif - /** @brief Copying is not allowed */ DistanceFieldVectorGL(const DistanceFieldVectorGL&) = delete; @@ -617,6 +645,8 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector #endif private: + /* Creates the GL shader program object but does nothing else. + Internal, used by compile(). */ explicit DistanceFieldVectorGL(NoInitT); /* Prevent accidentally calling irrelevant functions */ @@ -644,15 +674,19 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector #endif }; +/** +@brief Asynchronous compilation state +@m_since_latest +Returned by @ref compile(). See @ref shaders-async for more information. +*/ template class DistanceFieldVectorGL::CompileState: public DistanceFieldVectorGL { -private: + /* Everything deliberately private except for the inheritance */ friend class DistanceFieldVectorGL; explicit CompileState(NoCreateT): DistanceFieldVectorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} - CompileState(DistanceFieldVectorGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): - DistanceFieldVectorGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} + explicit CompileState(DistanceFieldVectorGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): DistanceFieldVectorGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} GL::Shader _vert, _frag; GL::Version _version; diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 645d7eade..3cc8084c4 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -67,10 +67,10 @@ namespace { #endif } -template typename FlatGL::CompileState FlatGL::compile(Flags flags -#ifndef MAGNUM_TARGET_GLES2 -, UnsignedInt materialCount, UnsignedInt drawCount -#endif +template typename FlatGL::CompileState FlatGL::compile(const Flags flags + #ifndef MAGNUM_TARGET_GLES2 + , const UnsignedInt materialCount, const UnsignedInt drawCount + #endif ) { #ifndef CORRADE_NO_ASSERT { @@ -237,13 +237,13 @@ template typename FlatGL::CompileState FlatG return CompileState{std::move(out), std::move(vert), std::move(frag), version}; } -template FlatGL::FlatGL(CompileState&& cs): FlatGL{static_cast(std::move(cs))} { - if (id() == 0) return; +template FlatGL::FlatGL(CompileState&& state): FlatGL{static_cast(std::move(state))} { + if(!id()) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); const GL::Context& context = GL::Context::current(); - const GL::Version version = cs._version; + const GL::Version version = state._version; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h index 354d43240..d7775f7e8 100644 --- a/src/Magnum/Shaders/FlatGL.h +++ b/src/Magnum/Shaders/FlatGL.h @@ -202,6 +202,8 @@ all shaders, see @ref shaders-usage-multidraw for an example. */ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL::AbstractShaderProgram { public: + class CompileState; + /** * @brief Vertex position * @@ -541,6 +543,34 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: typedef Implementation::FlatGLFlags Flags; #endif + /** + * @brief Compile asynchronously + * @m_since_latest + * + * Compared to @ref FlatGL(Flags) can perform an asynchronous + * compilation and linking. See @ref shaders-async for more + * information. + * @see @ref FlatGL(CompileState&&), + * @ref compile(Flags, UnsignedInt, UnsignedInt) + */ + static CompileState compile(Flags flags = {}); + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Compile for a multi-draw scenario asynchronously + * @m_since_latest + * + * Compared to @ref FlatGL(Flags, UnsignedInt, UnsignedInt) can perform + * an asynchronous compilation and linking. See @ref shaders-async for + * more information. + * @see @ref FlatGL(CompileState&&), @ref compile(Flags) + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif + /** * @brief Constructor * @param flags Flags @@ -549,6 +579,7 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: * scenario (without @ref Flag::UniformBuffers set), it's equivalent to * @ref FlatGL(Flags, UnsignedInt, UnsignedInt) with @p materialCount * and @p drawCount set to @cpp 1 @ce. + * @see @ref compile(Flags) */ explicit FlatGL(Flags flags = {}); @@ -573,6 +604,7 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: * If @p flags don't contain @ref Flag::UniformBuffers, * @p materialCount and @p drawCount is ignored and the constructor * behaves the same as @ref FlatGL(Flags). + * @see @ref compile(Flags, UnsignedInt, UnsignedInt) * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. @@ -589,6 +621,16 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: explicit FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); #endif + /** + * @brief Finalize an asynchronous compilation + * @m_since_latest + * + * Takes an asynchronous compilation state returned by @ref compile() + * and forms a ready-to-use shader object. See @ref shaders-async for + * more information. + */ + explicit FlatGL(CompileState&& state); + /** * @brief Construct without creating the underlying OpenGL object * @@ -603,20 +645,6 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: */ explicit FlatGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} - class CompileState; - - explicit FlatGL(CompileState&& cs); - - static CompileState compile(Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt materialCount, UnsignedInt drawCount - #endif - ); - - #ifndef MAGNUM_TARGET_GLES2 - static CompileState compile(Flags flags); - #endif - /** @brief Copying is not allowed */ FlatGL(const FlatGL&) = delete; @@ -1026,7 +1054,8 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: #endif private: - /* Creates the GL shader program object but nothing else. Internal, used by compile(). */ + /* Creates the GL shader program object but does nothing else. + Internal, used by compile(). */ explicit FlatGL(NoInitT); /* Prevent accidentally calling irrelevant functions */ @@ -1056,14 +1085,19 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: #endif }; +/** +@brief Asynchronous compilation state +@m_since_latest + +Returned by @ref compile(). See @ref shaders-async for more information. +*/ template class FlatGL::CompileState: public FlatGL { -private: + /* Everything deliberately private except for the inheritance */ friend class FlatGL; explicit CompileState(NoCreateT): FlatGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} - CompileState(FlatGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): - FlatGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} + explicit CompileState(FlatGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): FlatGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} GL::Shader _vert, _frag; GL::Version _version; diff --git a/src/Magnum/Shaders/MeshVisualizerGL.cpp b/src/Magnum/Shaders/MeshVisualizerGL.cpp index 6aaaac536..b08ae189c 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.cpp +++ b/src/Magnum/Shaders/MeshVisualizerGL.cpp @@ -139,10 +139,9 @@ void MeshVisualizerGLBase::assertExtensions(const FlagsBase flags) { #endif } -GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs, - const FlagsBase flags +GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs, const FlagsBase flags #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt materialCount, UnsignedInt drawCount + , const UnsignedInt materialCount, UnsignedInt const drawCount #endif ) { GL::Context& context = GL::Context::current(); @@ -376,12 +375,12 @@ MeshVisualizerGLBase& MeshVisualizerGLBase::bindObjectIdTexture(GL::Texture2DArr } -MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags +MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags #ifndef MAGNUM_TARGET_GLES2 , const UnsignedInt materialCount, const UnsignedInt drawCount #endif ) { - FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags)); + const FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags)); assertExtensions(baseFlags); #ifndef MAGNUM_TARGET_GLES2 @@ -410,9 +409,9 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags GL::Shader vert{NoCreate}; GL::Shader frag{NoCreate}; const GL::Version version = setupShaders(vert, frag, rs, baseFlags - #ifndef MAGNUM_TARGET_GLES2 - , materialCount, drawCount - #endif + #ifndef MAGNUM_TARGET_GLES2 + , materialCount, drawCount + #endif ); Containers::Optional geom; @@ -472,7 +471,7 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags vert.submitCompile(); frag.submitCompile(); - if (geom) geom->submitCompile(); + if(geom) geom->submitCompile(); MeshVisualizerGL2D out{NoInit}; out._flags = baseFlags; @@ -482,7 +481,7 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags #endif out.attachShaders({vert, frag}); - if (geom) out.attachShader(*geom); + if(geom) out.attachShader(*geom); /* ES3 has this done in the shader directly */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) @@ -519,26 +518,24 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags return CompileState{std::move(out), std::move(vert), std::move(frag), std::move(geom), flags, version}; } -MeshVisualizerGL2D::MeshVisualizerGL2D(Flags flags) : MeshVisualizerGL2D{compile(flags)} {} +MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): MeshVisualizerGL2D{compile(flags)} {} #ifndef MAGNUM_TARGET_GLES2 -MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags) { +MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags) { return compile(flags, 1, 1); } -MeshVisualizerGL2D::MeshVisualizerGL2D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount) - : MeshVisualizerGL2D{compile(flags, materialCount, drawCount)} {} +MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): MeshVisualizerGL2D{compile(flags, materialCount, drawCount)} {} #endif -MeshVisualizerGL2D::MeshVisualizerGL2D(CompileState&& cs) -: MeshVisualizerGL2D{static_cast(std::move(cs))} { - if (id() == 0) return; +MeshVisualizerGL2D::MeshVisualizerGL2D(CompileState&& state): MeshVisualizerGL2D{static_cast(std::move(state))} { + if(!id()) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); const GL::Context& context = GL::Context::current(); - const GL::Version version = cs._version; - Flags flags = cs._flags; + const GL::Version version = state._version; + const Flags flags = state._flags; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) @@ -744,9 +741,9 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags GL::Shader vert{NoCreate}; GL::Shader frag{NoCreate}; const GL::Version version = setupShaders(vert, frag, rs, baseFlags - #ifndef MAGNUM_TARGET_GLES2 - , materialCount, drawCount - #endif + #ifndef MAGNUM_TARGET_GLES2 + , materialCount, drawCount + #endif ); Containers::Optional geom; @@ -840,7 +837,7 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags vert.submitCompile(); frag.submitCompile(); - if (geom) geom->submitCompile(); + if(geom) geom->submitCompile(); MeshVisualizerGL3D out{NoInit}; out._flags = baseFlags; @@ -850,7 +847,7 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags #endif out.attachShaders({vert, frag}); - if (geom) out.attachShader(*geom); + if(geom) out.attachShader(*geom); /* ES3 has this done in the shader directly */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) @@ -903,14 +900,14 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags return CompileState{std::move(out), std::move(vert), std::move(frag), std::move(geom), flags, version}; } -MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& cs): MeshVisualizerGL3D{static_cast(std::move(cs))} { - if (id() == 0) return; +MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& state): MeshVisualizerGL3D{static_cast(std::move(state))} { + if(!id()) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); const GL::Context& context = GL::Context::current(); - const GL::Version version = cs._version; - Flags flags = cs._flags; + const GL::Version version = state._version; + Flags flags = state._flags; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) @@ -1043,15 +1040,14 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& cs): MeshVisualizerGL3D{st static_cast(version); } -MeshVisualizerGL3D::MeshVisualizerGL3D(Flags flags) : MeshVisualizerGL3D{compile(flags)} {} +MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags): MeshVisualizerGL3D{compile(flags)} {} #ifndef MAGNUM_TARGET_GLES2 -MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags) { +MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(const Flags flags) { return compile(flags, 1, 1); } -MeshVisualizerGL3D::MeshVisualizerGL3D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): - MeshVisualizerGL3D{compile(flags, materialCount, drawCount)} {} +MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): MeshVisualizerGL3D{compile(flags, materialCount, drawCount)} {} #endif MeshVisualizerGL3D& MeshVisualizerGL3D::setTransformationMatrix(const Matrix4& matrix) { diff --git a/src/Magnum/Shaders/MeshVisualizerGL.h b/src/Magnum/Shaders/MeshVisualizerGL.h index aa58e7f45..8857663ee 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.h +++ b/src/Magnum/Shaders/MeshVisualizerGL.h @@ -76,8 +76,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGLBase: public GL::AbstractShaderProgr explicit MeshVisualizerGLBase(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} static MAGNUM_SHADERS_LOCAL void assertExtensions(const FlagsBase flags); - static MAGNUM_SHADERS_LOCAL GL::Version setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs, - const FlagsBase flags + static MAGNUM_SHADERS_LOCAL GL::Version setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs, const FlagsBase flags #ifndef MAGNUM_TARGET_GLES2 , UnsignedInt materialCount, UnsignedInt drawCount #endif @@ -189,6 +188,8 @@ texture offset (or offset and layer). */ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisualizerGLBase { public: + class CompileState; + /** * @brief Vertex position * @@ -446,6 +447,35 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua /** @brief Flags */ typedef Containers::EnumSet Flags; + /** + * @brief Compile asynchronously + * @m_since_latest + * + * Compared to @ref MeshVisualizerGL2D(Flags) can perform an + * asynchronous compilation and linking. See @ref shaders-async for + * more information. + * @see @ref MeshVisualizerGL2D(CompileState&&), + * @ref compile(Flags, UnsignedInt, UnsignedInt) + */ + /* No default value, consistently with MeshVisualizerGL2D(Flags) */ + static CompileState compile(Flags flags); + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Compile for a multi-draw scenario asynchronously + * @m_since_latest + * + * Compared to @ref MeshVisualizerGL2D(Flags, UnsignedInt, UnsignedInt) + * can perform an asynchronous compilation and linking. See + * @ref shaders-async for more information. + * @see @ref MeshVisualizerGL2D(CompileState&&), @ref compile(Flags) + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif + /** * @brief Constructor * @param flags Flags @@ -456,6 +486,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua * scenario (without @ref Flag::UniformBuffers set), it's equivalent to * @ref MeshVisualizerGL2D(Flags, UnsignedInt, UnsignedInt) with * @p materialCount and @p drawCount set to @cpp 1 @ce. + * @see @ref compile(Flags) */ explicit MeshVisualizerGL2D(Flags flags); @@ -481,6 +512,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua * If @p flags don't contain @ref Flag::UniformBuffers, * @p materialCount and @p drawCount is ignored and the constructor * behaves the same as @ref MeshVisualizerGL2D(Flags). + * @see @ref compile(Flags, UnsignedInt, UnsignedInt) * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. @@ -496,6 +528,16 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua explicit MeshVisualizerGL2D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); #endif + /** + * @brief Finalize an asynchronous compilation + * @m_since_latest + * + * Takes an asynchronous compilation state returned by @ref compile() + * and forms a ready-to-use shader object. See @ref shaders-async for + * more information. + */ + explicit MeshVisualizerGL2D(CompileState&& state); + /** * @brief Construct without creating the underlying OpenGL object * @@ -510,20 +552,6 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua */ explicit MeshVisualizerGL2D(NoCreateT) noexcept: Implementation::MeshVisualizerGLBase{NoCreate} {} - class CompileState; - - explicit MeshVisualizerGL2D(CompileState&& cs); - - static CompileState compile(Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt materialCount, UnsignedInt drawCount - #endif - ); - - #ifndef MAGNUM_TARGET_GLES2 - static CompileState compile(Flags flags); - #endif - /** @brief Copying is not allowed */ MeshVisualizerGL2D(const MeshVisualizerGL2D&) = delete; @@ -881,19 +909,26 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua #endif private: - explicit MeshVisualizerGL2D(NoInitT) : Implementation::MeshVisualizerGLBase{NoInit} {} + /* Creates the GL shader program object but does nothing else. + Internal, used by compile(). */ + explicit MeshVisualizerGL2D(NoInitT): Implementation::MeshVisualizerGLBase{NoInit} {} Int _transformationProjectionMatrixUniform{9}; }; +/** +@brief Asynchronous compilation state +@m_since_latest + +Returned by @ref compile(). See @ref shaders-async for more information. +*/ class MeshVisualizerGL2D::CompileState: public MeshVisualizerGL2D { -private: + /* Everything deliberately private except for the inheritance */ friend class MeshVisualizerGL2D; explicit CompileState(NoCreateT): MeshVisualizerGL2D{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} - CompileState(MeshVisualizerGL2D&& shader, GL::Shader&& vert, GL::Shader&& frag, Containers::Optional&& geom, Flags flags, GL::Version version): - MeshVisualizerGL2D{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _geom{std::move(geom)}, _flags{flags}, _version{version} {} + explicit CompileState(MeshVisualizerGL2D&& shader, GL::Shader&& vert, GL::Shader&& frag, Containers::Optional&& geom, Flags flags, GL::Version version): MeshVisualizerGL2D{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _geom{std::move(geom)}, _flags{flags}, _version{version} {} GL::Shader _vert, _frag; Containers::Optional _geom; @@ -1139,6 +1174,8 @@ similar for all shaders, see @ref shaders-usage-multidraw for an example. */ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisualizerGLBase { public: + class CompileState; + /** * @brief Vertex position * @@ -1653,6 +1690,35 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua /** @brief Flags */ typedef Containers::EnumSet Flags; + /** + * @brief Compile asynchronously + * @m_since_latest + * + * Compared to @ref MeshVisualizerGL3D(Flags) can perform an + * asynchronous compilation and linking. See @ref shaders-async for + * more information. + * @see @ref MeshVisualizerGL3D(CompileState&&), + * @ref compile(Flags, UnsignedInt, UnsignedInt) + */ + /* No default value, consistently with MeshVisualizerGL3D(Flags) */ + static CompileState compile(Flags flags); + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Compile for a multi-draw scenario asynchronously + * @m_since_latest + * + * Compared to @ref MeshVisualizerGL3D(Flags, UnsignedInt, UnsignedInt) + * can perform an asynchronous compilation and linking. See + * @ref shaders-async for more information. + * @see @ref MeshVisualizerGL3D(CompileState&&), @ref compile(Flags) + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif + /** * @brief Constructor * @param flags Flags @@ -1666,6 +1732,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua * scenario (without @ref Flag::UniformBuffers set), it's equivalent to * @ref MeshVisualizerGL3D(Flags, UnsignedInt, UnsignedInt) with * @p materialCount and @p drawCount set to @cpp 1 @ce. + * @see @ref compile(Flags) */ explicit MeshVisualizerGL3D(Flags flags); @@ -1702,8 +1769,8 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua * @ref MeshVisualizerDrawUniform3D::materialId. * * If @p flags don't contain @ref Flag::UniformBuffers, - * @p materialCount and @p drawCount is ignored and the constructor - * behaves the same as @ref MeshVisualizerGL3D(Flags). + * @p materialCount and @p drawCount is ignored and the constructo + * @see @ref compile(Flags, UnsignedInt, UnsignedInt) * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. @@ -1734,20 +1801,15 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua */ explicit MeshVisualizerGL3D(NoCreateT) noexcept: Implementation::MeshVisualizerGLBase{NoCreate} {} - class CompileState; - - explicit MeshVisualizerGL3D(CompileState&& cs); - - static CompileState compile(Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt materialCount, UnsignedInt drawCount - #endif - ); - - #ifndef MAGNUM_TARGET_GLES2 - static CompileState compile(Flags flags); - #endif - + /** + * @brief Finalize an asynchronous compilation + * @m_since_latest + * + * Takes an asynchronous compilation state returned by @ref compile() + * and forms a ready-to-use shader object. See @ref shaders-async for + * more information. + */ + explicit MeshVisualizerGL3D(CompileState&& state); /** @brief Copying is not allowed */ MeshVisualizerGL3D(const MeshVisualizerGL3D&) = delete; @@ -2377,7 +2439,9 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua #endif private: - explicit MeshVisualizerGL3D(NoInitT) : Implementation::MeshVisualizerGLBase{NoInit} {} + /* Creates the GL shader program object but does nothing else. + Internal, used by compile(). */ + explicit MeshVisualizerGL3D(NoInitT): Implementation::MeshVisualizerGLBase{NoInit} {} Int _transformationMatrixUniform{9}, _projectionMatrixUniform{10}; @@ -2388,14 +2452,19 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua #endif }; -class MeshVisualizerGL3D::CompileState : public MeshVisualizerGL3D { -private: +/** +@brief Asynchronous compilation state +@m_since_latest + +Returned by @ref compile(). See @ref shaders-async for more information. +*/ +class MeshVisualizerGL3D::CompileState: public MeshVisualizerGL3D { + /* Everything deliberately private except for the inheritance */ friend class MeshVisualizerGL3D; - explicit CompileState(NoCreateT) : MeshVisualizerGL3D{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} + explicit CompileState(NoCreateT): MeshVisualizerGL3D{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} - CompileState(MeshVisualizerGL3D&& shader, GL::Shader&& vert, GL::Shader&& frag, Containers::Optional&& geom, Flags flags, GL::Version version) : - MeshVisualizerGL3D{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _geom{std::move(geom)}, _flags{flags}, _version{version} {} + explicit CompileState(MeshVisualizerGL3D&& shader, GL::Shader&& vert, GL::Shader&& frag, Containers::Optional&& geom, Flags flags, GL::Version version): MeshVisualizerGL3D{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _geom{std::move(geom)}, _flags{flags}, _version{version} {} GL::Shader _vert, _frag; Containers::Optional _geom; @@ -2403,7 +2472,6 @@ private: GL::Version _version; }; - /** @debugoperatorclassenum{MeshVisualizerGL2D,MeshVisualizerGL2D::Flag} */ MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, MeshVisualizerGL2D::Flag value); diff --git a/src/Magnum/Shaders/PhongGL.cpp b/src/Magnum/Shaders/PhongGL.cpp index bd8bf9e65..4e4538e63 100644 --- a/src/Magnum/Shaders/PhongGL.cpp +++ b/src/Magnum/Shaders/PhongGL.cpp @@ -347,13 +347,13 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh return CompileState{std::move(out), std::move(vert), std::move(frag), version}; } -PhongGL::PhongGL(CompileState&& cs): PhongGL{static_cast(std::move(cs))} { - if (id() == 0) return; +PhongGL::PhongGL(CompileState&& state): PhongGL{static_cast(std::move(state))} { + if(!id()) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); const GL::Context& context = GL::Context::current(); - const GL::Version version = cs._version; + const GL::Version version = state._version; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) @@ -463,15 +463,14 @@ PhongGL::PhongGL(CompileState&& cs): PhongGL{static_cast(std::move(cs static_cast(version); } -PhongGL::PhongGL(Flags flags, UnsignedInt lightCount): PhongGL{compile(flags, lightCount)} {} +PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): PhongGL{compile(flags, lightCount)} {} #ifndef MAGNUM_TARGET_GLES2 -PhongGL::CompileState PhongGL::compile(Flags flags, UnsignedInt lightCount) { +PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt lightCount) { return compile(flags, lightCount, 1, 1); } -PhongGL::PhongGL(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, UnsignedInt drawCount): - PhongGL{compile(flags, lightCount, materialCount, drawCount)} {} +PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount, const UnsignedInt materialCount, const UnsignedInt drawCount): PhongGL{compile(flags, lightCount, materialCount, drawCount)} {} #endif PhongGL& PhongGL::setAmbientColor(const Magnum::Color4& color) { diff --git a/src/Magnum/Shaders/PhongGL.h b/src/Magnum/Shaders/PhongGL.h index 8a06e2ccc..e496e5850 100644 --- a/src/Magnum/Shaders/PhongGL.h +++ b/src/Magnum/Shaders/PhongGL.h @@ -297,6 +297,8 @@ Besides that, the usage is similar for all shaders, see */ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { public: + class CompileState; + /** * @brief Vertex position * @@ -754,6 +756,34 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { */ typedef Containers::EnumSet Flags; + /** + * @brief Compile asynchronously + * @m_since_latest + * + * Compared to @ref PhongGL(Flags, UnsignedInt) can perform an + * asynchronous compilation and linking. See @ref shaders-async for + * more information. + * @see @ref PhongGL(CompileState&&), + * @ref compile(Flags, UnsignedInt, UnsignedInt, UnsignedInt) + */ + static CompileState compile(Flags flags = {}, UnsignedInt lightCount = 1); + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Compile for a multi-draw scenario asynchronously + * @m_since_latest + * + * Compared to @ref PhongGL(Flags, UnsignedInt, UnsignedInt, UnsignedInt) + * can perform an asynchronous compilation and linking. See + * @ref shaders-async for more information. + * @see @ref PhongGL(CompileState&&), @ref compile(Flags, UnsignedInt) + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + static CompileState compile(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, UnsignedInt drawCount); + #endif + /** * @brief Constructor * @param flags Flags @@ -763,6 +793,7 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { * scenario (without @ref Flag::UniformBuffers set), it's equivalent to * @ref PhongGL(Flags, UnsignedInt, UnsignedInt, UnsignedInt) with * @p materialCount and @p drawCount set to @cpp 1 @ce. + * @see @ref compile(Flags, UnsignedInt) */ explicit PhongGL(Flags flags = {}, UnsignedInt lightCount = 1); @@ -792,6 +823,7 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { * If @p flags don't contain @ref Flag::UniformBuffers, * @p materialCount and @p drawCount is ignored and the constructor * behaves the same as @ref PhongGL(Flags, UnsignedInt). + * @see @ref compile(Flags, UnsignedInt, UnsignedInt, UnsignedInt) * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. @@ -808,6 +840,16 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { explicit PhongGL(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, UnsignedInt drawCount); #endif + /** + * @brief Finalize an asynchronous compilation + * @m_since_latest + * + * Takes an asynchronous compilation state returned by @ref compile() + * and forms a ready-to-use shader object. See @ref shaders-async for + * more information. + */ + explicit PhongGL(CompileState&& state); + /** * @brief Construct without creating the underlying OpenGL object * @@ -822,20 +864,6 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { */ explicit PhongGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} - class CompileState; - - explicit PhongGL(CompileState&& cs); - - static CompileState compile(Flags flags, UnsignedInt lightCount - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt materialCount, UnsignedInt drawCount - #endif - ); - - #ifndef MAGNUM_TARGET_GLES2 - static CompileState compile(Flags flags, UnsignedInt lightCount); - #endif - /** @brief Copying is not allowed */ PhongGL(const PhongGL&) = delete; @@ -1759,6 +1787,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { #endif private: + /* Creates the GL shader program object but does nothing else. + Internal, used by compile(). */ explicit PhongGL(NoInitT) {} /* Prevent accidentally calling irrelevant functions */ @@ -1801,14 +1831,19 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { #endif }; +/** +@brief Asynchronous compilation state +@m_since_latest + +Returned by @ref compile(). See @ref shaders-async for more information. +*/ class PhongGL::CompileState: public PhongGL { -private: + /* Everything deliberately private except for the inheritance */ friend class PhongGL; explicit CompileState(NoCreateT): PhongGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} - CompileState(PhongGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): - PhongGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} + explicit CompileState(PhongGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): PhongGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} GL::Shader _vert, _frag; GL::Version _version; diff --git a/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp b/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp index e23db4a99..dd5f72242 100644 --- a/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp +++ b/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp @@ -31,8 +31,8 @@ #include #include #include -#include #include +#include #ifdef CORRADE_TARGET_APPLE #include @@ -388,13 +388,13 @@ template void DistanceFieldVectorGLTest::construct() { template void DistanceFieldVectorGLTest::constructAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - auto compileState = DistanceFieldVectorGL::compile(DistanceFieldVectorGL2D::Flag::TextureTransformation); - CORRADE_COMPARE(compileState.flags(), DistanceFieldVectorGL2D::Flag::TextureTransformation); + typename DistanceFieldVectorGL::CompileState state = DistanceFieldVectorGL::compile(DistanceFieldVectorGL2D::Flag::TextureTransformation); + CORRADE_COMPARE(state.flags(), DistanceFieldVectorGL2D::Flag::TextureTransformation); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - DistanceFieldVectorGL shader{std::move(compileState)}; + DistanceFieldVectorGL shader{std::move(state)}; CORRADE_COMPARE(shader.flags(), DistanceFieldVectorGL2D::Flag::TextureTransformation); CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); @@ -451,24 +451,23 @@ template void DistanceFieldVectorGLTest::constructUnifor template void DistanceFieldVectorGLTest::constructUniformBuffersAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif - auto compileState = DistanceFieldVectorGL::compile(DistanceFieldVectorGL2D::Flag::UniformBuffers, 16, 4); - CORRADE_COMPARE(compileState.flags(), DistanceFieldVectorGL2D::Flag::UniformBuffers); - CORRADE_COMPARE(compileState.materialCount(), 16); - CORRADE_COMPARE(compileState.drawCount(), 4); + typename DistanceFieldVectorGL::CompileState state = DistanceFieldVectorGL::compile(DistanceFieldVectorGL2D::Flag::UniformBuffers, 16, 48); + CORRADE_COMPARE(state.flags(), DistanceFieldVectorGL2D::Flag::UniformBuffers); + CORRADE_COMPARE(state.materialCount(), 16); + CORRADE_COMPARE(state.drawCount(), 48); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - DistanceFieldVectorGL shader{std::move(compileState)}; + DistanceFieldVectorGL shader{std::move(state)}; CORRADE_COMPARE(shader.flags(), DistanceFieldVectorGL2D::Flag::UniformBuffers); CORRADE_COMPARE(shader.materialCount(), 16); - CORRADE_COMPARE(shader.drawCount(), 4); + CORRADE_COMPARE(shader.drawCount(), 48); CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); { diff --git a/src/Magnum/Shaders/Test/FlatGLTest.cpp b/src/Magnum/Shaders/Test/FlatGLTest.cpp index 192c5fca2..94485a545 100644 --- a/src/Magnum/Shaders/Test/FlatGLTest.cpp +++ b/src/Magnum/Shaders/Test/FlatGLTest.cpp @@ -31,8 +31,8 @@ #include #include #include -#include #include +#include #ifdef CORRADE_TARGET_APPLE #include @@ -866,13 +866,14 @@ template void FlatGLTest::construct() { template void FlatGLTest::constructAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - auto compileState = FlatGL::compile(FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation); - CORRADE_COMPARE(compileState.flags(), FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation); - while(!compileState.isLinkFinished()) + typename FlatGL::CompileState state = FlatGL::compile(FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation); + CORRADE_COMPARE(state.flags(), FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation); + + while(!state.isLinkFinished()) Utility::System::sleep(100); - FlatGL shader{std::move(compileState)}; + FlatGL shader{std::move(state)}; CORRADE_COMPARE(shader.flags(), FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation); CORRADE_VERIFY(shader.id()); @@ -938,18 +939,18 @@ template void FlatGLTest::constructUniformBuffersAsync() CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif - auto compileState = FlatGL::compile(FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::AlphaMask, 1, 1); - CORRADE_COMPARE(compileState.flags(), FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::AlphaMask); - CORRADE_COMPARE(compileState.materialCount(), 1); - CORRADE_COMPARE(compileState.drawCount(), 1); + typename FlatGL::CompileState state = FlatGL::compile(FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::AlphaMask, 8, 48); + CORRADE_COMPARE(state.flags(), FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::AlphaMask); + CORRADE_COMPARE(state.materialCount(), 8); + CORRADE_COMPARE(state.drawCount(), 48); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - FlatGL shader{std::move(compileState)}; + FlatGL shader{std::move(state)}; CORRADE_COMPARE(shader.flags(), FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::AlphaMask); - CORRADE_COMPARE(shader.materialCount(), 1); - CORRADE_COMPARE(shader.drawCount(), 1); + CORRADE_COMPARE(shader.materialCount(), 8); + CORRADE_COMPARE(shader.drawCount(), 48); CORRADE_VERIFY(shader.id()); { #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) diff --git a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp index fbe96056e..957f33a9a 100644 --- a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp +++ b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp @@ -31,8 +31,8 @@ #include #include #include -#include #include +#include #ifdef CORRADE_TARGET_APPLE #include @@ -1416,13 +1416,13 @@ void MeshVisualizerGLTest::construct2D() { void MeshVisualizerGLTest::construct2DAsync() { - auto compileState = MeshVisualizerGL2D::compile(MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); - CORRADE_COMPARE(compileState.flags(), MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); + MeshVisualizerGL2D::CompileState state = MeshVisualizerGL2D::compile(MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); + CORRADE_COMPARE(state.flags(), MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - MeshVisualizerGL2D shader{std::move(compileState)}; + MeshVisualizerGL2D shader{std::move(state)}; CORRADE_COMPARE(shader.flags(), MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); @@ -1521,15 +1521,15 @@ void MeshVisualizerGLTest::constructUniformBuffers2DAsync() { CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif - auto compileState = MeshVisualizerGL2D::compile( MeshVisualizerGL2D::Flag::UniformBuffers|MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader, 8, 55); - CORRADE_COMPARE(compileState.flags(), MeshVisualizerGL2D::Flag::UniformBuffers|MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); - CORRADE_COMPARE(compileState.materialCount(), 8); - CORRADE_COMPARE(compileState.drawCount(), 55); + MeshVisualizerGL2D::CompileState state = MeshVisualizerGL2D::compile( MeshVisualizerGL2D::Flag::UniformBuffers|MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader, 8, 55); + CORRADE_COMPARE(state.flags(), MeshVisualizerGL2D::Flag::UniformBuffers|MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); + CORRADE_COMPARE(state.materialCount(), 8); + CORRADE_COMPARE(state.drawCount(), 55); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - MeshVisualizerGL2D shader{std::move(compileState)}; + MeshVisualizerGL2D shader{std::move(state)}; CORRADE_COMPARE(shader.flags(), MeshVisualizerGL2D::Flag::UniformBuffers|MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); CORRADE_COMPARE(shader.materialCount(), 8); CORRADE_COMPARE(shader.drawCount(), 55); @@ -1607,13 +1607,13 @@ void MeshVisualizerGLTest::construct3D() { } void MeshVisualizerGLTest::construct3DAsync() { - auto compileState = MeshVisualizerGL3D::compile(MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); - CORRADE_COMPARE(compileState.flags(), MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); + MeshVisualizerGL3D::CompileState state = MeshVisualizerGL3D::compile(MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); + CORRADE_COMPARE(state.flags(), MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - MeshVisualizerGL3D shader{std::move(compileState)}; + MeshVisualizerGL3D shader{std::move(state)}; CORRADE_COMPARE(shader.flags(), MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); @@ -1711,18 +1711,18 @@ void MeshVisualizerGLTest::constructUniformBuffers3DAsync() { CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif - auto compileState = MeshVisualizerGL3D::compile(MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader, 6, 28); - CORRADE_COMPARE(compileState.flags(), MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); - CORRADE_COMPARE(compileState.materialCount(), 6); - CORRADE_COMPARE(compileState.drawCount(), 28); + MeshVisualizerGL3D::CompileState state = MeshVisualizerGL3D::compile(MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader, 6, 28); + CORRADE_COMPARE(state.flags(), MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); + CORRADE_COMPARE(state.materialCount(), 6); + CORRADE_COMPARE(state.drawCount(), 28); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - MeshVisualizerGL3D shader{std::move(compileState)}; + MeshVisualizerGL3D shader{std::move(state)}; CORRADE_COMPARE(shader.flags(), MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); - CORRADE_COMPARE(compileState.materialCount(), 6); - CORRADE_COMPARE(compileState.drawCount(), 28); + CORRADE_COMPARE(state.materialCount(), 6); + CORRADE_COMPARE(state.drawCount(), 28); CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); { diff --git a/src/Magnum/Shaders/Test/PhongGLTest.cpp b/src/Magnum/Shaders/Test/PhongGLTest.cpp index d0df58ec4..a9d6f2f4e 100644 --- a/src/Magnum/Shaders/Test/PhongGLTest.cpp +++ b/src/Magnum/Shaders/Test/PhongGLTest.cpp @@ -31,9 +31,9 @@ #include #include #include -#include #include #include +#include #ifdef CORRADE_TARGET_APPLE #include @@ -1199,14 +1199,14 @@ void PhongGLTest::construct() { } void PhongGLTest::constructAsync() { - auto compileState = PhongGL::compile(PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset, 3); - CORRADE_COMPARE(compileState.flags(), PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset); - CORRADE_COMPARE(compileState.lightCount(), 3); + PhongGL::CompileState state = PhongGL::compile(PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset, 3); + CORRADE_COMPARE(state.flags(), PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset); + CORRADE_COMPARE(state.lightCount(), 3); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - PhongGL shader{std::move(compileState)}; + PhongGL shader{std::move(state)}; CORRADE_COMPARE(shader.flags(), PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset); CORRADE_COMPARE(shader.lightCount(), 3); CORRADE_VERIFY(shader.isLinkFinished()); @@ -1270,16 +1270,16 @@ void PhongGLTest::constructUniformBuffersAsync() { CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif - auto compileState = PhongGL::compile(PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling, 8, 8, 24); - CORRADE_COMPARE(compileState.flags(), PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling); - CORRADE_COMPARE(compileState.lightCount(), 8); - CORRADE_COMPARE(compileState.materialCount(), 8); - CORRADE_COMPARE(compileState.drawCount(), 24); + PhongGL::CompileState state = PhongGL::compile(PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling, 8, 8, 24); + CORRADE_COMPARE(state.flags(), PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling); + CORRADE_COMPARE(state.lightCount(), 8); + CORRADE_COMPARE(state.materialCount(), 8); + CORRADE_COMPARE(state.drawCount(), 24); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - PhongGL shader{std::move(compileState)}; + PhongGL shader{std::move(state)}; CORRADE_COMPARE(shader.flags(), PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling); CORRADE_COMPARE(shader.lightCount(), 8); CORRADE_COMPARE(shader.materialCount(), 8); diff --git a/src/Magnum/Shaders/Test/VectorGLTest.cpp b/src/Magnum/Shaders/Test/VectorGLTest.cpp index 715688e1e..a160640f7 100644 --- a/src/Magnum/Shaders/Test/VectorGLTest.cpp +++ b/src/Magnum/Shaders/Test/VectorGLTest.cpp @@ -31,8 +31,8 @@ #include #include #include -#include #include +#include #ifdef CORRADE_TARGET_APPLE #include @@ -384,13 +384,13 @@ template void VectorGLTest::construct() { template void VectorGLTest::constructAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - auto compileState = VectorGL::compile(VectorGL2D::Flag::TextureTransformation); - CORRADE_COMPARE(compileState.flags(), VectorGL2D::Flag::TextureTransformation); + typename VectorGL::CompileState state = VectorGL::compile(VectorGL2D::Flag::TextureTransformation); + CORRADE_COMPARE(state.flags(), VectorGL2D::Flag::TextureTransformation); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - VectorGL shader{std::move(compileState)}; + VectorGL shader{std::move(state)}; CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_COMPARE(shader.flags(), VectorGL2D::Flag::TextureTransformation); CORRADE_VERIFY(shader.id()); @@ -452,19 +452,19 @@ template void VectorGLTest::constructUniformBuffersAsync CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif - auto compileState = VectorGL::compile(VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation, 1, 1); - CORRADE_COMPARE(compileState.flags(), VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation); - CORRADE_COMPARE(compileState.materialCount(), 1); - CORRADE_COMPARE(compileState.drawCount(), 1); + typename VectorGL::CompileState state = VectorGL::compile(VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation, 15, 42); + CORRADE_COMPARE(state.flags(), VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation); + CORRADE_COMPARE(state.materialCount(), 15); + CORRADE_COMPARE(state.drawCount(), 42); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - VectorGL shader{std::move(compileState)}; + VectorGL shader{std::move(state)}; CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_COMPARE(shader.flags(), VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation); - CORRADE_COMPARE(shader.materialCount(), 1); - CORRADE_COMPARE(shader.drawCount(), 1); + CORRADE_COMPARE(shader.materialCount(), 15); + CORRADE_COMPARE(shader.drawCount(), 42); CORRADE_VERIFY(shader.id()); { #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) diff --git a/src/Magnum/Shaders/Test/VertexColorGLTest.cpp b/src/Magnum/Shaders/Test/VertexColorGLTest.cpp index 451c7348f..b62e6232c 100644 --- a/src/Magnum/Shaders/Test/VertexColorGLTest.cpp +++ b/src/Magnum/Shaders/Test/VertexColorGLTest.cpp @@ -29,8 +29,8 @@ #include #include #include -#include #include +#include #ifdef CORRADE_TARGET_APPLE #include @@ -321,12 +321,12 @@ template void VertexColorGLTest::construct() { template void VertexColorGLTest::constructAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - auto compileState = VertexColorGL::compile({}); + typename VertexColorGL::CompileState state = VertexColorGL::compile({}); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - VertexColorGL shader{std::move(compileState)}; + VertexColorGL shader{std::move(state)}; CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); { @@ -387,14 +387,14 @@ template void VertexColorGLTest::constructUniformBuffers CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif - auto compileState = VertexColorGL::compile(VertexColorGL2D::Flag::UniformBuffers, 63); - CORRADE_COMPARE(compileState.flags(), VertexColorGL2D::Flag::UniformBuffers); - CORRADE_COMPARE(compileState.drawCount(), 63); + typename VertexColorGL::CompileState state = VertexColorGL::compile(VertexColorGL2D::Flag::UniformBuffers, 63); + CORRADE_COMPARE(state.flags(), VertexColorGL2D::Flag::UniformBuffers); + CORRADE_COMPARE(state.drawCount(), 63); - while(!compileState.isLinkFinished()) + while(!state.isLinkFinished()) Utility::System::sleep(100); - VertexColorGL shader{std::move(compileState)}; + VertexColorGL shader{std::move(state)}; CORRADE_COMPARE(shader.flags(), VertexColorGL2D::Flag::UniformBuffers); CORRADE_COMPARE(shader.drawCount(), 63); CORRADE_VERIFY(shader.isLinkFinished()); diff --git a/src/Magnum/Shaders/VectorGL.cpp b/src/Magnum/Shaders/VectorGL.cpp index dd6ff2c07..a58c784f4 100644 --- a/src/Magnum/Shaders/VectorGL.cpp +++ b/src/Magnum/Shaders/VectorGL.cpp @@ -164,14 +164,13 @@ template typename VectorGL::CompileState Vec return CompileState{std::move(out), std::move(vert), std::move(frag), version}; } -template VectorGL::VectorGL(CompileState&& cs): VectorGL{static_cast(std::move(cs))} { - if (id() == 0) return; +template VectorGL::VectorGL(CompileState&& state): VectorGL{static_cast(std::move(state))} { + if(!id()) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); const GL::Context& context = GL::Context::current(); - const GL::Version version = cs._version; - + const GL::Version version = state._version; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) @@ -227,15 +226,14 @@ template VectorGL::VectorGL(CompileState&& c static_cast(version); } -template VectorGL::VectorGL(Flags flags): VectorGL{compile(flags)} {} +template VectorGL::VectorGL(const Flags flags): VectorGL{compile(flags)} {} #ifndef MAGNUM_TARGET_GLES2 -template typename VectorGL::CompileState VectorGL::compile(Flags flags) { +template typename VectorGL::CompileState VectorGL::compile(const Flags flags) { return compile(flags, 1, 1); } -template VectorGL::VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): - VectorGL{compile(flags, materialCount, drawCount)} {} +template VectorGL::VectorGL(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): VectorGL{compile(flags, materialCount, drawCount)} {} #endif template VectorGL::VectorGL(NoInitT) {} diff --git a/src/Magnum/Shaders/VectorGL.h b/src/Magnum/Shaders/VectorGL.h index 057dfc620..601bd0a44 100644 --- a/src/Magnum/Shaders/VectorGL.h +++ b/src/Magnum/Shaders/VectorGL.h @@ -116,6 +116,8 @@ example. */ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL::AbstractShaderProgram { public: + class CompileState; + /** * @brief Vertex position * @@ -213,6 +215,34 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL typedef Implementation::VectorGLFlags Flags; #endif + /** + * @brief Compile asynchronously + * @m_since_latest + * + * Compared to @ref VectorGL(Flags) can perform an asynchronous + * compilation and linking. See @ref shaders-async for more + * information. + * @see @ref VectorGL(CompileState&&), + * @ref compile(Flags, UnsignedInt, UnsignedInt) + */ + static CompileState compile(Flags flags = {}); + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Compile for a multi-draw scenario asynchronously + * @m_since_latest + * + * Compared to @ref VectorGL(Flags, UnsignedInt, UnsignedInt) can + * perform an asynchronous compilation and linking. See + * @ref shaders-async for more information. + * @see @ref VectorGL(CompileState&&), @ref compile(Flags) + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif + /** * @brief Constructor * @param flags Flags @@ -221,6 +251,7 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL * scenario (without @ref Flag::UniformBuffers set), it's equivalent to * @ref VectorGL(Flags, UnsignedInt, UnsignedInt) with @p materialCount * and @p drawCount set to @cpp 1 @ce. + * @see @ref compile(Flags) */ explicit VectorGL(Flags flags = {}); @@ -244,6 +275,7 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL * * If @p flags don't contain @ref Flag::UniformBuffers, @p drawCount is * ignored and the constructor behaves the same as @ref VectorGL(Flags). + * @see @ref compile(Flags, UnsignedInt, UnsignedInt) * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. @@ -260,6 +292,16 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL explicit VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); #endif + /** + * @brief Finalize an asynchronous compilation + * @m_since_latest + * + * Takes an asynchronous compilation state returned by @ref compile() + * and forms a ready-to-use shader object. See @ref shaders-async for + * more information. + */ + explicit VectorGL(CompileState&& state); + /** * @brief Construct without creating the underlying OpenGL object * @@ -274,20 +316,6 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL */ explicit VectorGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} - class CompileState; - - explicit VectorGL(CompileState&& cs); - - static CompileState compile(Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt materialCount, UnsignedInt drawCount - #endif - ); - - #ifndef MAGNUM_TARGET_GLES2 - static CompileState compile(Flags flags); - #endif - /** @brief Copying is not allowed */ VectorGL(const VectorGL&) = delete; @@ -569,7 +597,8 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL #endif private: - /* Creates the GL shader program object but nothing else. Internal, used by compile(). */ + /* Creates the GL shader program object but does nothing else. + Internal, used by compile(). */ explicit VectorGL(NoInitT); /* Prevent accidentally calling irrelevant functions */ @@ -595,14 +624,19 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL #endif }; +/** +@brief Asynchronous compilation state +@m_since_latest + +Returned by @ref compile(). See @ref shaders-async for more information. +*/ template class VectorGL::CompileState: public VectorGL { -private: + /* Everything deliberately private except for the inheritance */ friend class VectorGL; explicit CompileState(NoCreateT): VectorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} - CompileState(VectorGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): - VectorGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} + explicit CompileState(VectorGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): VectorGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} GL::Shader _vert, _frag; GL::Version _version; diff --git a/src/Magnum/Shaders/VertexColorGL.cpp b/src/Magnum/Shaders/VertexColorGL.cpp index 01af44cd1..c2667666c 100644 --- a/src/Magnum/Shaders/VertexColorGL.cpp +++ b/src/Magnum/Shaders/VertexColorGL.cpp @@ -142,13 +142,13 @@ template typename VertexColorGL::CompileStat return CompileState{std::move(out), std::move(vert), std::move(frag), version}; } -template VertexColorGL::VertexColorGL(CompileState&& cs): VertexColorGL{static_cast(std::move(cs))} { - if (id() == 0) return; +template VertexColorGL::VertexColorGL(CompileState&& state): VertexColorGL{static_cast(std::move(state))} { + if(!id()) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); const GL::Context& context = GL::Context::current(); - const GL::Version version = cs._version; + const GL::Version version = state._version; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) @@ -190,15 +190,14 @@ template VertexColorGL::VertexColorGL(Compil static_cast(version); } -template VertexColorGL::VertexColorGL(Flags flags): VertexColorGL{compile(flags)} {} +template VertexColorGL::VertexColorGL(const Flags flags): VertexColorGL{compile(flags)} {} #ifndef MAGNUM_TARGET_GLES2 -template typename VertexColorGL::CompileState VertexColorGL::compile(Flags flags) { +template typename VertexColorGL::CompileState VertexColorGL::compile(const Flags flags) { return compile(flags, 1); } -template VertexColorGL::VertexColorGL(Flags flags, UnsignedInt drawCount): - VertexColorGL{compile(flags, drawCount)} {} +template VertexColorGL::VertexColorGL(const Flags flags, const UnsignedInt drawCount): VertexColorGL{compile(flags, drawCount)} {} #endif template VertexColorGL::VertexColorGL(NoInitT) {} diff --git a/src/Magnum/Shaders/VertexColorGL.h b/src/Magnum/Shaders/VertexColorGL.h index 988af7811..1c671c779 100644 --- a/src/Magnum/Shaders/VertexColorGL.h +++ b/src/Magnum/Shaders/VertexColorGL.h @@ -111,6 +111,8 @@ similar for all shaders, see @ref shaders-usage-multidraw for an example. */ template class MAGNUM_SHADERS_EXPORT VertexColorGL: public GL::AbstractShaderProgram { public: + class CompileState; + /** * @brief Vertex position * @@ -208,6 +210,34 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ typedef Implementation::VertexColorGLFlags Flags; #endif + /** + * @brief Compile asynchronously + * @m_since_latest + * + * Compared to @ref VertexColorGL(Flags) can perform an asynchronous + * compilation and linking. See @ref shaders-async for more + * information. + * @see @ref VertexColorGL(CompileState&&), + * @ref compile(Flags, UnsignedInt) + */ + static CompileState compile(Flags flags = {}); + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Compile for a multi-draw scenario asynchronously + * @m_since_latest + * + * Compared to @ref VertexColorGL(Flags, UnsignedInt) can perform an + * asynchronous compilation and linking. See @ref shaders-async for + * more information. + * @see @ref VertexColorGL(CompileState&&), @ref compile(Flags) + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + static CompileState compile(Flags flags, UnsignedInt drawCount); + #endif + /** * @brief Constructor * @param flags Flags @@ -216,6 +246,7 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ * scenario (without @ref Flag::UniformBuffers set), it's equivalent to * @ref VertexColorGL(Flags, UnsignedInt) with @p drawCount set to * @cpp 1 @ce. + * @see @ref compile(Flags) */ explicit VertexColorGL(Flags flags = {}); @@ -235,6 +266,7 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ * If @p flags don't contain @ref Flag::UniformBuffers, @p drawCount is * ignored and the constructor behaves the same as * @ref VertexColorGL(Flags). + * @see @ref compile(Flags, UnsignedInt) * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. @@ -251,6 +283,16 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ explicit VertexColorGL(Flags flags, UnsignedInt drawCount); #endif + /** + * @brief Finalize an asynchronous compilation + * @m_since_latest + * + * Takes an asynchronous compilation state returned by @ref compile() + * and forms a ready-to-use shader object. See @ref shaders-async for + * more information. + */ + explicit VertexColorGL(CompileState&& state); + /** * @brief Construct without creating the underlying OpenGL object * @@ -265,20 +307,6 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ */ explicit VertexColorGL(NoCreateT) noexcept: AbstractShaderProgram{NoCreate} {} - class CompileState; - - explicit VertexColorGL(CompileState&& cs); - - static CompileState compile(Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt drawCount - #endif - ); - - #ifndef MAGNUM_TARGET_GLES2 - static CompileState compile(Flags flags); - #endif - /** @brief Copying is not allowed */ VertexColorGL(const VertexColorGL&) = delete; @@ -421,6 +449,8 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ #endif private: + /* Creates the GL shader program object but does nothing else. + Internal, used by compile(). */ explicit VertexColorGL(NoInitT); /* Prevent accidentally calling irrelevant functions */ @@ -443,14 +473,19 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ #endif }; +/** +@brief Asynchronous compilation state +@m_since_latest + +Returned by @ref compile(). See @ref shaders-async for more information. +*/ template class VertexColorGL::CompileState: public VertexColorGL { -private: + /* Everything deliberately private except for the inheritance */ friend class VertexColorGL; explicit CompileState(NoCreateT): VertexColorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} - CompileState(VertexColorGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): - VertexColorGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} + explicit CompileState(VertexColorGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): VertexColorGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} GL::Shader _vert, _frag; GL::Version _version;