From 51c8ba7fb1857600adad0b2667dc530805f3bfb2 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Fri, 8 Jul 2022 22:01:09 +0300 Subject: [PATCH 01/27] Basic async shader compilation for FlatGL --- src/Magnum/GL/AbstractShaderProgram.cpp | 25 +++++- src/Magnum/GL/AbstractShaderProgram.h | 47 ++++++++++- src/Magnum/GL/Shader.cpp | 21 ++++- src/Magnum/GL/Shader.h | 36 ++++++++ src/Magnum/Shaders/FlatGL.cpp | 107 +++++++++++++++--------- src/Magnum/Shaders/FlatGL.h | 43 ++++++++++ src/MagnumExternal/OpenGL/GL/flextGL.h | 6 +- 7 files changed, 240 insertions(+), 45 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.cpp b/src/Magnum/GL/AbstractShaderProgram.cpp index aab5854486..298da4d4a7 100644 --- a/src/Magnum/GL/AbstractShaderProgram.cpp +++ b/src/Magnum/GL/AbstractShaderProgram.cpp @@ -586,10 +586,21 @@ void AbstractShaderProgram::transformFeedbackVaryingsImplementationDanglingWorka bool AbstractShaderProgram::link() { return link({*this}); } bool AbstractShaderProgram::link(std::initializer_list> shaders) { - bool allSuccess = true; + submitLink(shaders); + return checkLink(shaders); +} + +void AbstractShaderProgram::submitLink() { submitLink({*this}); } - /* Invoke (possibly parallel) linking on all shaders */ +bool AbstractShaderProgram::checkLink() { return checkLink({*this}); } + +void AbstractShaderProgram::submitLink(std::initializer_list> shaders) { + /* Invoke (possibly parallel) linking on all shaders */ for(AbstractShaderProgram& shader: shaders) glLinkProgram(shader._id); +} + +bool AbstractShaderProgram::checkLink(std::initializer_list> shaders) { + bool allSuccess = true; /* After linking phase, check status of all shaders */ Int i = 1; @@ -632,6 +643,16 @@ bool AbstractShaderProgram::link(std::initializer_list> shaders); + /** + * @brief Submit shaders for linking + * + * The operation is batched in a + * way that allows the driver to link multiple shaders simultaneously + * (i.e. in multiple threads). + * + */ + static void submitLink(std::initializer_list> shaders); + + /** + * @brief Check linking status of shaders and await completion + * + * Returns @cpp false @ce if linking of any shader failed, @cpp true @ce + * if everything succeeded. Linker message (if any) is printed to error + * output. + * + */ + static bool checkLink(std::initializer_list> shaders); + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) /** * @brief Allow retrieving program binary @@ -1453,6 +1475,24 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { */ bool link(); + /** + * @brief Submit single shader for linking + * + */ + void submitLink(); + + /** + * @brief Check link status and await completion + * + */ + bool checkLink(); + + /** + * @brief Non-blocking linking status check + * + */ + bool isLinkFinished(); + /** * @brief Get uniform location * @param name Uniform name @@ -1729,6 +1769,11 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { #endif }; +struct AbstractShaderProgram::CompileState : public AbstractShaderProgram { + using AbstractShaderProgram::AbstractShaderProgram; + bool isLinkFinished(); +}; + }} #endif diff --git a/src/Magnum/GL/Shader.cpp b/src/Magnum/GL/Shader.cpp index 8708fa4b97..1b1441361b 100644 --- a/src/Magnum/GL/Shader.cpp +++ b/src/Magnum/GL/Shader.cpp @@ -749,14 +749,27 @@ Shader& Shader::addFile(const std::string& filename) { bool Shader::compile() { return compile({*this}); } +void Shader::submitCompile() { submitCompile({*this}); } + +bool Shader::checkCompile() { return checkCompile({*this}); } + bool Shader::compile(std::initializer_list> shaders) { - bool allSuccess = true; + submitCompile(shaders); + return checkCompile(shaders); +} +bool Shader::isCompileFinished() { + GLint success; + glGetShaderiv(_id, GL_COMPLETION_STATUS_KHR, &success); + return success == GL_TRUE; +} + +void Shader::submitCompile(std::initializer_list> shaders) { /* Allocate large enough array for source pointers and sizes (to avoid reallocating it for each of them) */ std::size_t maxSourceCount = 0; for(Shader& shader: shaders) { - CORRADE_ASSERT(shader._sources.size() > 1, "GL::Shader::compile(): no files added", false); + CORRADE_ASSERT(shader._sources.size() > 1, "GL::Shader::compile(): no files added", ); maxSourceCount = Math::max(shader._sources.size(), maxSourceCount); } /** @todo ArrayTuple/VLAs */ @@ -775,6 +788,10 @@ bool Shader::compile(std::initializer_list> shader /* Invoke (possibly parallel) compilation on all shaders */ for(Shader& shader: shaders) glCompileShader(shader._id); +} + +bool Shader::checkCompile(std::initializer_list> shaders) { + bool allSuccess = true; /* After compilation phase, check status of all shaders */ Int i = 1; diff --git a/src/Magnum/GL/Shader.h b/src/Magnum/GL/Shader.h index 99984dc643..1b481ef06b 100644 --- a/src/Magnum/GL/Shader.h +++ b/src/Magnum/GL/Shader.h @@ -521,6 +521,23 @@ class MAGNUM_GL_EXPORT Shader: public AbstractObject { */ static bool compile(std::initializer_list> shaders); + /** + * @brief Submit multiple shaders for compilation + * + * The operation is batched in a way that + * allows the driver to perform multiple compilations simultaneously + * (i.e. in multiple threads). + */ + static void submitCompile(std::initializer_list> shaders); + + /** + * @brief Check compilations status of multiple shaders and await completion + * + * Returns @cpp false @ce if compilation of any shader failed, + * @cpp true @ce if everything succeeded. + */ + static bool checkCompile(std::initializer_list> shaders); + /** * @brief Constructor * @param version Target version @@ -643,6 +660,25 @@ class MAGNUM_GL_EXPORT Shader: public AbstractObject { */ bool compile(); + /** + * @brief Submit shader for compilation + * + * Submits shader for compilation. + */ + void submitCompile(); + + /** + * @brief Check compilation status and await completion + * + */ + bool checkCompile(); + + /** + * @brief Non-blocking compilation status check + * + */ + bool isCompileFinished(); + private: void MAGNUM_GL_LOCAL addSourceImplementationDefault(std::string source); #if defined(CORRADE_TARGET_EMSCRIPTEN) && defined(__EMSCRIPTEN_PTHREADS__) diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 86504acad1..984546024c 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -31,7 +31,6 @@ #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" -#include "Magnum/GL/Shader.h" #include "Magnum/GL/Texture.h" #include "Magnum/Math/Color.h" #include "Magnum/Math/Matrix3.h" @@ -68,16 +67,11 @@ namespace { #endif } -template FlatGL::FlatGL(const Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , const UnsignedInt materialCount, const UnsignedInt drawCount - #endif -): - _flags{flags} - #ifndef MAGNUM_TARGET_GLES2 - , _materialCount{materialCount}, _drawCount{drawCount} - #endif -{ +template typename FlatGL::CompileState FlatGL::compile(Flags flags +#ifndef MAGNUM_TARGET_GLES2 +, UnsignedInt materialCount, UnsignedInt drawCount +#endif +) { #ifndef CORRADE_NO_ASSERT { const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || flags & Flag::Textured @@ -86,22 +80,22 @@ template FlatGL::FlatGL(const Flags flags #endif ; CORRADE_ASSERT(textureTransformationNotEnabledOrTextured, - "Shaders::FlatGL: texture transformation enabled but the shader is not textured", ); + "Shaders::FlatGL: texture transformation enabled but the shader is not textured", CompileState{NoCreate}); } #endif #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, - "Shaders::FlatGL: material count can't be zero", ); + "Shaders::FlatGL: material count can't be zero", CompileState{NoCreate}); CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, - "Shaders::FlatGL: draw count can't be zero", ); + "Shaders::FlatGL: draw count can't be zero", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags & Flag::TextureArrays) || flags & Flag::Textured || flags >= Flag::ObjectIdTexture, - "Shaders::FlatGL: texture arrays enabled but the shader is not textured", ); + "Shaders::FlatGL: texture arrays enabled but the shader is not textured", CompileState{NoCreate}); CORRADE_ASSERT(!(flags & Flag::UniformBuffers) || !(flags & Flag::TextureArrays) || flags >= (Flag::TextureArrays|Flag::TextureTransformation), - "Shaders::FlatGL: texture arrays require texture transformation enabled as well if uniform buffers are used", ); + "Shaders::FlatGL: texture arrays require texture transformation enabled as well if uniform buffers are used", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES @@ -195,9 +189,14 @@ template FlatGL::FlatGL(const Flags flags frag.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("Flat.frag")); - CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); + GL::Shader::submitCompile({vert, frag}); - attachShaders({vert, frag}); + CompileState cs{std::move(frag), std::move(vert), flags + #ifndef MAGNUM_TARGET_GLES2 + , materialCount, drawCount + #endif + }; + cs.attachShaders({cs._frag, cs._vert}); /* ES3 has this done in the shader directly and doesn't even provide bindFragmentDataLocation() */ @@ -206,53 +205,71 @@ template FlatGL::FlatGL(const Flags flags if(!context.isExtensionSupported(version)) #endif { - bindAttributeLocation(Position::Location, "position"); + cs.bindAttributeLocation(Position::Location, "position"); if(flags & Flag::Textured #ifndef MAGNUM_TARGET_GLES2 || flags >= Flag::ObjectIdTexture #endif ) - bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); + cs.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); if(flags & Flag::VertexColor) - bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ + cs.bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ #ifndef MAGNUM_TARGET_GLES2 if(flags & Flag::ObjectId) { - bindFragmentDataLocation(ColorOutput, "color"); - bindFragmentDataLocation(ObjectIdOutput, "objectId"); + cs.bindFragmentDataLocation(ColorOutput, "color"); + cs.bindFragmentDataLocation(ObjectIdOutput, "objectId"); } if(flags >= Flag::InstancedObjectId) - bindAttributeLocation(ObjectId::Location, "instanceObjectId"); + cs.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); #endif if(flags & Flag::InstancedTransformation) - bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); + cs.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); if(flags >= Flag::InstancedTextureOffset) - bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); + cs.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); } #endif - CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + cs.submitLink(); + + return cs; +} + +template FlatGL::FlatGL(CompileState&& cs) +: AbstractShaderProgram{static_cast(std::move(cs))}, + _flags(cs._flags), _materialCount{cs._materialCount}, _drawCount(cs._drawCount) { + + CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::checkCompile({cs._vert, cs._frag})); + CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); + + const GL::Context& context = GL::Context::current(); + + #ifndef MAGNUM_TARGET_GLES + const GL::Version version = context.supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); + #else + const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); + #endif #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) #endif { #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::UniformBuffers) { if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset"); } else #endif { _transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); - if(flags & Flag::TextureTransformation) + if(_flags & Flag::TextureTransformation) _textureMatrixUniform = uniformLocation("textureMatrix"); #ifndef MAGNUM_TARGET_GLES2 - if(flags & Flag::TextureArrays) + if(_flags & Flag::TextureArrays) _textureLayerUniform = uniformLocation("textureLayer"); #endif _colorUniform = uniformLocation("color"); - if(flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask"); + if(_flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask"); #ifndef MAGNUM_TARGET_GLES2 - if(flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId"); + if(_flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId"); #endif } } @@ -261,13 +278,13 @@ template FlatGL::FlatGL(const Flags flags if(!context.isExtensionSupported(version)) #endif { - if(flags & Flag::Textured) setUniform(uniformLocation("textureData"), TextureUnit); + if(_flags & Flag::Textured) setUniform(uniformLocation("textureData"), TextureUnit); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit); - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit); + if(_flags >= Flag::UniformBuffers) { setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding); setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding); - if(flags & Flag::TextureTransformation) + if(_flags & Flag::TextureTransformation) setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding); setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding); } @@ -277,22 +294,34 @@ template FlatGL::FlatGL(const Flags flags /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ #ifdef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::UniformBuffers) { /* Draw offset is zero by default */ } else #endif { setTransformationProjectionMatrix(MatrixTypeFor{Math::IdentityInit}); - if(flags & Flag::TextureTransformation) + if(_flags & Flag::TextureTransformation) setTextureMatrix(Matrix3{Math::IdentityInit}); /* Texture layer is zero by default */ setColor(Magnum::Color4{1.0f}); - if(flags & Flag::AlphaMask) setAlphaMask(0.5f); + if(_flags & Flag::AlphaMask) setAlphaMask(0.5f); /* Object ID is zero by default */ } #endif } +template FlatGL::FlatGL(Flags flags + #ifndef MAGNUM_TARGET_GLES2 + , UnsignedInt materialCount, UnsignedInt drawCount + #endif +): + #ifndef MAGNUM_TARGET_GLES2 + FlatGL(compile(flags, materialCount, drawCount)) + #else + FlatGL{compile(flags)} + #endif +{} + #ifndef MAGNUM_TARGET_GLES2 template FlatGL::FlatGL(const Flags flags): FlatGL{flags, 1, 1} {} #endif diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h index bd76a49c81..535b80cd38 100644 --- a/src/Magnum/Shaders/FlatGL.h +++ b/src/Magnum/Shaders/FlatGL.h @@ -32,6 +32,7 @@ #include "Magnum/DimensionTraits.h" #include "Magnum/GL/AbstractShaderProgram.h" +#include "Magnum/GL/Shader.h" #include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/visibility.h" @@ -602,6 +603,48 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: */ explicit FlatGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} + struct CompileState; + + explicit FlatGL(CompileState&& cs); + + static CompileState compile(Flags flags + #ifndef MAGNUM_TARGET_GLES2 + , UnsignedInt materialCount, UnsignedInt drawCount + #endif + ); + + struct CompileState : public GL::AbstractShaderProgram::CompileState { + friend CompileState FlatGL::compile(Flags + #ifndef MAGNUM_TARGET_GLES2 + , UnsignedInt, UnsignedInt + #endif + ); + friend FlatGL::FlatGL(CompileState&&); + + explicit CompileState(NoCreateT) noexcept: GL::AbstractShaderProgram::CompileState({NoCreate}), + _vert(NoCreate), _frag(NoCreate) {} + + CompileState(GL::Shader&& vert, GL::Shader&& frag, Flags flags + #ifndef MAGNUM_TARGET_GLES2 + , UnsignedInt materialCount, UnsignedInt drawCount + #endif + ) + : _vert(std::move(vert)), _frag(std::move(frag)), _flags(flags) + #ifndef MAGNUM_TARGET_GLES2 + ,_materialCount(materialCount), _drawCount(drawCount) + #endif + {} + + private: + GL::Shader _vert, _frag; + Flags _flags; + + #ifndef MAGNUM_TARGET_GLES2 + UnsignedInt _materialCount; + UnsignedInt _drawCount; + #endif + }; + /** @brief Copying is not allowed */ FlatGL(const FlatGL&) = delete; diff --git a/src/MagnumExternal/OpenGL/GL/flextGL.h b/src/MagnumExternal/OpenGL/GL/flextGL.h index f2f2bc72e7..ddc166c9cb 100644 --- a/src/MagnumExternal/OpenGL/GL/flextGL.h +++ b/src/MagnumExternal/OpenGL/GL/flextGL.h @@ -1523,7 +1523,7 @@ typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum /* GL_VERSION_4_5 */ -#define GL_CONTEXT_LOST 0x0507 +#define GL_CONTEXT_LOST 0x0507 #define GL_LOWER_LEFT 0x8CA1 #define GL_UPPER_LEFT 0x8CA2 #define GL_NEGATIVE_ONE_TO_ONE 0x935E @@ -1773,6 +1773,10 @@ typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum #define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285 +/* GL_KHR_parallel_shader_compile */ + +#define GL_COMPLETION_STATUS_KHR 0x91B1 + /* GL_NV_sample_locations */ #define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV 0x933D From 37b47f148c1fa133b859d5f1b564dfca482293f1 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Mon, 25 Jul 2022 16:29:33 +0300 Subject: [PATCH 02/27] Refactor FlatGL::CompileState --- src/Magnum/GL/AbstractShaderProgram.cpp | 4 -- src/Magnum/GL/AbstractShaderProgram.h | 19 +++----- src/Magnum/Shaders/FlatGL.cpp | 25 +++++----- src/Magnum/Shaders/FlatGL.h | 64 ++++++++++++------------- 4 files changed, 52 insertions(+), 60 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.cpp b/src/Magnum/GL/AbstractShaderProgram.cpp index 298da4d4a7..3714f7b249 100644 --- a/src/Magnum/GL/AbstractShaderProgram.cpp +++ b/src/Magnum/GL/AbstractShaderProgram.cpp @@ -649,10 +649,6 @@ bool AbstractShaderProgram::isLinkFinished() { return success == GL_TRUE; } -bool AbstractShaderProgram::CompileState::isLinkFinished() { - return AbstractShaderProgram::isLinkFinished(); -} - void AbstractShaderProgram::cleanLogImplementationNoOp(std::string&) {} #if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES) diff --git a/src/Magnum/GL/AbstractShaderProgram.h b/src/Magnum/GL/AbstractShaderProgram.h index 89b42ea0ed..54db33c864 100644 --- a/src/Magnum/GL/AbstractShaderProgram.h +++ b/src/Magnum/GL/AbstractShaderProgram.h @@ -449,8 +449,6 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { friend Implementation::ShaderProgramState; public: - struct CompileState; - #ifndef MAGNUM_TARGET_GLES2 /** * @brief Buffer mode for transform feedback @@ -1260,6 +1258,12 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { AbstractShaderProgram& dispatchCompute(const Vector3ui& workgroupCount); #endif + /** + * @brief Non-blocking linking status check + * + */ + bool isLinkFinished(); + protected: /** * @brief Link the shaders @@ -1487,12 +1491,6 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { */ bool checkLink(); - /** - * @brief Non-blocking linking status check - * - */ - bool isLinkFinished(); - /** * @brief Get uniform location * @param name Uniform name @@ -1769,11 +1767,6 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { #endif }; -struct AbstractShaderProgram::CompileState : public AbstractShaderProgram { - using AbstractShaderProgram::AbstractShaderProgram; - bool isLinkFinished(); -}; - }} #endif diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 984546024c..152104c07f 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -191,8 +191,8 @@ template typename FlatGL::CompileState FlatG GL::Shader::submitCompile({vert, frag}); - CompileState cs{std::move(frag), std::move(vert), flags - #ifndef MAGNUM_TARGET_GLES2 + CompileState cs{std::move(frag), std::move(vert), version, flags + #ifndef MAGNUM_TARGET_GLES , materialCount, drawCount #endif }; @@ -235,19 +235,12 @@ template typename FlatGL::CompileState FlatG } template FlatGL::FlatGL(CompileState&& cs) -: AbstractShaderProgram{static_cast(std::move(cs))}, - _flags(cs._flags), _materialCount{cs._materialCount}, _drawCount(cs._drawCount) { - +: FlatGL{static_cast(std::move(cs))} { CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::checkCompile({cs._vert, cs._frag})); CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); const GL::Context& context = GL::Context::current(); - - #ifndef MAGNUM_TARGET_GLES - const GL::Version version = context.supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); - #else - const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); - #endif + const GL::Version version = cs._version; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) @@ -322,6 +315,16 @@ template FlatGL::FlatGL(Flags flags #endif {} +template FlatGL::FlatGL(NoInitT, Flags flags + #ifndef MAGNUM_TARGET_GLES2 + , UnsignedInt materialCount, UnsignedInt drawCount + #endif +) : GL::AbstractShaderProgram{}, _flags(flags), + #ifndef MAGNUM_TARGET_GLES2 + _materialCount(materialCount), _drawCount(drawCount) + #endif +{} + #ifndef MAGNUM_TARGET_GLES2 template FlatGL::FlatGL(const Flags flags): FlatGL{flags, 1, 1} {} #endif diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h index 535b80cd38..38070f0799 100644 --- a/src/Magnum/Shaders/FlatGL.h +++ b/src/Magnum/Shaders/FlatGL.h @@ -613,38 +613,6 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: #endif ); - struct CompileState : public GL::AbstractShaderProgram::CompileState { - friend CompileState FlatGL::compile(Flags - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt, UnsignedInt - #endif - ); - friend FlatGL::FlatGL(CompileState&&); - - explicit CompileState(NoCreateT) noexcept: GL::AbstractShaderProgram::CompileState({NoCreate}), - _vert(NoCreate), _frag(NoCreate) {} - - CompileState(GL::Shader&& vert, GL::Shader&& frag, Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt materialCount, UnsignedInt drawCount - #endif - ) - : _vert(std::move(vert)), _frag(std::move(frag)), _flags(flags) - #ifndef MAGNUM_TARGET_GLES2 - ,_materialCount(materialCount), _drawCount(drawCount) - #endif - {} - - private: - GL::Shader _vert, _frag; - Flags _flags; - - #ifndef MAGNUM_TARGET_GLES2 - UnsignedInt _materialCount; - UnsignedInt _drawCount; - #endif - }; - /** @brief Copying is not allowed */ FlatGL(const FlatGL&) = delete; @@ -1053,6 +1021,17 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: } #endif + protected: + /** + * @brief Construct without running shader compilation and linking + * + */ + FlatGL(NoInitT, Flags flags + #ifndef MAGNUM_TARGET_GLES2 + , UnsignedInt materialCount, UnsignedInt drawCount + #endif + ); + private: /* Prevent accidentally calling irrelevant functions */ #ifndef MAGNUM_TARGET_GLES @@ -1081,6 +1060,27 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: #endif }; +template class FlatGL::CompileState : public FlatGL { +private: + friend class FlatGL; + using FlatGL::FlatGL; + + CompileState(NoCreateT) : FlatGL(NoCreate), _vert{NoCreate}, _frag{NoCreate} {} + + CompileState(GL::Shader&& vert, GL::Shader&& frag, GL::Version version, Flags flags + #ifndef MAGNUM_TARGET_GLES2 + , UnsignedInt materialCount, UnsignedInt drawCount + #endif + ) : FlatGL(NoInit, flags + #ifndef MAGNUM_TARGET_GLES2 + , materialCount, drawCount + #endif + ), _vert(std::move(vert)), _frag(std::move(frag)), _version(version) {} + + GL::Shader _vert, _frag; + GL::Version _version; +}; + /** @brief 2D flat OpenGL shader @m_since_latest From 66015a2f4e07fe6a05bae7b3495e4c2dbc730ca9 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Mon, 25 Jul 2022 16:45:38 +0300 Subject: [PATCH 03/27] Move shader compilation/linking to member functions --- src/Magnum/GL/AbstractShaderProgram.cpp | 81 +++++++--------- src/Magnum/GL/AbstractShaderProgram.h | 20 ---- src/Magnum/GL/Shader.cpp | 120 ++++++++++-------------- src/Magnum/GL/Shader.h | 17 ---- src/Magnum/Shaders/FlatGL.cpp | 10 +- 5 files changed, 90 insertions(+), 158 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.cpp b/src/Magnum/GL/AbstractShaderProgram.cpp index 3714f7b249..39e6ad7c67 100644 --- a/src/Magnum/GL/AbstractShaderProgram.cpp +++ b/src/Magnum/GL/AbstractShaderProgram.cpp @@ -585,61 +585,48 @@ void AbstractShaderProgram::transformFeedbackVaryingsImplementationDanglingWorka bool AbstractShaderProgram::link() { return link({*this}); } -bool AbstractShaderProgram::link(std::initializer_list> shaders) { - submitLink(shaders); - return checkLink(shaders); +void AbstractShaderProgram::submitLink() { + glLinkProgram(_id); } -void AbstractShaderProgram::submitLink() { submitLink({*this}); } +bool AbstractShaderProgram::checkLink() { + GLint success, logLength; + glGetProgramiv(_id, GL_LINK_STATUS, &success); + glGetProgramiv(_id, GL_INFO_LOG_LENGTH, &logLength); + + /* Error or warning message. The string is returned null-terminated, + strip the \0 at the end afterwards. */ + std::string message(logLength, '\n'); + if(message.size() > 1) + glGetProgramInfoLog(_id, message.size(), nullptr, &message[0]); + message.resize(Math::max(logLength, 1)-1); -bool AbstractShaderProgram::checkLink() { return checkLink({*this}); } + /* Some drivers are chatty and can't keep shut when there's nothing to + be said, handle that as well. */ + Context::current().state().shaderProgram.cleanLogImplementation(message); -void AbstractShaderProgram::submitLink(std::initializer_list> shaders) { - /* Invoke (possibly parallel) linking on all shaders */ - for(AbstractShaderProgram& shader: shaders) glLinkProgram(shader._id); -} + /** @todo update log messages */ -bool AbstractShaderProgram::checkLink(std::initializer_list> shaders) { - bool allSuccess = true; + /* Show error log */ + if(!success) { + Error out{Debug::Flag::NoNewlineAtTheEnd}; + out << "GL::AbstractShaderProgram::link(): linking"; + out << "failed with the following message:" << Debug::newline << message; - /* After linking phase, check status of all shaders */ - Int i = 1; - for(AbstractShaderProgram& shader: shaders) { - GLint success, logLength; - glGetProgramiv(shader._id, GL_LINK_STATUS, &success); - glGetProgramiv(shader._id, GL_INFO_LOG_LENGTH, &logLength); - - /* Error or warning message. The string is returned null-terminated, - strip the \0 at the end afterwards. */ - std::string message(logLength, '\n'); - if(message.size() > 1) - glGetProgramInfoLog(shader._id, message.size(), nullptr, &message[0]); - message.resize(Math::max(logLength, 1)-1); - - /* Some drivers are chatty and can't keep shut when there's nothing to - be said, handle that as well. */ - Context::current().state().shaderProgram.cleanLogImplementation(message); - - /* Show error log */ - if(!success) { - Error out{Debug::Flag::NoNewlineAtTheEnd}; - out << "GL::AbstractShaderProgram::link(): linking"; - if(shaders.size() != 1) out << "of shader" << i; - out << "failed with the following message:" << Debug::newline << message; - - /* Or just warnings, if any */ - } else if(!message.empty()) { - Warning out{Debug::Flag::NoNewlineAtTheEnd}; - out << "GL::AbstractShaderProgram::link(): linking"; - if(shaders.size() != 1) out << "of shader" << i; - out << "succeeded with the following message:" << Debug::newline << message; - } - - /* Success of all depends on each of them */ - allSuccess = allSuccess && success; - ++i; + /* Or just warnings, if any */ + } else if(!message.empty()) { + Warning out{Debug::Flag::NoNewlineAtTheEnd}; + out << "GL::AbstractShaderProgram::link(): linking"; + out << "succeeded with the following message:" << Debug::newline << message; } + return success; +} + +bool AbstractShaderProgram::link(std::initializer_list> shaders) { + for(AbstractShaderProgram& shader: shaders) shader.submitLink(); + bool allSuccess = true; + for(AbstractShaderProgram& shader: shaders) allSuccess &= shader.checkLink(); return allSuccess; } diff --git a/src/Magnum/GL/AbstractShaderProgram.h b/src/Magnum/GL/AbstractShaderProgram.h index 54db33c864..60d2f13861 100644 --- a/src/Magnum/GL/AbstractShaderProgram.h +++ b/src/Magnum/GL/AbstractShaderProgram.h @@ -1280,26 +1280,6 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { */ static bool link(std::initializer_list> shaders); - /** - * @brief Submit shaders for linking - * - * The operation is batched in a - * way that allows the driver to link multiple shaders simultaneously - * (i.e. in multiple threads). - * - */ - static void submitLink(std::initializer_list> shaders); - - /** - * @brief Check linking status of shaders and await completion - * - * Returns @cpp false @ce if linking of any shader failed, @cpp true @ce - * if everything succeeded. Linker message (if any) is printed to error - * output. - * - */ - static bool checkLink(std::initializer_list> shaders); - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) /** * @brief Allow retrieving program binary diff --git a/src/Magnum/GL/Shader.cpp b/src/Magnum/GL/Shader.cpp index 1b1441361b..ec25103566 100644 --- a/src/Magnum/GL/Shader.cpp +++ b/src/Magnum/GL/Shader.cpp @@ -749,91 +749,71 @@ Shader& Shader::addFile(const std::string& filename) { bool Shader::compile() { return compile({*this}); } -void Shader::submitCompile() { submitCompile({*this}); } +void Shader::submitCompile() { + CORRADE_ASSERT(_sources.size() > 1, "GL::Shader::compile(): no files added", ); -bool Shader::checkCompile() { return checkCompile({*this}); } + /** @todo ArrayTuple/VLAs */ + Containers::Array pointers(_sources.size()); + Containers::Array sizes(_sources.size()); -bool Shader::compile(std::initializer_list> shaders) { - submitCompile(shaders); - return checkCompile(shaders); -} + /* Upload sources of all shaders */ + for(std::size_t i = 0; i != _sources.size(); ++i) { + pointers[i] = static_cast(_sources[i].data()); + sizes[i] = _sources[i].size(); + } -bool Shader::isCompileFinished() { - GLint success; - glGetShaderiv(_id, GL_COMPLETION_STATUS_KHR, &success); - return success == GL_TRUE; + glShaderSource(_id, _sources.size(), pointers, sizes); + glCompileShader(_id); } -void Shader::submitCompile(std::initializer_list> shaders) { - /* Allocate large enough array for source pointers and sizes (to avoid - reallocating it for each of them) */ - std::size_t maxSourceCount = 0; - for(Shader& shader: shaders) { - CORRADE_ASSERT(shader._sources.size() > 1, "GL::Shader::compile(): no files added", ); - maxSourceCount = Math::max(shader._sources.size(), maxSourceCount); - } - /** @todo ArrayTuple/VLAs */ - Containers::Array pointers(maxSourceCount); - Containers::Array sizes(maxSourceCount); +bool Shader::checkCompile() { /* After compilation phase, check status of all shaders */ + GLint success, logLength; + glGetShaderiv(_id, GL_COMPILE_STATUS, &success); + glGetShaderiv(_id, GL_INFO_LOG_LENGTH, &logLength); - /* Upload sources of all shaders */ - for(Shader& shader: shaders) { - for(std::size_t i = 0; i != shader._sources.size(); ++i) { - pointers[i] = static_cast(shader._sources[i].data()); - sizes[i] = shader._sources[i].size(); - } + /* Error or warning message. The string is returned null-terminated, + strip the \0 at the end afterwards. */ + std::string message(logLength, '\0'); + if(message.size() > 1) + glGetShaderInfoLog(_id, message.size(), nullptr, &message[0]); + message.resize(Math::max(logLength, 1)-1); - glShaderSource(shader._id, shader._sources.size(), pointers, sizes); - } + /* Some drivers are chatty and can't keep shut when there's nothing to + be said, handle that as well. */ + Context::current().state().shader.cleanLogImplementation(message); - /* Invoke (possibly parallel) compilation on all shaders */ - for(Shader& shader: shaders) glCompileShader(shader._id); -} + /** @todo update log messages */ -bool Shader::checkCompile(std::initializer_list> shaders) { - bool allSuccess = true; + /* Show error log */ + if(!success) { + Error out{Debug::Flag::NoNewlineAtTheEnd}; + out << "GL::Shader::compile(): compilation of" << shaderName(_type) << "shader"; + out << "failed with the following message:" << Debug::newline << message; - /* After compilation phase, check status of all shaders */ - Int i = 1; - for(Shader& shader: shaders) { - GLint success, logLength; - glGetShaderiv(shader._id, GL_COMPILE_STATUS, &success); - glGetShaderiv(shader._id, GL_INFO_LOG_LENGTH, &logLength); - - /* Error or warning message. The string is returned null-terminated, - strip the \0 at the end afterwards. */ - std::string message(logLength, '\0'); - if(message.size() > 1) - glGetShaderInfoLog(shader._id, message.size(), nullptr, &message[0]); - message.resize(Math::max(logLength, 1)-1); - - /* Some drivers are chatty and can't keep shut when there's nothing to - be said, handle that as well. */ - Context::current().state().shader.cleanLogImplementation(message); - - /* Show error log */ - if(!success) { - Error out{Debug::Flag::NoNewlineAtTheEnd}; - out << "GL::Shader::compile(): compilation of" << shaderName(shader._type) << "shader"; - if(shaders.size() != 1) out << i; - out << "failed with the following message:" << Debug::newline << message; - - /* Or just warnings, if any */ - } else if(!message.empty()) { - Warning out{Debug::Flag::NoNewlineAtTheEnd}; - out << "GL::Shader::compile(): compilation of" << shaderName(shader._type) << "shader"; - if(shaders.size() != 1) out << i; - out << "succeeded with the following message:" << Debug::newline << message; - } - - /* Success of all depends on each of them */ - allSuccess = allSuccess && success; - ++i; + /* Or just warnings, if any */ + } else if(!message.empty()) { + Warning out{Debug::Flag::NoNewlineAtTheEnd}; + out << "GL::Shader::compile(): compilation of" << shaderName(_type) << "shader"; + out << "succeeded with the following message:" << Debug::newline << message; } + return success; +} + +bool Shader::compile(std::initializer_list> shaders) { + /* Invoke (possibly parallel) compilation on all shaders */ + for(Shader& shader: shaders) shader.submitCompile(); + bool allSuccess = true; + for(Shader& shader: shaders) allSuccess &= shader.checkCompile(); return allSuccess; } +bool Shader::isCompileFinished() { + GLint success; + glGetShaderiv(_id, GL_COMPLETION_STATUS_KHR, &success); + return success == GL_TRUE; +} + void Shader::cleanLogImplementationNoOp(std::string&) {} #if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES) diff --git a/src/Magnum/GL/Shader.h b/src/Magnum/GL/Shader.h index 1b481ef06b..9d61d2a40b 100644 --- a/src/Magnum/GL/Shader.h +++ b/src/Magnum/GL/Shader.h @@ -521,23 +521,6 @@ class MAGNUM_GL_EXPORT Shader: public AbstractObject { */ static bool compile(std::initializer_list> shaders); - /** - * @brief Submit multiple shaders for compilation - * - * The operation is batched in a way that - * allows the driver to perform multiple compilations simultaneously - * (i.e. in multiple threads). - */ - static void submitCompile(std::initializer_list> shaders); - - /** - * @brief Check compilations status of multiple shaders and await completion - * - * Returns @cpp false @ce if compilation of any shader failed, - * @cpp true @ce if everything succeeded. - */ - static bool checkCompile(std::initializer_list> shaders); - /** * @brief Constructor * @param version Target version diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 152104c07f..650c583c7d 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -189,7 +189,8 @@ template typename FlatGL::CompileState FlatG frag.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("Flat.frag")); - GL::Shader::submitCompile({vert, frag}); + vert.submitCompile(); + frag.submitCompile(); CompileState cs{std::move(frag), std::move(vert), version, flags #ifndef MAGNUM_TARGET_GLES @@ -236,7 +237,8 @@ template typename FlatGL::CompileState FlatG template FlatGL::FlatGL(CompileState&& cs) : FlatGL{static_cast(std::move(cs))} { - CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::checkCompile({cs._vert, cs._frag})); + CORRADE_INTERNAL_ASSERT_OUTPUT(cs._vert.checkCompile()); + CORRADE_INTERNAL_ASSERT_OUTPUT(cs._frag.checkCompile()); CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); const GL::Context& context = GL::Context::current(); @@ -319,10 +321,10 @@ template FlatGL::FlatGL(NoInitT, Flags flags #ifndef MAGNUM_TARGET_GLES2 , UnsignedInt materialCount, UnsignedInt drawCount #endif -) : GL::AbstractShaderProgram{}, _flags(flags), +) : GL::AbstractShaderProgram{}, _flags(flags), #ifndef MAGNUM_TARGET_GLES2 _materialCount(materialCount), _drawCount(drawCount) - #endif + #endif {} #ifndef MAGNUM_TARGET_GLES2 From 8bcd04a1e2187b072c73e272b9c49637e3aedffa Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Wed, 27 Jul 2022 09:22:20 +0300 Subject: [PATCH 04/27] Refactor FlatGL::CompileState --- src/Magnum/GL/AbstractShaderProgram.cpp | 2 +- src/Magnum/GL/Shader.cpp | 2 +- src/Magnum/Shaders/FlatGL.cpp | 26 +++++++++--------------- src/Magnum/Shaders/FlatGL.h | 27 ++++++------------------- 4 files changed, 17 insertions(+), 40 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.cpp b/src/Magnum/GL/AbstractShaderProgram.cpp index 39e6ad7c67..a246694d58 100644 --- a/src/Magnum/GL/AbstractShaderProgram.cpp +++ b/src/Magnum/GL/AbstractShaderProgram.cpp @@ -626,7 +626,7 @@ bool AbstractShaderProgram::checkLink() { bool AbstractShaderProgram::link(std::initializer_list> shaders) { for(AbstractShaderProgram& shader: shaders) shader.submitLink(); bool allSuccess = true; - for(AbstractShaderProgram& shader: shaders) allSuccess &= shader.checkLink(); + for(AbstractShaderProgram& shader: shaders) allSuccess = allSuccess && shader.checkLink(); return allSuccess; } diff --git a/src/Magnum/GL/Shader.cpp b/src/Magnum/GL/Shader.cpp index ec25103566..b4bcf94ee6 100644 --- a/src/Magnum/GL/Shader.cpp +++ b/src/Magnum/GL/Shader.cpp @@ -804,7 +804,7 @@ bool Shader::compile(std::initializer_list> shader /* Invoke (possibly parallel) compilation on all shaders */ for(Shader& shader: shaders) shader.submitCompile(); bool allSuccess = true; - for(Shader& shader: shaders) allSuccess &= shader.checkCompile(); + for(Shader& shader: shaders) allSuccess = allSuccess && shader.checkCompile(); return allSuccess; } diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 650c583c7d..91a052fd15 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -192,12 +192,14 @@ template typename FlatGL::CompileState FlatG vert.submitCompile(); frag.submitCompile(); - CompileState cs{std::move(frag), std::move(vert), version, flags - #ifndef MAGNUM_TARGET_GLES - , materialCount, drawCount + FlatGL out{NoInit}; + out._flags = flags; + #ifndef MAGNUM_TARGET_GLES2 + out._materialCount = materialCount; + out._drawCount = drawCount; #endif - }; - cs.attachShaders({cs._frag, cs._vert}); + + out.attachShaders({vert, frag}); /* ES3 has this done in the shader directly and doesn't even provide bindFragmentDataLocation() */ @@ -230,9 +232,9 @@ template typename FlatGL::CompileState FlatG } #endif - cs.submitLink(); + out.submitLink(); - return cs; + return CompileState{std::move(out), std::move()}; } template FlatGL::FlatGL(CompileState&& cs) @@ -317,16 +319,6 @@ template FlatGL::FlatGL(Flags flags #endif {} -template FlatGL::FlatGL(NoInitT, Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt materialCount, UnsignedInt drawCount - #endif -) : GL::AbstractShaderProgram{}, _flags(flags), - #ifndef MAGNUM_TARGET_GLES2 - _materialCount(materialCount), _drawCount(drawCount) - #endif -{} - #ifndef MAGNUM_TARGET_GLES2 template FlatGL::FlatGL(const Flags flags): FlatGL{flags, 1, 1} {} #endif diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h index 38070f0799..2278fa18c6 100644 --- a/src/Magnum/Shaders/FlatGL.h +++ b/src/Magnum/Shaders/FlatGL.h @@ -1021,18 +1021,10 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: } #endif - protected: - /** - * @brief Construct without running shader compilation and linking - * - */ - FlatGL(NoInitT, Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt materialCount, UnsignedInt drawCount - #endif - ); - private: + /* Creates the GL shader program object but nothing else. Internal, used by compile(). */ + explicit FlatGL(NoInitT) {} + /* Prevent accidentally calling irrelevant functions */ #ifndef MAGNUM_TARGET_GLES using GL::AbstractShaderProgram::drawTransformFeedback; @@ -1063,19 +1055,12 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: template class FlatGL::CompileState : public FlatGL { private: friend class FlatGL; - using FlatGL::FlatGL; + using FlatGL::isLinkFinished; CompileState(NoCreateT) : FlatGL(NoCreate), _vert{NoCreate}, _frag{NoCreate} {} - CompileState(GL::Shader&& vert, GL::Shader&& frag, GL::Version version, Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt materialCount, UnsignedInt drawCount - #endif - ) : FlatGL(NoInit, flags - #ifndef MAGNUM_TARGET_GLES2 - , materialCount, drawCount - #endif - ), _vert(std::move(vert)), _frag(std::move(frag)), _version(version) {} + 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; From 89582ef54d142333e76fef94aee242a1f3cda181 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Wed, 27 Jul 2022 10:06:08 +0300 Subject: [PATCH 05/27] Update doc comments --- src/Magnum/GL/AbstractShaderProgram.h | 28 ++++++++++++++++----------- src/Magnum/GL/Shader.h | 19 ++++++++++-------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.h b/src/Magnum/GL/AbstractShaderProgram.h index 60d2f13861..48d1b2b17b 100644 --- a/src/Magnum/GL/AbstractShaderProgram.h +++ b/src/Magnum/GL/AbstractShaderProgram.h @@ -1265,18 +1265,13 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { bool isLinkFinished(); protected: - /** - * @brief Link the shaders + /** @brief Link the shaders * + * Calls @ref submitLink() on all shaders first, then @ref checkLink(). * Returns @cpp false @ce if linking of any shader failed, @cpp true @ce - * if everything succeeded. Linker message (if any) is printed to error - * output. All attached shaders must be compiled with - * @ref Shader::compile() before linking. The operation is batched in a + * if everything succeeded. The operation is batched in a * way that allows the driver to link multiple shaders simultaneously * (i.e. in multiple threads). - * @see @fn_gl_keyword{LinkProgram}, @fn_gl_keyword{GetProgram} with - * @def_gl{LINK_STATUS} and @def_gl{INFO_LOG_LENGTH}, - * @fn_gl_keyword{GetProgramInfoLog} */ static bool link(std::initializer_list> shaders); @@ -1452,22 +1447,33 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { /** * @brief Link the shader * - * Links single shader. If possible, prefer to link multiple shaders - * at once using @ref link(std::initializer_list>) + * Calls @ref submitLink(), then @ref checkLink(). + * If possible, prefer to link multiple shaders at once using + * @ref link(std::initializer_list>) * for improved performance, see its documentation for more * information. */ bool link(); /** - * @brief Submit single shader for linking + * @brief Submit for linking + * + * The attached shaders must be compiled with @ref Shader::compile() before linking. * + * @see @fn_gl_keyword{LinkProgram} */ void submitLink(); /** * @brief Check link status and await completion * + * 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 + * @def_gl{LINK_STATUS} and @def_gl{INFO_LOG_LENGTH}, + * @fn_gl_keyword{GetProgramInfoLog} */ bool checkLink(); diff --git a/src/Magnum/GL/Shader.h b/src/Magnum/GL/Shader.h index 9d61d2a40b..af7065c762 100644 --- a/src/Magnum/GL/Shader.h +++ b/src/Magnum/GL/Shader.h @@ -510,14 +510,11 @@ class MAGNUM_GL_EXPORT Shader: public AbstractObject { /** * @brief Compile multiple shaders simultaneously * + * Calls @ref submitCompile() on all shaders first, then @ref checkCompile(). * Returns @cpp false @ce if compilation of any shader failed, - * @cpp true @ce if everything succeeded. Compiler messages (if any) - * are printed to error output. The operation is batched in a way that + * @cpp true @ce if everything succeeded. The operation is batched in a way that * allows the driver to perform multiple compilations simultaneously * (i.e. in multiple threads). - * @see @fn_gl_keyword{ShaderSource}, @fn_gl_keyword{CompileShader}, - * @fn_gl_keyword{GetShader} with @def_gl{COMPILE_STATUS} and - * @def_gl{INFO_LOG_LENGTH}, @fn_gl_keyword{GetShaderInfoLog} */ static bool compile(std::initializer_list> shaders); @@ -636,8 +633,9 @@ class MAGNUM_GL_EXPORT Shader: public AbstractObject { /** * @brief Compile shader * - * Compiles single shader. Prefer to compile multiple shaders at once - * using @ref compile(std::initializer_list>) + * Calls @ref submitCompile(), then @ref checkCompile(). + * Prefer to compile multiple shaders at once using + * @ref compile(std::initializer_list>) * for improved performance, see its documentation for more * information. */ @@ -646,13 +644,18 @@ class MAGNUM_GL_EXPORT Shader: public AbstractObject { /** * @brief Submit shader for compilation * - * Submits shader for compilation. + * @see @fn_gl_keyword{ShaderSource}, @fn_gl_keyword{CompileShader} */ void submitCompile(); /** * @brief Check compilation status and await completion * + * Returns @cpp false @ce if compilation of failed, @cpp true @ce on success. + * This function must be called only after @ref submitCompile(). + * + * @see @fn_gl_keyword{GetShader} with @def_gl{COMPILE_STATUS} and + * @def_gl{INFO_LOG_LENGTH}, @fn_gl_keyword{GetShaderInfoLog} */ bool checkCompile(); From 05d49d666eeb75e49f0668b17eeded3401df639b Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Wed, 27 Jul 2022 11:28:02 +0300 Subject: [PATCH 06/27] Implement completion status fallback & fixes --- src/Magnum/GL/AbstractShaderProgram.cpp | 16 +++++++------- src/Magnum/GL/AbstractShaderProgram.h | 2 ++ .../GL/Implementation/ShaderProgramState.cpp | 7 +++++++ .../GL/Implementation/ShaderProgramState.h | 1 + src/Magnum/GL/Implementation/ShaderState.cpp | 12 +++++++---- src/Magnum/GL/Implementation/ShaderState.h | 1 + src/Magnum/GL/Shader.cpp | 16 +++++++------- src/Magnum/GL/Shader.h | 2 ++ src/Magnum/Shaders/FlatGL.cpp | 21 +++++++++++-------- src/Magnum/Shaders/FlatGL.h | 10 +++++---- 10 files changed, 57 insertions(+), 31 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.cpp b/src/Magnum/GL/AbstractShaderProgram.cpp index a246694d58..c551d876bc 100644 --- a/src/Magnum/GL/AbstractShaderProgram.cpp +++ b/src/Magnum/GL/AbstractShaderProgram.cpp @@ -605,19 +605,17 @@ bool AbstractShaderProgram::checkLink() { be said, handle that as well. */ Context::current().state().shaderProgram.cleanLogImplementation(message); - /** @todo update log messages */ - /* Show error log */ if(!success) { Error out{Debug::Flag::NoNewlineAtTheEnd}; - out << "GL::AbstractShaderProgram::link(): linking"; - out << "failed with the following message:" << Debug::newline << message; + out << "GL::AbstractShaderProgram::link(): linking failed with the following message:" + << Debug::newline << message; /* Or just warnings, if any */ } else if(!message.empty()) { Warning out{Debug::Flag::NoNewlineAtTheEnd}; - out << "GL::AbstractShaderProgram::link(): linking"; - out << "succeeded with the following message:" << Debug::newline << message; + out << "GL::AbstractShaderProgram::link(): linking succeeded with the following message:" + << Debug::newline << message; } return success; @@ -632,7 +630,7 @@ bool AbstractShaderProgram::link(std::initializer_list name) { const GLint location = glGetUniformLocation(_id, name); if(location == -1) diff --git a/src/Magnum/GL/AbstractShaderProgram.h b/src/Magnum/GL/AbstractShaderProgram.h index 48d1b2b17b..b6319cef83 100644 --- a/src/Magnum/GL/AbstractShaderProgram.h +++ b/src/Magnum/GL/AbstractShaderProgram.h @@ -1692,6 +1692,8 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { static MAGNUM_GL_LOCAL void cleanLogImplementationAngle(std::string& message); #endif + static MAGNUM_GL_LOCAL void completionStatusImplementationFallback(GLuint, GLenum, GLint*); + MAGNUM_GL_LOCAL static void use(GLuint id); void use(); diff --git a/src/Magnum/GL/Implementation/ShaderProgramState.cpp b/src/Magnum/GL/Implementation/ShaderProgramState.cpp index 1e31255602..9799fc0874 100644 --- a/src/Magnum/GL/Implementation/ShaderProgramState.cpp +++ b/src/Magnum/GL/Implementation/ShaderProgramState.cpp @@ -78,6 +78,13 @@ ShaderProgramState::ShaderProgramState(Context& context, Containers::StaticArray cleanLogImplementation = &AbstractShaderProgram::cleanLogImplementationNoOp; } + if(context.isExtensionSupported()) { + extensions[Extensions::KHR::parallel_shader_compile::Index] = Extensions::KHR::parallel_shader_compile::string(); + completionStatusImplementation = glGetProgramiv; + } else { + completionStatusImplementation = &AbstractShaderProgram::completionStatusImplementationFallback; + } + #ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/GL/Implementation/ShaderProgramState.h b/src/Magnum/GL/Implementation/ShaderProgramState.h index 01f131b8fa..e057e5aad0 100644 --- a/src/Magnum/GL/Implementation/ShaderProgramState.h +++ b/src/Magnum/GL/Implementation/ShaderProgramState.h @@ -47,6 +47,7 @@ struct ShaderProgramState { void(AbstractShaderProgram::*transformFeedbackVaryingsImplementation)(Containers::ArrayView, AbstractShaderProgram::TransformFeedbackBufferMode); #endif void(*cleanLogImplementation)(std::string&); + void(*completionStatusImplementation)(GLuint, GLenum, GLint* value); #ifndef MAGNUM_TARGET_WEBGL void(APIENTRY *uniform1fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); diff --git a/src/Magnum/GL/Implementation/ShaderState.cpp b/src/Magnum/GL/Implementation/ShaderState.cpp index ffc0c2f1e1..17758a8013 100644 --- a/src/Magnum/GL/Implementation/ShaderState.cpp +++ b/src/Magnum/GL/Implementation/ShaderState.cpp @@ -31,12 +31,13 @@ #include "Magnum/GL/Context.h" #include "Magnum/GL/Shader.h" +#include "Magnum/GL/Extensions.h" namespace Magnum { namespace GL { namespace Implementation { using namespace Containers::Literals; -ShaderState::ShaderState(Context& context, Containers::StaticArrayView): +ShaderState::ShaderState(Context& context, Containers::StaticArrayView extensions): maxVertexOutputComponents{}, maxFragmentInputComponents{}, #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) maxTessellationControlInputComponents{}, maxTessellationControlOutputComponents{}, maxTessellationControlTotalOutputComponents{}, maxTessellationEvaluationInputComponents{}, maxTessellationEvaluationOutputComponents{}, maxGeometryInputComponents{}, maxGeometryOutputComponents{}, maxGeometryTotalOutputComponents{}, maxAtomicCounterBuffers{}, maxCombinedAtomicCounterBuffers{}, maxAtomicCounters{}, maxCombinedAtomicCounters{}, maxImageUniforms{}, maxCombinedImageUniforms{}, maxShaderStorageBlocks{}, maxCombinedShaderStorageBlocks{}, @@ -68,9 +69,12 @@ ShaderState::ShaderState(Context& context, Containers::StaticArrayView(context); + if(context.isExtensionSupported()) { + extensions[Extensions::KHR::parallel_shader_compile::Index] = Extensions::KHR::parallel_shader_compile::string(); + completionStatusImplementation = glGetShaderiv; + } else { + completionStatusImplementation = &Shader::completionStatusImplementationFallback; + } } }}} diff --git a/src/Magnum/GL/Implementation/ShaderState.h b/src/Magnum/GL/Implementation/ShaderState.h index 3eef9f0b58..caddd741d3 100644 --- a/src/Magnum/GL/Implementation/ShaderState.h +++ b/src/Magnum/GL/Implementation/ShaderState.h @@ -53,6 +53,7 @@ struct ShaderState { void(Shader::*addSourceImplementation)(std::string); void(*cleanLogImplementation)(std::string&); + void(*completionStatusImplementation)(GLuint, GLenum, GLint* value); GLint maxVertexOutputComponents, maxFragmentInputComponents; diff --git a/src/Magnum/GL/Shader.cpp b/src/Magnum/GL/Shader.cpp index b4bcf94ee6..8b7bbb98bf 100644 --- a/src/Magnum/GL/Shader.cpp +++ b/src/Magnum/GL/Shader.cpp @@ -782,19 +782,17 @@ bool Shader::checkCompile() { /* After compilation phase, check status of all sh be said, handle that as well. */ Context::current().state().shader.cleanLogImplementation(message); - /** @todo update log messages */ - /* Show error log */ if(!success) { Error out{Debug::Flag::NoNewlineAtTheEnd}; - out << "GL::Shader::compile(): compilation of" << shaderName(_type) << "shader"; - out << "failed with the following message:" << Debug::newline << message; + out << "GL::Shader::compile(): compilation of" << shaderName(_type) << "shader" + << "failed with the following message:" << Debug::newline << message; /* Or just warnings, if any */ } else if(!message.empty()) { Warning out{Debug::Flag::NoNewlineAtTheEnd}; - out << "GL::Shader::compile(): compilation of" << shaderName(_type) << "shader"; - out << "succeeded with the following message:" << Debug::newline << message; + out << "GL::Shader::compile(): compilation of" << shaderName(_type) << "shader" + << "succeeded with the following message:" << Debug::newline << message; } return success; @@ -810,7 +808,7 @@ bool Shader::compile(std::initializer_list> shader bool Shader::isCompileFinished() { GLint success; - glGetShaderiv(_id, GL_COMPLETION_STATUS_KHR, &success); + Context::current().state().shader.completionStatusImplementation(_id, GL_COMPLETION_STATUS_KHR, &success); return success == GL_TRUE; } @@ -822,6 +820,10 @@ void Shader::cleanLogImplementationIntelWindows(std::string& message) { } #endif +void Shader::completionStatusImplementationFallback(GLuint, GLenum, GLint* value) { + *value = GL_TRUE; +} + #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const Shader::Type value) { debug << "GL::Shader::Type" << Debug::nospace; diff --git a/src/Magnum/GL/Shader.h b/src/Magnum/GL/Shader.h index af7065c762..ccc3105db5 100644 --- a/src/Magnum/GL/Shader.h +++ b/src/Magnum/GL/Shader.h @@ -676,6 +676,8 @@ class MAGNUM_GL_EXPORT Shader: public AbstractObject { static MAGNUM_GL_LOCAL void cleanLogImplementationIntelWindows(std::string& message); #endif + static MAGNUM_GL_LOCAL void completionStatusImplementationFallback(GLuint, GLenum, GLint*); + Type _type; GLuint _id; diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 91a052fd15..6fdfdbcd21 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -208,33 +208,33 @@ template typename FlatGL::CompileState FlatG if(!context.isExtensionSupported(version)) #endif { - cs.bindAttributeLocation(Position::Location, "position"); + out.bindAttributeLocation(Position::Location, "position"); if(flags & Flag::Textured #ifndef MAGNUM_TARGET_GLES2 || flags >= Flag::ObjectIdTexture #endif ) - cs.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); + out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); if(flags & Flag::VertexColor) - cs.bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ + out.bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ #ifndef MAGNUM_TARGET_GLES2 if(flags & Flag::ObjectId) { - cs.bindFragmentDataLocation(ColorOutput, "color"); - cs.bindFragmentDataLocation(ObjectIdOutput, "objectId"); + out.bindFragmentDataLocation(ColorOutput, "color"); + out.bindFragmentDataLocation(ObjectIdOutput, "objectId"); } if(flags >= Flag::InstancedObjectId) - cs.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); + out.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); #endif if(flags & Flag::InstancedTransformation) - cs.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); + out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); if(flags >= Flag::InstancedTextureOffset) - cs.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); + out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); } #endif out.submitLink(); - return CompileState{std::move(out), std::move()}; + return CompileState{std::move(out), std::move(vert), std::move(frag), version}; } template FlatGL::FlatGL(CompileState&& cs) @@ -305,6 +305,9 @@ template FlatGL::FlatGL(CompileState&& cs) /* Object ID is zero by default */ } #endif + + static_cast(version); + static_cast(context); } template FlatGL::FlatGL(Flags flags diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h index 2278fa18c6..55a14a461e 100644 --- a/src/Magnum/Shaders/FlatGL.h +++ b/src/Magnum/Shaders/FlatGL.h @@ -603,7 +603,7 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: */ explicit FlatGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} - struct CompileState; + class CompileState; explicit FlatGL(CompileState&& cs); @@ -1053,14 +1053,16 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: }; template class FlatGL::CompileState : public FlatGL { +public: + using FlatGL::isLinkFinished; + private: friend class FlatGL; - using FlatGL::isLinkFinished; 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} {} + 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; From fa26cfcbc0aa788711cc1057c72f64e35c88e314 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Thu, 28 Jul 2022 14:37:42 +0300 Subject: [PATCH 07/27] More small fixes --- src/Magnum/GL/AbstractShaderProgram.h | 3 ++- src/Magnum/Shaders/FlatGL.cpp | 18 ++---------------- src/Magnum/Shaders/FlatGL.h | 16 ++++++++++------ 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.h b/src/Magnum/GL/AbstractShaderProgram.h index b6319cef83..4d18951b5a 100644 --- a/src/Magnum/GL/AbstractShaderProgram.h +++ b/src/Magnum/GL/AbstractShaderProgram.h @@ -1458,7 +1458,8 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { /** * @brief Submit for linking * - * The attached shaders must be compiled with @ref Shader::compile() before linking. + * The attached shaders must be compiled with @ref Shader::compile() + * or @ref Shader::submitCompile() before linking. * * @see @fn_gl_keyword{LinkProgram} */ diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 6fdfdbcd21..fdf5f3cb79 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -239,6 +239,8 @@ template typename FlatGL::CompileState FlatG template FlatGL::FlatGL(CompileState&& cs) : FlatGL{static_cast(std::move(cs))} { + if (_id == 0) return; + CORRADE_INTERNAL_ASSERT_OUTPUT(cs._vert.checkCompile()); CORRADE_INTERNAL_ASSERT_OUTPUT(cs._frag.checkCompile()); CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); @@ -310,22 +312,6 @@ template FlatGL::FlatGL(CompileState&& cs) static_cast(context); } -template FlatGL::FlatGL(Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , UnsignedInt materialCount, UnsignedInt drawCount - #endif -): - #ifndef MAGNUM_TARGET_GLES2 - FlatGL(compile(flags, materialCount, drawCount)) - #else - FlatGL{compile(flags)} - #endif -{} - -#ifndef MAGNUM_TARGET_GLES2 -template FlatGL::FlatGL(const Flags flags): FlatGL{flags, 1, 1} {} -#endif - template FlatGL& FlatGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h index 55a14a461e..6c6fe5d0e0 100644 --- a/src/Magnum/Shaders/FlatGL.h +++ b/src/Magnum/Shaders/FlatGL.h @@ -550,7 +550,7 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: * @ref FlatGL(Flags, UnsignedInt, UnsignedInt) with @p materialCount * and @p drawCount set to @cpp 1 @ce. */ - explicit FlatGL(Flags flags = {}); + explicit FlatGL(Flags flags = {}) : FlatGL{compile(flags)} {} #ifndef MAGNUM_TARGET_GLES2 /** @@ -586,7 +586,8 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: for this might be too confusing); what if some parameters won't be (unsigned) integers? like a string with shader extensions? make a whole Configuration class? */ - explicit FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + explicit FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): + FlatGL{compile(flags, materialCount, drawCount)} {} #endif /** @@ -613,6 +614,12 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: #endif ); + #ifndef MAGNUM_TARGET_GLES2 + static CompileState compile(Flags flags) { + return compile(flags, 1, 1); + } + #endif + /** @brief Copying is not allowed */ FlatGL(const FlatGL&) = delete; @@ -1053,13 +1060,10 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: }; template class FlatGL::CompileState : public FlatGL { -public: - using FlatGL::isLinkFinished; - private: friend class FlatGL; - CompileState(NoCreateT) : FlatGL(NoCreate), _vert{NoCreate}, _frag{NoCreate} {} + 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} {} From 0acc265c9af905530019fc78f8303e839feaf1e0 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Fri, 29 Jul 2022 14:24:21 +0300 Subject: [PATCH 08/27] Fix wrong access --- src/Magnum/Shaders/FlatGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index fdf5f3cb79..c17fccd13f 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -239,7 +239,7 @@ template typename FlatGL::CompileState FlatG template FlatGL::FlatGL(CompileState&& cs) : FlatGL{static_cast(std::move(cs))} { - if (_id == 0) return; + if (id() == 0) return; CORRADE_INTERNAL_ASSERT_OUTPUT(cs._vert.checkCompile()); CORRADE_INTERNAL_ASSERT_OUTPUT(cs._frag.checkCompile()); From 6fe87cc7bf2cb19c6cd9dfe76d22f0f4b648bc10 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Mon, 1 Aug 2022 14:27:31 +0300 Subject: [PATCH 09/27] Implement tests for compile/link/flat --- .../GL/Test/AbstractShaderProgramGLTest.cpp | 109 ++++++++++++++++++ src/Magnum/GL/Test/ShaderGLTest.cpp | 68 ++++++++--- src/Magnum/Shaders/FlatGL.cpp | 2 +- src/Magnum/Shaders/Test/FlatGLTest.cpp | 91 ++++++++++++++- 4 files changed, 251 insertions(+), 19 deletions(-) diff --git a/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp b/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp index 658fa112e1..18ec7b602b 100644 --- a/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp +++ b/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp @@ -27,6 +27,7 @@ #include #include /** @todo remove when Shader is -free */ #include +#include #include #include @@ -68,8 +69,11 @@ struct AbstractShaderProgramGLTest: OpenGLTester { #ifndef MAGNUM_TARGET_GLES void createMultipleOutputsIndexed(); #endif + void createAsync(); void linkFailure(); + void linkFailureAsync(); + void uniformNotFound(); void uniform(); @@ -103,12 +107,14 @@ AbstractShaderProgramGLTest::AbstractShaderProgramGLTest() { #endif &AbstractShaderProgramGLTest::create, + &AbstractShaderProgramGLTest::createAsync, &AbstractShaderProgramGLTest::createMultipleOutputs, #ifndef MAGNUM_TARGET_GLES &AbstractShaderProgramGLTest::createMultipleOutputsIndexed, #endif &AbstractShaderProgramGLTest::linkFailure, + &AbstractShaderProgramGLTest::linkFailureAsync, &AbstractShaderProgramGLTest::uniformNotFound, &AbstractShaderProgramGLTest::uniform, @@ -205,6 +211,8 @@ struct MyPublicShader: AbstractShaderProgram { using AbstractShaderProgram::bindFragmentDataLocation; #endif using AbstractShaderProgram::link; + using AbstractShaderProgram::submitLink; + using AbstractShaderProgram::checkLink; using AbstractShaderProgram::uniformLocation; #ifndef MAGNUM_TARGET_GLES2 using AbstractShaderProgram::uniformBlockIndex; @@ -257,6 +265,74 @@ void AbstractShaderProgramGLTest::create() { MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_VERIFY(linked); + // TODO: decide on this. + //CORRADE_VERIFY(program.isLinkFinished()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(valid); + } + + const Int matrixUniform = program.uniformLocation("matrix"); + const Int multiplierUniform = program.uniformLocation("multiplier"); + const Int colorUniform = program.uniformLocation("color"); + const Int additionsUniform = program.uniformLocation("additions"); + + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_VERIFY(matrixUniform >= 0); + CORRADE_VERIFY(multiplierUniform >= 0); + CORRADE_VERIFY(colorUniform >= 0); + CORRADE_VERIFY(additionsUniform >= 0); +} + +void AbstractShaderProgramGLTest::createAsync() { + Utility::Resource rs("AbstractShaderProgramGLTest"); + + Shader vert( + #ifndef MAGNUM_TARGET_GLES + #ifndef CORRADE_TARGET_APPLE + Version::GL210 + #else + Version::GL310 + #endif + #else + Version::GLES200 + #endif + , Shader::Type::Vertex); + vert.addSource(rs.getString("MyShader.vert")); + const bool vertCompiled = vert.compile(); + + Shader frag( + #ifndef MAGNUM_TARGET_GLES + #ifndef CORRADE_TARGET_APPLE + Version::GL210 + #else + Version::GL310 + #endif + #else + Version::GLES200 + #endif + , Shader::Type::Fragment); + frag.addSource(rs.getString("MyShader.frag")); + const bool fragCompiled = frag.compile(); + + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_VERIFY(vertCompiled); + CORRADE_VERIFY(fragCompiled); + + MyPublicShader program; + program.attachShaders({vert, frag}); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + program.bindAttributeLocation(0, "position"); + program.submitLink(); + + CORRADE_VERIFY(program.checkLink()); + const bool valid = program.validate().first; + + MAGNUM_VERIFY_NO_GL_ERROR(); { #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); @@ -412,6 +488,39 @@ void AbstractShaderProgramGLTest::linkFailure() { CORRADE_VERIFY(!program.link()); } +void AbstractShaderProgramGLTest::linkFailureAsync() { + Shader shader( + #ifndef MAGNUM_TARGET_GLES + #ifndef CORRADE_TARGET_APPLE + Version::GL210 + #else + Version::GL310 + #endif + #else + Version::GLES200 + #endif + , Shader::Type::Fragment); + shader.addSource("[fu] bleh error #:! stuff\n"); + + { + Error redirectError{nullptr}; + CORRADE_VERIFY(!shader.compile()); + } + + MyPublicShader program; + program.attachShaders({shader}); + + std::ostringstream out; + Error redirectError{&out}; + + program.submitLink(); + CORRADE_VERIFY(out.str().empty()); + + CORRADE_VERIFY(!program.checkLink()); + CORRADE_COMPARE_AS(out.str(), "GL::AbstractShaderProgram::link(): linking failed with the following message:", + TestSuite::Compare::StringHasPrefix); +} + void AbstractShaderProgramGLTest::uniformNotFound() { MyPublicShader program; diff --git a/src/Magnum/GL/Test/ShaderGLTest.cpp b/src/Magnum/GL/Test/ShaderGLTest.cpp index 5c7978b77d..32ad1a28b1 100644 --- a/src/Magnum/GL/Test/ShaderGLTest.cpp +++ b/src/Magnum/GL/Test/ShaderGLTest.cpp @@ -23,7 +23,9 @@ DEALINGS IN THE SOFTWARE. */ +#include #include /** @todo remove once Shader is -free */ +#include #include #include @@ -40,6 +42,18 @@ namespace Magnum { namespace GL { namespace Test { namespace { +constexpr GL::Version shaderCompileGLVersion = +#ifndef MAGNUM_TARGET_GLES + #ifndef CORRADE_TARGET_APPLE + Version::GL210 + #else + Version::GL310 + #endif + ; +#else +Version::GLES200; +#endif + struct ShaderGLTest: OpenGLTester { explicit ShaderGLTest(); @@ -55,6 +69,9 @@ struct ShaderGLTest: OpenGLTester { void addSourceNoVersion(); void addFile(); void compile(); + void compileFailure(); + void compileAsync(); + void compileAsyncFailure(); void compileUtf8(); void compileNoVersion(); }; @@ -72,6 +89,9 @@ ShaderGLTest::ShaderGLTest() { &ShaderGLTest::addSourceNoVersion, &ShaderGLTest::addFile, &ShaderGLTest::compile, + &ShaderGLTest::compileFailure, + &ShaderGLTest::compileAsync, + &ShaderGLTest::compileAsyncFailure, &ShaderGLTest::compileUtf8, &ShaderGLTest::compileNoVersion}); } @@ -262,25 +282,41 @@ void ShaderGLTest::addFile() { } void ShaderGLTest::compile() { - #ifndef MAGNUM_TARGET_GLES - constexpr Version v = - #ifndef CORRADE_TARGET_APPLE - Version::GL210 - #else - Version::GL310 - #endif - ; - #else - constexpr Version v = Version::GLES200; - #endif - - Shader shader(v, Shader::Type::Fragment); + Shader shader(shaderCompileGLVersion, Shader::Type::Fragment); shader.addSource("void main() {}\n"); + CORRADE_VERIFY(shader.compile()); + CORRADE_VERIFY(shader.isCompileFinished()); +} + +void ShaderGLTest::compileFailure() { + Shader shader(shaderCompileGLVersion, Shader::Type::Fragment); + shader.addSource("[fu] bleh error #:! stuff\n"); + + CORRADE_VERIFY(!shader.compile()); + CORRADE_VERIFY(shader.isCompileFinished()); +} + +void ShaderGLTest::compileAsync() { + Shader shader(shaderCompileGLVersion, Shader::Type::Fragment); + shader.addSource("void main() {}\n"); + shader.submitCompile(); + + CORRADE_VERIFY(shader.checkCompile()); +} + +void ShaderGLTest::compileAsyncFailure() { + Shader shader(shaderCompileGLVersion, Shader::Type::Fragment); + shader.addSource("[fu] bleh error #:! stuff\n"); + shader.submitCompile(); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(out.str().empty()); - Shader shader2(v, Shader::Type::Fragment); - shader2.addSource("[fu] bleh error #:! stuff\n"); - CORRADE_VERIFY(!shader2.compile()); + CORRADE_VERIFY(!shader.checkCompile()); + CORRADE_COMPARE_AS(out.str(), "GL::Shader::compile(): compilation of fragment shader failed with the following message:", + TestSuite::Compare::StringHasPrefix); } void ShaderGLTest::compileUtf8() { diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index c17fccd13f..29c34cb61e 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -241,9 +241,9 @@ template FlatGL::FlatGL(CompileState&& cs) : FlatGL{static_cast(std::move(cs))} { if (id() == 0) return; + CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); CORRADE_INTERNAL_ASSERT_OUTPUT(cs._vert.checkCompile()); CORRADE_INTERNAL_ASSERT_OUTPUT(cs._frag.checkCompile()); - CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); const GL::Context& context = GL::Context::current(); const GL::Version version = cs._version; diff --git a/src/Magnum/Shaders/Test/FlatGLTest.cpp b/src/Magnum/Shaders/Test/FlatGLTest.cpp index 730bb0fada..003ab2eb88 100644 --- a/src/Magnum/Shaders/Test/FlatGLTest.cpp +++ b/src/Magnum/Shaders/Test/FlatGLTest.cpp @@ -83,8 +83,10 @@ struct FlatGLTest: GL::OpenGLTester { explicit FlatGLTest(); template void construct(); + template void constructAsync(); #ifndef MAGNUM_TARGET_GLES2 template void constructUniformBuffers(); + template void constructUniformBuffersAsync(); #endif template void constructMove(); @@ -597,13 +599,18 @@ constexpr struct { FlatGLTest::FlatGLTest() { addInstancedTests({ &FlatGLTest::construct<2>, - &FlatGLTest::construct<3>}, + &FlatGLTest::construct<3>, + &FlatGLTest::constructAsync<2>, + &FlatGLTest::constructAsync<3>}, Containers::arraySize(ConstructData)); + #ifndef MAGNUM_TARGET_GLES2 addInstancedTests({ &FlatGLTest::constructUniformBuffers<2>, - &FlatGLTest::constructUniformBuffers<3>}, + &FlatGLTest::constructUniformBuffers<3>, + &FlatGLTest::constructUniformBuffersAsync<2>, + &FlatGLTest::constructUniformBuffersAsync<3>}, Containers::arraySize(ConstructUniformBuffersData)); #endif @@ -853,6 +860,37 @@ template void FlatGLTest::construct() { MAGNUM_VERIFY_NO_GL_ERROR(); } +template void FlatGLTest::constructAsync() { + setTestCaseTemplateName(Utility::format("{}", dimensions)); + + auto&& data = ConstructData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + #ifndef MAGNUM_TARGET_GLES + if((data.flags & FlatGL2D::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); + if((data.flags & FlatGL2D::Flag::TextureArrays) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::texture_array::string() << "is not supported."); + #endif + + auto compileState = FlatGL::compile(data.flags); + CORRADE_COMPARE(compileState.flags(), data.flags); + + FlatGL shader{std::move(compileState)}; + CORRADE_COMPARE(shader.flags(), data.flags); + // TODO: decide on this. + // CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} + #ifndef MAGNUM_TARGET_GLES2 template void FlatGLTest::constructUniformBuffers() { setTestCaseTemplateName(Utility::format("{}", dimensions)); @@ -896,6 +934,55 @@ template void FlatGLTest::constructUniformBuffers() { MAGNUM_VERIFY_NO_GL_ERROR(); } + +template void FlatGLTest::constructUniformBuffersAsync() { + setTestCaseTemplateName(Utility::format("{}", dimensions)); + + auto&& data = ConstructUniformBuffersData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + #ifndef MAGNUM_TARGET_GLES + if((data.flags & FlatGL2D::Flag::UniformBuffers) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); + if((data.flags & FlatGL2D::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); + if((data.flags & FlatGL2D::Flag::TextureArrays) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::texture_array::string() << "is not supported."); + #endif + + if(data.flags >= FlatGL2D::Flag::MultiDraw) { + #ifndef MAGNUM_TARGET_GLES + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); + #elif !defined(MAGNUM_TARGET_WEBGL) + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); + #endif + } + + auto compileState = FlatGL::compile(data.flags, data.materialCount, data.drawCount); + CORRADE_COMPARE(compileState.flags(), data.flags); + CORRADE_COMPARE(compileState.materialCount(), data.materialCount); + CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + + FlatGL shader{std::move(compileState)}; + CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_COMPARE(shader.materialCount(), data.materialCount); + CORRADE_COMPARE(shader.drawCount(), data.drawCount); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} + #endif template void FlatGLTest::constructMove() { From 1a1c045ef3093b322b24d0d124ee13f980b3d2f4 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Sat, 6 Aug 2022 13:04:04 +0300 Subject: [PATCH 10/27] Fixes: docs, tests --- src/Magnum/GL/AbstractShaderProgram.h | 6 ++ src/Magnum/GL/Shader.h | 4 + .../GL/Test/AbstractShaderProgramGLTest.cpp | 20 ++++- src/Magnum/GL/Test/ShaderGLTest.cpp | 80 +++++++++++++++---- src/Magnum/Shaders/Test/FlatGLTest.cpp | 45 ++++++++--- 5 files changed, 125 insertions(+), 30 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.h b/src/Magnum/GL/AbstractShaderProgram.h index 4d18951b5a..f72621ecac 100644 --- a/src/Magnum/GL/AbstractShaderProgram.h +++ b/src/Magnum/GL/AbstractShaderProgram.h @@ -1260,7 +1260,13 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { /** * @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. + * + * @see @fn_gl_keyword{GetProgram} with + * @def_gl_extension{COMPLETION_STATUS,KHR,parallel_shader_compile} */ bool isLinkFinished(); diff --git a/src/Magnum/GL/Shader.h b/src/Magnum/GL/Shader.h index ccc3105db5..045d822bdd 100644 --- a/src/Magnum/GL/Shader.h +++ b/src/Magnum/GL/Shader.h @@ -661,6 +661,10 @@ class MAGNUM_GL_EXPORT Shader: public AbstractObject { /** * @brief Non-blocking compilation status check + * @return @cpp true @ce if shader compilation finished, @cpp false @ce otherwise + * + * @see @fn_gl_keyword{GetProgram} with + * @def_gl_extension{COMPLETION_STATUS,KHR,parallel_shader_compile} * */ bool isCompileFinished(); diff --git a/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp b/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp index 18ec7b602b..e378aca0e3 100644 --- a/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp +++ b/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "Magnum/Image.h" #include "Magnum/ImageView.h" @@ -265,8 +266,10 @@ void AbstractShaderProgramGLTest::create() { MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_VERIFY(linked); - // TODO: decide on this. - //CORRADE_VERIFY(program.isLinkFinished()); + + // Some drivers need a bit of time to update this result + Utility::System::sleep(200); + CORRADE_VERIFY(program.isLinkFinished()); { #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); @@ -329,7 +332,11 @@ void AbstractShaderProgramGLTest::createAsync() { program.bindAttributeLocation(0, "position"); program.submitLink(); + while(!program.isLinkFinished()) + Utility::System::sleep(100); + CORRADE_VERIFY(program.checkLink()); + CORRADE_VERIFY(program.isLinkFinished()); const bool valid = program.validate().first; MAGNUM_VERIFY_NO_GL_ERROR(); @@ -486,6 +493,9 @@ void AbstractShaderProgramGLTest::linkFailure() { MyPublicShader program; program.attachShaders({shader}); CORRADE_VERIFY(!program.link()); + + Utility::System::sleep(200); + CORRADE_VERIFY(program.isLinkFinished()); } void AbstractShaderProgramGLTest::linkFailureAsync() { @@ -512,11 +522,15 @@ void AbstractShaderProgramGLTest::linkFailureAsync() { std::ostringstream out; Error redirectError{&out}; - program.submitLink(); + + while(!program.isLinkFinished()) + Utility::System::sleep(100); + CORRADE_VERIFY(out.str().empty()); CORRADE_VERIFY(!program.checkLink()); + CORRADE_VERIFY(program.isLinkFinished()); CORRADE_COMPARE_AS(out.str(), "GL::AbstractShaderProgram::link(): linking failed with the following message:", TestSuite::Compare::StringHasPrefix); } diff --git a/src/Magnum/GL/Test/ShaderGLTest.cpp b/src/Magnum/GL/Test/ShaderGLTest.cpp index 32ad1a28b1..49ef6cc663 100644 --- a/src/Magnum/GL/Test/ShaderGLTest.cpp +++ b/src/Magnum/GL/Test/ShaderGLTest.cpp @@ -27,6 +27,7 @@ #include /** @todo remove once Shader is -free */ #include #include +#include #include #include "Magnum/GL/Context.h" @@ -42,18 +43,6 @@ namespace Magnum { namespace GL { namespace Test { namespace { -constexpr GL::Version shaderCompileGLVersion = -#ifndef MAGNUM_TARGET_GLES - #ifndef CORRADE_TARGET_APPLE - Version::GL210 - #else - Version::GL310 - #endif - ; -#else -Version::GLES200; -#endif - struct ShaderGLTest: OpenGLTester { explicit ShaderGLTest(); @@ -282,7 +271,19 @@ void ShaderGLTest::addFile() { } void ShaderGLTest::compile() { - Shader shader(shaderCompileGLVersion, Shader::Type::Fragment); + #ifndef MAGNUM_TARGET_GLES + constexpr Version v = + #ifndef CORRADE_TARGET_APPLE + Version::GL210 + #else + Version::GL310 + #endif + ; + #else + constexpr Version v = Version::GLES200; + #endif + + Shader shader(v, Shader::Type::Fragment); shader.addSource("void main() {}\n"); CORRADE_VERIFY(shader.compile()); @@ -290,7 +291,19 @@ void ShaderGLTest::compile() { } void ShaderGLTest::compileFailure() { - Shader shader(shaderCompileGLVersion, Shader::Type::Fragment); + #ifndef MAGNUM_TARGET_GLES + constexpr Version v = + #ifndef CORRADE_TARGET_APPLE + Version::GL210 + #else + Version::GL310 + #endif + ; + #else + constexpr Version v = Version::GLES200; + #endif + + Shader shader(v, Shader::Type::Fragment); shader.addSource("[fu] bleh error #:! stuff\n"); CORRADE_VERIFY(!shader.compile()); @@ -298,23 +311,56 @@ void ShaderGLTest::compileFailure() { } void ShaderGLTest::compileAsync() { - Shader shader(shaderCompileGLVersion, Shader::Type::Fragment); + #ifndef MAGNUM_TARGET_GLES + constexpr Version v = + #ifndef CORRADE_TARGET_APPLE + Version::GL210 + #else + Version::GL310 + #endif + ; + #else + constexpr Version v = Version::GLES200; + #endif + + Shader shader(v, Shader::Type::Fragment); shader.addSource("void main() {}\n"); shader.submitCompile(); + while(!shader.isCompileFinished()) + Utility::System::sleep(100); + CORRADE_VERIFY(shader.checkCompile()); + CORRADE_VERIFY(shader.isCompileFinished()); } void ShaderGLTest::compileAsyncFailure() { - Shader shader(shaderCompileGLVersion, Shader::Type::Fragment); + #ifndef MAGNUM_TARGET_GLES + constexpr Version v = + #ifndef CORRADE_TARGET_APPLE + Version::GL210 + #else + Version::GL310 + #endif + ; + #else + constexpr Version v = Version::GLES200; + #endif + + Shader shader(v, Shader::Type::Fragment); shader.addSource("[fu] bleh error #:! stuff\n"); - shader.submitCompile(); std::ostringstream out; Error redirectError{&out}; + shader.submitCompile(); + + while(!shader.isCompileFinished()) + Utility::System::sleep(100); + CORRADE_VERIFY(out.str().empty()); CORRADE_VERIFY(!shader.checkCompile()); + CORRADE_VERIFY(shader.isCompileFinished()); CORRADE_COMPARE_AS(out.str(), "GL::Shader::compile(): compilation of fragment shader failed with the following message:", TestSuite::Compare::StringHasPrefix); } diff --git a/src/Magnum/Shaders/Test/FlatGLTest.cpp b/src/Magnum/Shaders/Test/FlatGLTest.cpp index 003ab2eb88..2828e2dbf4 100644 --- a/src/Magnum/Shaders/Test/FlatGLTest.cpp +++ b/src/Magnum/Shaders/Test/FlatGLTest.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #ifdef CORRADE_TARGET_APPLE @@ -599,19 +600,22 @@ constexpr struct { FlatGLTest::FlatGLTest() { addInstancedTests({ &FlatGLTest::construct<2>, - &FlatGLTest::construct<3>, - &FlatGLTest::constructAsync<2>, - &FlatGLTest::constructAsync<3>}, + &FlatGLTest::construct<3>}, Containers::arraySize(ConstructData)); + addTests({ + &FlatGLTest::constructAsync<2>, + &FlatGLTest::constructAsync<3>}); #ifndef MAGNUM_TARGET_GLES2 addInstancedTests({ &FlatGLTest::constructUniformBuffers<2>, - &FlatGLTest::constructUniformBuffers<3>, - &FlatGLTest::constructUniformBuffersAsync<2>, - &FlatGLTest::constructUniformBuffersAsync<3>}, + &FlatGLTest::constructUniformBuffers<3>}, Containers::arraySize(ConstructUniformBuffersData)); + + addTests({ + &FlatGLTest::constructUniformBuffersAsync<2>, + &FlatGLTest::constructUniformBuffersAsync<3>}); #endif addTests({ @@ -863,7 +867,14 @@ template void FlatGLTest::construct() { template void FlatGLTest::constructAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - auto&& data = ConstructData[testCaseInstanceId()]; + constexpr struct { + const char* name; + FlatGL2D::Flags flags; + } data { + "textured + texture transformation", + FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation + }; + setTestCaseDescription(data.name); #ifndef MAGNUM_TARGET_GLES @@ -876,10 +887,12 @@ template void FlatGLTest::constructAsync() { auto compileState = FlatGL::compile(data.flags); CORRADE_COMPARE(compileState.flags(), data.flags); + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + FlatGL shader{std::move(compileState)}; CORRADE_COMPARE(shader.flags(), data.flags); - // TODO: decide on this. - // CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_VERIFY(shader.id()); { #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) @@ -938,7 +951,16 @@ template void FlatGLTest::constructUniformBuffers() { template void FlatGLTest::constructUniformBuffersAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - auto&& data = ConstructUniformBuffersData[testCaseInstanceId()]; + constexpr struct { + const char* name; + FlatGL2D::Flags flags; + UnsignedInt materialCount, drawCount; + } data { + "alpha mask", + FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::AlphaMask, + 1, 1 + }; + setTestCaseDescription(data.name); #ifndef MAGNUM_TARGET_GLES @@ -968,6 +990,9 @@ template void FlatGLTest::constructUniformBuffersAsync() CORRADE_COMPARE(compileState.materialCount(), data.materialCount); CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + FlatGL shader{std::move(compileState)}; CORRADE_COMPARE(shader.flags(), data.flags); CORRADE_COMPARE(shader.materialCount(), data.materialCount); From fefb99d24d17140061a05c7e5c6d6f16f0b967de Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Tue, 9 Aug 2022 15:45:57 +0300 Subject: [PATCH 11/27] VectorGL & tests --- src/Magnum/Shaders/Test/VectorGLTest.cpp | 94 ++++++++++++++++++++++++ src/Magnum/Shaders/VectorGL.cpp | 63 ++++++++++------ src/Magnum/Shaders/VectorGL.h | 38 +++++++++- 3 files changed, 169 insertions(+), 26 deletions(-) diff --git a/src/Magnum/Shaders/Test/VectorGLTest.cpp b/src/Magnum/Shaders/Test/VectorGLTest.cpp index 670886fb7b..7b8bff18fc 100644 --- a/src/Magnum/Shaders/Test/VectorGLTest.cpp +++ b/src/Magnum/Shaders/Test/VectorGLTest.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #ifdef CORRADE_TARGET_APPLE @@ -83,8 +84,10 @@ struct VectorGLTest: GL::OpenGLTester { explicit VectorGLTest(); template void construct(); + template void constructAsync(); #ifndef MAGNUM_TARGET_GLES2 template void constructUniformBuffers(); + template void constructUniformBuffersAsync(); #endif template void constructMove(); @@ -247,11 +250,19 @@ VectorGLTest::VectorGLTest() { &VectorGLTest::construct<3>}, Containers::arraySize(ConstructData)); + addTests({ + &VectorGLTest::constructAsync<2>, + &VectorGLTest::constructAsync<3>}); + #ifndef MAGNUM_TARGET_GLES2 addInstancedTests({ &VectorGLTest::constructUniformBuffers<2>, &VectorGLTest::constructUniformBuffers<3>}, Containers::arraySize(ConstructUniformBuffersData)); + + addTests({ + &VectorGLTest::constructUniformBuffersAsync<2>, + &VectorGLTest::constructUniformBuffersAsync<3>}); #endif addTests({ @@ -370,6 +381,38 @@ template void VectorGLTest::construct() { MAGNUM_VERIFY_NO_GL_ERROR(); } +template void VectorGLTest::constructAsync() { + setTestCaseTemplateName(Utility::format("{}", dimensions)); + + constexpr struct { + const char* name; + VectorGL2D::Flags flags; + } data { + "texture transformation", VectorGL2D::Flag::TextureTransformation + }; + setTestCaseDescription(data.name); + + auto compileState = VectorGL::compile(data.flags); + CORRADE_COMPARE(compileState.flags(), data.flags); + + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + + VectorGL shader{std::move(compileState)}; + CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} + + #ifndef MAGNUM_TARGET_GLES2 template void VectorGLTest::constructUniformBuffers() { setTestCaseTemplateName(Utility::format("{}", dimensions)); @@ -408,6 +451,57 @@ template void VectorGLTest::constructUniformBuffers() { MAGNUM_VERIFY_NO_GL_ERROR(); } + +template void VectorGLTest::constructUniformBuffersAsync() { + setTestCaseTemplateName(Utility::format("{}", dimensions)); + + constexpr struct { + const char* name; + VectorGL2D::Flags flags; + UnsignedInt materialCount, drawCount; + } data {"texture transformation", VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation, 1, 1}; + setTestCaseDescription(data.name); + + #ifndef MAGNUM_TARGET_GLES + if((data.flags & VectorGL::Flag::UniformBuffers) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); + #endif + + if(data.flags >= VectorGL2D::Flag::MultiDraw) { + #ifndef MAGNUM_TARGET_GLES + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); + #elif !defined(MAGNUM_TARGET_WEBGL) + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); + #endif + } + + auto compileState = VectorGL::compile(data.flags, data.materialCount, data.drawCount); + CORRADE_COMPARE(compileState.flags(), data.flags); + CORRADE_COMPARE(compileState.materialCount(), data.materialCount); + CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + + VectorGL shader{std::move(compileState)}; + CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_COMPARE(shader.drawCount(), data.drawCount); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} #endif template void VectorGLTest::constructMove() { diff --git a/src/Magnum/Shaders/VectorGL.cpp b/src/Magnum/Shaders/VectorGL.cpp index addcb7433d..d5f8224fdf 100644 --- a/src/Magnum/Shaders/VectorGL.cpp +++ b/src/Magnum/Shaders/VectorGL.cpp @@ -63,21 +63,16 @@ namespace { #endif } -template VectorGL::VectorGL(const Flags flags +template typename VectorGL::CompileState VectorGL::compile(const Flags flags #ifndef MAGNUM_TARGET_GLES2 , const UnsignedInt materialCount, const UnsignedInt drawCount #endif -): - _flags{flags} - #ifndef MAGNUM_TARGET_GLES2 - , _materialCount{materialCount}, _drawCount{drawCount} - #endif -{ +) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, - "Shaders::VectorGL: material count can't be zero", ); + "Shaders::VectorGL: material count can't be zero", CompileState{NoCreate}); CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, - "Shaders::VectorGL: draw count can't be zero", ); + "Shaders::VectorGL: draw count can't be zero", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES @@ -141,9 +136,17 @@ template VectorGL::VectorGL(const Flags flag frag.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("Vector.frag")); - CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); + vert.submitCompile(); + frag.submitCompile(); + + VectorGL out{NoInit}; + out._flags = flags; + #ifndef MAGNUM_TARGET_GLES2 + out._materialCount = materialCount; + out._drawCount = drawCount; + #endif - attachShaders({vert, frag}); + out.attachShaders({vert, frag}); /* ES3 has this done in the shader directly */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) @@ -151,25 +154,41 @@ template VectorGL::VectorGL(const Flags flag if(!context.isExtensionSupported(version)) #endif { - bindAttributeLocation(Position::Location, "position"); - bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); + out.bindAttributeLocation(Position::Location, "position"); + out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); } #endif - CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + out.submitLink(); + + 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; + + CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); + CORRADE_INTERNAL_ASSERT_OUTPUT(cs._vert.checkCompile()); + CORRADE_INTERNAL_ASSERT_OUTPUT(cs._frag.checkCompile()); + + const GL::Context& context = GL::Context::current(); + const GL::Version version = cs._version; + #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) #endif { #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::UniformBuffers) { if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset"); } else #endif { _transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); - if(flags & Flag::TextureTransformation) + if(_flags & Flag::TextureTransformation) _textureMatrixUniform = uniformLocation("textureMatrix"); _backgroundColorUniform = uniformLocation("backgroundColor"); _colorUniform = uniformLocation("color"); @@ -182,10 +201,10 @@ template VectorGL::VectorGL(const Flags flag { setUniform(uniformLocation("vectorTexture"), TextureUnit); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::UniformBuffers) { setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding); setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding); - if(flags & Flag::TextureTransformation) + if(_flags & Flag::TextureTransformation) setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding); setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding); } @@ -195,13 +214,13 @@ template VectorGL::VectorGL(const Flags flag /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ #ifdef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::UniformBuffers) { /* Draw offset is zero by default */ } else #endif { setTransformationProjectionMatrix(MatrixTypeFor{Math::IdentityInit}); - if(flags & Flag::TextureTransformation) + if(_flags & Flag::TextureTransformation) setTextureMatrix(Matrix3{Math::IdentityInit}); /* Background color is zero by default */ setColor(Color4{1.0f}); @@ -209,10 +228,6 @@ template VectorGL::VectorGL(const Flags flag #endif } -#ifndef MAGNUM_TARGET_GLES2 -template VectorGL::VectorGL(const Flags flags): VectorGL{flags, 1, 1} {} -#endif - template VectorGL& VectorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), diff --git a/src/Magnum/Shaders/VectorGL.h b/src/Magnum/Shaders/VectorGL.h index e1157ba9d3..ae4a3aa6c7 100644 --- a/src/Magnum/Shaders/VectorGL.h +++ b/src/Magnum/Shaders/VectorGL.h @@ -32,6 +32,7 @@ #include "Magnum/DimensionTraits.h" #include "Magnum/GL/AbstractShaderProgram.h" +#include "Magnum/GL/Shader.h" #include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/visibility.h" @@ -221,7 +222,7 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL * @ref VectorGL(Flags, UnsignedInt, UnsignedInt) with @p materialCount * and @p drawCount set to @cpp 1 @ce. */ - explicit VectorGL(Flags flags = {}); + explicit VectorGL(Flags flags = {}) : VectorGL{compile(flags)} {}; #ifndef MAGNUM_TARGET_GLES2 /** @@ -256,7 +257,8 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL for this might be too confusing); what if some parameters won't be (unsigned) integers? like a string with shader extensions? make a whole Configuration class? */ - explicit VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + explicit VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount) : + VectorGL{compile(flags, materialCount, drawCount)} {} #endif /** @@ -273,6 +275,22 @@ 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) { + return compile(flags, 1, 1); + } + #endif + /** @brief Copying is not allowed */ VectorGL(const VectorGL&) = delete; @@ -554,6 +572,9 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL #endif private: + /* Creates the GL shader program object but nothing else. Internal, used by compile(). */ + explicit VectorGL(NoInitT) {} + /* Prevent accidentally calling irrelevant functions */ #ifndef MAGNUM_TARGET_GLES using GL::AbstractShaderProgram::drawTransformFeedback; @@ -577,6 +598,19 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL #endif }; +template class VectorGL::CompileState : public VectorGL { +private: + 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} {} + + GL::Shader _vert, _frag; + GL::Version _version; +}; + /** @brief Two-dimensional vector OpenGL shader @m_since_latest From e1ec1a6794747ca0b2343804043727ebe50041ed Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Thu, 11 Aug 2022 22:55:29 +0300 Subject: [PATCH 12/27] MeshVisualizerGL3D & tests --- src/Magnum/Shaders/MeshVisualizerGL.cpp | 307 +++++++++------- src/Magnum/Shaders/MeshVisualizerGL.h | 79 +++- .../Shaders/Test/MeshVisualizerGLTest.cpp | 339 ++++++++++++++++++ src/Magnum/Shaders/VectorGL.cpp | 5 +- 4 files changed, 592 insertions(+), 138 deletions(-) diff --git a/src/Magnum/Shaders/MeshVisualizerGL.cpp b/src/Magnum/Shaders/MeshVisualizerGL.cpp index 615231aa59..eaec0dd12b 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.cpp +++ b/src/Magnum/Shaders/MeshVisualizerGL.cpp @@ -26,7 +26,6 @@ #include "MeshVisualizerGL.h" #include -#include #include #include #include @@ -72,17 +71,7 @@ namespace { namespace Implementation { -MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags - #ifndef MAGNUM_TARGET_GLES2 - , const UnsignedInt materialCount, const UnsignedInt drawCount - #endif -): - _flags{flags} - #ifndef MAGNUM_TARGET_GLES2 - , _materialCount{materialCount}, - _drawCount{drawCount} - #endif -{ +void MeshVisualizerGLBase::assertExtensions(const FlagsBase flags) { #ifndef MAGNUM_TARGET_GLES2 #ifndef CORRADE_NO_ASSERT Int countMutuallyExclusive = 0; @@ -120,7 +109,7 @@ MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags #endif #ifndef MAGNUM_TARGET_GLES2 - if(_flags & FlagBase::Wireframe && !(_flags & FlagBase::NoGeometryShader)) { + if(flags & FlagBase::Wireframe && !(flags & FlagBase::NoGeometryShader)) { #ifndef MAGNUM_TARGET_GLES MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL320); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::geometry_shader4); @@ -129,12 +118,12 @@ MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags #endif } #else - if(_flags & FlagBase::Wireframe) + if(flags & FlagBase::Wireframe) MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::OES::standard_derivatives); #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(_flags & FlagBase::PrimitiveId && !(_flags >= FlagBase::PrimitiveIdFromVertexId)) { + if(flags & FlagBase::PrimitiveId && !(flags >= FlagBase::PrimitiveIdFromVertexId)) { #ifndef MAGNUM_TARGET_GLES MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL320); #else @@ -150,18 +139,23 @@ MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags #endif } -GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs) const { +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 + #endif +) { GL::Context& context = GL::Context::current(); #ifndef MAGNUM_TARGET_GLES const GL::Version version = context.supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); /* Extended in MeshVisualizerGL3D for TBN visualization */ - CORRADE_INTERNAL_ASSERT(!(_flags & FlagBase::Wireframe) || _flags & FlagBase::NoGeometryShader || version >= GL::Version::GL320); + CORRADE_INTERNAL_ASSERT(!(flags & FlagBase::Wireframe) || flags & FlagBase::NoGeometryShader || version >= GL::Version::GL320); #elif !defined(MAGNUM_TARGET_WEBGL) /* ES 3.2 needed for gl_PrimitiveID */ const GL::Version version = context.supportedVersion({GL::Version::GLES320, GL::Version::GLES310, GL::Version::GLES300, GL::Version::GLES200}); /* Extended in MeshVisualizerGL3D for TBN visualization */ - CORRADE_INTERNAL_ASSERT(!(_flags & FlagBase::Wireframe) || _flags & FlagBase::NoGeometryShader || version >= GL::Version::GLES310); + CORRADE_INTERNAL_ASSERT(!(flags & FlagBase::Wireframe) || flags & FlagBase::NoGeometryShader || version >= GL::Version::GLES310); #else const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); #endif @@ -169,18 +163,18 @@ GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& fra vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); - vert.addSource(_flags & FlagBase::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") + vert.addSource(flags & FlagBase::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") #ifndef MAGNUM_TARGET_GLES2 - .addSource(_flags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "") - .addSource(_flags & FlagBase::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") - .addSource(_flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") - .addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + .addSource(flags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "") + .addSource(flags & FlagBase::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") + .addSource(flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") + .addSource(flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") #endif - .addSource(_flags & FlagBase::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "") + .addSource(flags & FlagBase::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "") #ifndef MAGNUM_TARGET_GLES2 - .addSource(_flags >= FlagBase::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : "") - .addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") - .addSource(_flags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "") + .addSource(flags >= FlagBase::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : "") + .addSource(flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") + .addSource(flags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "") #endif #ifdef MAGNUM_TARGET_WEBGL .addSource("#define SUBSCRIPTING_WORKAROUND\n") @@ -190,38 +184,38 @@ GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& fra #endif ; #ifndef MAGNUM_TARGET_GLES2 - if(_flags >= FlagBase::UniformBuffers) { + if(flags >= FlagBase::UniformBuffers) { vert.addSource(Utility::formatString( "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n" "#define MATERIAL_COUNT {}\n", - _drawCount, - _materialCount)); - vert.addSource(_flags >= FlagBase::MultiDraw ? "#define MULTI_DRAW\n" : ""); + drawCount, + materialCount)); + vert.addSource(flags >= FlagBase::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif - frag.addSource(_flags & FlagBase::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") + frag.addSource(flags & FlagBase::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") #ifndef MAGNUM_TARGET_GLES2 - .addSource(_flags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "") - .addSource(_flags >= FlagBase::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "") - .addSource(_flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") - .addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") - .addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") - .addSource(_flags & FlagBase::PrimitiveId ? - (_flags >= FlagBase::PrimitiveIdFromVertexId ? + .addSource(flags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "") + .addSource(flags >= FlagBase::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "") + .addSource(flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") + .addSource(flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + .addSource(flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") + .addSource(flags & FlagBase::PrimitiveId ? + (flags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "#define PRIMITIVE_ID\n") : "") #endif ; #ifndef MAGNUM_TARGET_GLES2 - if(_flags >= FlagBase::UniformBuffers) { + if(flags >= FlagBase::UniformBuffers) { frag.addSource(Utility::formatString( "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n" "#define MATERIAL_COUNT {}\n", - _drawCount, - _materialCount)); - frag.addSource(_flags >= FlagBase::MultiDraw ? "#define MULTI_DRAW\n" : ""); + drawCount, + materialCount)); + frag.addSource(flags >= FlagBase::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif @@ -382,21 +376,20 @@ MeshVisualizerGLBase& MeshVisualizerGLBase::bindObjectIdTexture(GL::Texture2DArr } -MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags +MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags #ifndef MAGNUM_TARGET_GLES2 , const UnsignedInt materialCount, const UnsignedInt drawCount #endif -): Implementation::MeshVisualizerGLBase{Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags)) - #ifndef MAGNUM_TARGET_GLES2 - , materialCount, drawCount - #endif -} { +) { + FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags)); + assertExtensions(baseFlags); + #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), - "Shaders::MeshVisualizerGL2D: at least one visualization feature has to be enabled", ); + "Shaders::MeshVisualizerGL2D: at least one visualization feature has to be enabled", CompileState{NoCreate}); #else CORRADE_ASSERT(flags & (Flag::Wireframe & ~Flag::NoGeometryShader), - "Shaders::MeshVisualizerGL2D: at least Flag::Wireframe has to be enabled", ); + "Shaders::MeshVisualizerGL2D: at least Flag::Wireframe has to be enabled", CompileState{NoCreate}); #endif /* Has to be here and not in the base class in order to have it exit the @@ -404,9 +397,9 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags otherwise */ #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, - "Shaders::MeshVisualizerGL2D: material count can't be zero", ); + "Shaders::MeshVisualizerGL2D: material count can't be zero", CompileState{NoCreate}); CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, - "Shaders::MeshVisualizerGL2D: draw count can't be zero", ); + "Shaders::MeshVisualizerGL2D: draw count can't be zero", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES @@ -416,7 +409,12 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags Utility::Resource rs{"MagnumShadersGL"}; GL::Shader vert{NoCreate}; GL::Shader frag{NoCreate}; - const GL::Version version = setupShaders(vert, frag, rs); + const GL::Version version = setupShaders(vert, frag, rs, baseFlags + #ifndef MAGNUM_TARGET_GLES2 + , materialCount, drawCount + #endif + ); + Containers::Optional geom; vert.addSource("#define TWO_DIMENSIONS\n") /* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when @@ -439,19 +437,19 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags frag.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("MeshVisualizer.frag")); + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - Containers::Optional geom; if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) { geom = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Geometry); (*geom) .addSource("#define WIREFRAME_RENDERING\n#define MAX_VERTICES 3\n") - .addSource(_flags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "") - .addSource(_flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") - .addSource(_flags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "") - .addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") - .addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") - .addSource(_flags & FlagBase::PrimitiveId ? - (_flags >= FlagBase::PrimitiveIdFromVertexId ? + .addSource(baseFlags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "") + .addSource(baseFlags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") + .addSource(baseFlags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "") + .addSource(baseFlags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + .addSource(baseFlags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") + .addSource(baseFlags & FlagBase::PrimitiveId ? + (baseFlags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "#define PRIMITIVE_ID\n") : ""); #ifndef MAGNUM_TARGET_GLES2 @@ -461,8 +459,8 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n" "#define MATERIAL_COUNT {}\n", - _drawCount, - _materialCount)); + drawCount, + materialCount)); geom->addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif @@ -472,48 +470,75 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags static_cast(version); #endif - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(geom) CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, *geom, frag})); - else - #endif - CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); + vert.submitCompile(); + frag.submitCompile(); + if (geom) geom->submitCompile(); - attachShaders({vert, frag}); - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(geom) attachShader(*geom); + MeshVisualizerGL2D out{NoInit}; + out._flags = baseFlags; + #ifndef MAGNUM_TARGET_GLES2 + out._materialCount = materialCount; + out._drawCount = drawCount; #endif + out.attachShaders({vert, frag}); + if (geom) out.attachShader(*geom); + /* ES3 has this done in the shader directly */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) #endif { - bindAttributeLocation(Position::Location, "position"); + out.bindAttributeLocation(Position::Location, "position"); #ifndef MAGNUM_TARGET_GLES2 if(flags >= Flag::ObjectIdTexture) - bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); + out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); if(flags >= Flag::InstancedObjectId) - bindAttributeLocation(ObjectId::Location, "instanceObjectId"); + out.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); #endif if(flags & Flag::InstancedTransformation) - bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); + out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); #ifndef MAGNUM_TARGET_GLES2 if(flags >= Flag::InstancedTextureOffset) - bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); + out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); #endif #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_GLES if(!context.isVersionSupported(GL::Version::GL310)) #endif { - bindAttributeLocation(VertexIndex::Location, "vertexIndex"); + out.bindAttributeLocation(VertexIndex::Location, "vertexIndex"); } #endif } #endif - CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + out.submitLink(); + + return CompileState{std::move(out), std::move(vert), std::move(frag), std::move(geom), flags, version}; +} + +MeshVisualizerGL2D::MeshVisualizerGL2D(Flags flags) : MeshVisualizerGL2D{compile(flags)} {} + +#ifndef MAGNUM_TARGET_GLES2 +MeshVisualizer2D::CompileState MeshVisualizer2D::compile(Flags flags) { + return compile(flags, 1, 1); +} + +MeshVisualizerGL2D::MeshVisualizerGL2D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount) + : MeshVisualizerGL2D{compile(flags, materialCount, drawCount)} {} +#endif + +MeshVisualizer2D::MeshVisualizerGL2D(CompileState&& cs) +: MeshVisualizerGL2D{static_cast(std::move(cs))} { + if (id() == 0) return; + + CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); + + const GL::Context& context = GL::Context::current(); + const GL::Version version = cs._version; + Flags flags = cs._flags; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) @@ -610,10 +635,6 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags #endif } -#ifndef MAGNUM_TARGET_GLES2 -MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): MeshVisualizerGL2D{flags, 1, 1} {} -#endif - MeshVisualizerGL2D& MeshVisualizerGL2D::setViewportSize(const Vector2& size) { /* Not asserting here, since the relation to wireframe is a bit vague. Also it's an ugly hack that should be removed, ideally. */ @@ -674,25 +695,24 @@ MeshVisualizerGL2D& MeshVisualizerGL2D::bindDrawBuffer(GL::Buffer& buffer, const } #endif -MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags +MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags #ifndef MAGNUM_TARGET_GLES2 , const UnsignedInt materialCount, const UnsignedInt drawCount #endif -): Implementation::MeshVisualizerGLBase{Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags)) - #ifndef MAGNUM_TARGET_GLES2 - , materialCount, drawCount - #endif -} { +) { + FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags)); + assertExtensions(baseFlags); + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), - "Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", ); + "Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", CompileState{NoCreate}); CORRADE_ASSERT(!(flags & Flag::NoGeometryShader && flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection)), - "Shaders::MeshVisualizerGL3D: geometry shader has to be enabled when rendering TBN direction", ); + "Shaders::MeshVisualizerGL3D: geometry shader has to be enabled when rendering TBN direction", CompileState{NoCreate}); CORRADE_ASSERT(!(flags & Flag::BitangentDirection && flags & Flag::BitangentFromTangentDirection), - "Shaders::MeshVisualizerGL3D: Flag::BitangentDirection and Flag::BitangentFromTangentDirection are mutually exclusive", ); + "Shaders::MeshVisualizerGL3D: Flag::BitangentDirection and Flag::BitangentFromTangentDirection are mutually exclusive", CompileState{NoCreate}); #elif !defined(MAGNUM_TARGET_GLES2) CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), - "Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", ); + "Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", CompileState{NoCreate}); #else CORRADE_ASSERT(flags & (Flag::Wireframe & ~Flag::NoGeometryShader), "Shaders::MeshVisualizerGL3D: at least Flag::Wireframe has to be enabled", ); @@ -700,7 +720,7 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) CORRADE_ASSERT(!(flags >= Flag::InstancedObjectId) || !(flags & Flag::BitangentDirection), - "Shaders::MeshVisualizerGL3D: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", ); + "Shaders::MeshVisualizerGL3D: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", CompileState{NoCreate}); #endif /* Has to be here and not in the base class in order to have it exit the @@ -708,9 +728,9 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags otherwise */ #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, - "Shaders::MeshVisualizerGL3D: material count can't be zero", ); + "Shaders::MeshVisualizerGL3D: material count can't be zero", CompileState{NoCreate}); CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, - "Shaders::MeshVisualizerGL3D: draw count can't be zero", ); + "Shaders::MeshVisualizerGL3D: draw count can't be zero", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES @@ -720,7 +740,12 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags Utility::Resource rs{"MagnumShadersGL"}; GL::Shader vert{NoCreate}; GL::Shader frag{NoCreate}; - const GL::Version version = setupShaders(vert, frag, rs); + const GL::Version version = setupShaders(vert, frag, rs, baseFlags + #ifndef MAGNUM_TARGET_GLES2 + , materialCount, drawCount + #endif + ); + Containers::Optional geom; /* Expands the check done for wireframe in MeshVisualizerBase with TBN */ #ifndef MAGNUM_TARGET_GLES @@ -768,7 +793,6 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags .addSource(rs.getString("MeshVisualizer.frag")); #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - Containers::Optional geom; if(flags & (Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection) && !(flags & Flag::NoGeometryShader)) { Int maxVertices = 0; if(flags & Flag::Wireframe) maxVertices += 3; @@ -781,13 +805,13 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags (*geom) .addSource(Utility::formatString("#define MAX_VERTICES {}\n", maxVertices)) .addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") - .addSource(_flags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "") - .addSource(_flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") - .addSource(_flags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "") - .addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") - .addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") - .addSource(_flags & FlagBase::PrimitiveId ? - (_flags >= FlagBase::PrimitiveIdFromVertexId ? + .addSource(baseFlags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "") + .addSource(baseFlags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") + .addSource(baseFlags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "") + .addSource(baseFlags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + .addSource(baseFlags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") + .addSource(baseFlags & FlagBase::PrimitiveId ? + (baseFlags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "#define PRIMITIVE_ID\n") : "") .addSource(flags & Flag::TangentDirection ? "#define TANGENT_DIRECTION\n" : "") @@ -800,8 +824,8 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n" "#define MATERIAL_COUNT {}\n", - _drawCount, - _materialCount)); + drawCount, + materialCount)); geom->addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif @@ -811,50 +835,53 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags static_cast(version); #endif - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(geom) CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, *geom, frag})); - else - #endif - CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); + vert.submitCompile(); + frag.submitCompile(); + if (geom) geom->submitCompile(); - attachShaders({vert, frag}); - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(geom) attachShader(*geom); + MeshVisualizerGL3D out{NoInit}; + out._flags = baseFlags; + #ifndef MAGNUM_TARGET_GLES2 + out._materialCount = materialCount; + out._drawCount = drawCount; #endif + out.attachShaders({vert, frag}); + if (geom) out.attachShader(*geom); + /* ES3 has this done in the shader directly */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) #endif { - bindAttributeLocation(Position::Location, "position"); + out.bindAttributeLocation(Position::Location, "position"); #ifndef MAGNUM_TARGET_GLES2 if(flags >= Flag::ObjectIdTexture) - bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); + out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); if(flags >= Flag::InstancedObjectId) - bindAttributeLocation(ObjectId::Location, "instanceObjectId"); + out.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); #endif if(flags & Flag::InstancedTransformation) { - bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); + out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) if(flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection)) - bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix"); + out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix"); #endif } #ifndef MAGNUM_TARGET_GLES2 if(flags >= Flag::InstancedTextureOffset) - bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); + out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) if(flags & Flag::TangentDirection || flags & Flag::BitangentFromTangentDirection) - bindAttributeLocation(Tangent4::Location, "tangent"); + out.bindAttributeLocation(Tangent4::Location, "tangent"); if(flags & Flag::BitangentDirection) - bindAttributeLocation(Bitangent::Location, "bitangent"); + out.bindAttributeLocation(Bitangent::Location, "bitangent"); if(flags & Flag::NormalDirection || flags & Flag::BitangentFromTangentDirection) - bindAttributeLocation(Normal::Location, "normal"); + out.bindAttributeLocation(Normal::Location, "normal"); #endif #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) @@ -862,13 +889,37 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags if(!context.isVersionSupported(GL::Version::GL310)) #endif { - bindAttributeLocation(VertexIndex::Location, "vertexIndex"); + out.bindAttributeLocation(VertexIndex::Location, "vertexIndex"); } #endif } #endif - CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + out.submitLink(); + + return CompileState{std::move(out), std::move(vert), std::move(frag), std::move(geom), flags, version}; +} + +MeshVisualizerGL3D::MeshVisualizerGL3D(Flags flags) : MeshVisualizerGL3D{compile(flags)} {} + +#ifndef MAGNUM_TARGET_GLES2 +MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags) { + return compile(flags, 1, 1); +} + +MeshVisualizerGL3D::MeshVisualizerGL3D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount) + : MeshVisualizerGL3D{compile(flags, materialCount, drawCount)} {} +#endif + +MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& cs) +: MeshVisualizerGL3D{static_cast(std::move(cs))} { + if (id() == 0) return; + + CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); + + const GL::Context& context = GL::Context::current(); + const GL::Version version = cs._version; + Flags flags = cs._flags; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) @@ -998,10 +1049,6 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags #endif } -#ifndef MAGNUM_TARGET_GLES2 -MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags): MeshVisualizerGL3D{flags, 1, 1} {} -#endif - MeshVisualizerGL3D& MeshVisualizerGL3D::setTransformationMatrix(const Matrix4& matrix) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags() >= Flag::UniformBuffers), diff --git a/src/Magnum/Shaders/MeshVisualizerGL.h b/src/Magnum/Shaders/MeshVisualizerGL.h index b217f1d395..33ec8e3298 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.h +++ b/src/Magnum/Shaders/MeshVisualizerGL.h @@ -32,8 +32,10 @@ #include +#include #include "Magnum/DimensionTraits.h" #include "Magnum/GL/AbstractShaderProgram.h" +#include "Magnum/GL/Shader.h" #include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/visibility.h" @@ -69,14 +71,17 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGLBase: public GL::AbstractShaderProgr CORRADE_ENUMSET_FRIEND_OPERATORS(FlagsBase) - explicit MeshVisualizerGLBase(FlagsBase flags + explicit MeshVisualizerGLBase(NoInitT) {} + + 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 #ifndef MAGNUM_TARGET_GLES2 , UnsignedInt materialCount, UnsignedInt drawCount #endif ); - explicit MeshVisualizerGLBase(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} - - MAGNUM_SHADERS_LOCAL GL::Version setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs) const; #ifndef MAGNUM_TARGET_GLES2 MeshVisualizerGLBase& setTextureMatrix(const Matrix3& matrix); @@ -505,6 +510,20 @@ 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; @@ -862,9 +881,26 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua #endif private: + explicit MeshVisualizerGL2D(NoInitT) : Implementation::MeshVisualizerGLBase{NoInit} {} + Int _transformationProjectionMatrixUniform{9}; }; +class MeshVisualizerGL2D::CompileState : public MeshVisualizerGL2D { +private: + 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} {} + + GL::Shader _vert, _frag; + Containers::Optional _geom; + Flags _flags; + GL::Version _version; +}; + /** @brief 3D mesh visualization OpenGL shader @m_since_latest @@ -1639,7 +1675,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua * @m_deprecated_since{2020,06} Use @ref MeshVisualizerGL3D(Flags) * instead. */ - explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(Flags) instead") MeshVisualizerGL3D(): MeshVisualizerGL3D{{}} {} + explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(Flags) instead") MeshVisualizerGL3D(): MeshVisualizerGL3D{Flags{}} {} #endif #ifndef MAGNUM_TARGET_GLES2 @@ -1698,6 +1734,21 @@ 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 Copying is not allowed */ MeshVisualizerGL3D(const MeshVisualizerGL3D&) = delete; @@ -2326,6 +2377,8 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua #endif private: + explicit MeshVisualizerGL3D(NoInitT) : Implementation::MeshVisualizerGLBase{NoInit} {} + Int _transformationMatrixUniform{9}, _projectionMatrixUniform{10}; #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -2335,6 +2388,22 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua #endif }; +class MeshVisualizerGL3D::CompileState : public MeshVisualizerGL3D { +private: + friend class MeshVisualizerGL3D; + + 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} {} + + GL::Shader _vert, _frag; + Containers::Optional _geom; + Flags _flags; + GL::Version _version; +}; + + /** @debugoperatorclassenum{MeshVisualizerGL2D,MeshVisualizerGL2D::Flag} */ MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, MeshVisualizerGL2D::Flag value); diff --git a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp index 7ac0ac6122..ce92897897 100644 --- a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp +++ b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #ifdef CORRADE_TARGET_APPLE @@ -88,12 +89,16 @@ struct MeshVisualizerGLTest: GL::OpenGLTester { explicit MeshVisualizerGLTest(); void construct2D(); + void construct2DAsync(); #ifndef MAGNUM_TARGET_GLES2 void constructUniformBuffers2D(); + void constructUniformBuffers2DAsync(); #endif void construct3D(); + void construct3DAsync(); #ifndef MAGNUM_TARGET_GLES2 void constructUniformBuffers3D(); + void constructUniformBuffers3DAsync(); #endif void construct2DInvalid(); @@ -1055,17 +1060,23 @@ MeshVisualizerGLTest::MeshVisualizerGLTest() { addInstancedTests({&MeshVisualizerGLTest::construct2D}, Containers::arraySize(ConstructData2D)); + addTests({&MeshVisualizerGLTest::construct2DAsync}); + #ifndef MAGNUM_TARGET_GLES2 addInstancedTests({&MeshVisualizerGLTest::constructUniformBuffers2D}, Containers::arraySize(ConstructUniformBuffersData2D)); + addTests({&MeshVisualizerGLTest::constructUniformBuffers2DAsync}); #endif addInstancedTests({&MeshVisualizerGLTest::construct3D}, Containers::arraySize(ConstructData3D)); + addTests({&MeshVisualizerGLTest::construct3DAsync}); + #ifndef MAGNUM_TARGET_GLES2 addInstancedTests({&MeshVisualizerGLTest::constructUniformBuffers3D}, Containers::arraySize(ConstructUniformBuffersData3D)); + addTests({&MeshVisualizerGLTest::constructUniformBuffers3DAsync}); #endif addInstancedTests({&MeshVisualizerGLTest::construct2DInvalid}, @@ -1403,6 +1414,78 @@ void MeshVisualizerGLTest::construct2D() { MAGNUM_VERIFY_NO_GL_ERROR(); } + +void MeshVisualizerGLTest::construct2DAsync() { + constexpr struct { + const char* name; + MeshVisualizerGL2D::Flags flags; + } data { + "wireframe w/o GS", MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader + }; + setTestCaseDescription(data.name); + + #ifndef MAGNUM_TARGET_GLES + if((data.flags & MeshVisualizerGL2D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); + #endif + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + if(data.flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId && + #ifndef MAGNUM_TARGET_GLES + !GL::Context::current().isVersionSupported(GL::Version::GL300) + #else + !GL::Context::current().isVersionSupported(GL::Version::GLES300) + #endif + ) CORRADE_SKIP("gl_VertexID not supported."); + #endif + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + if(data.flags & MeshVisualizerGL2D::Flag::PrimitiveId && !(data.flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId) && + #ifndef MAGNUM_TARGET_GLES + !GL::Context::current().isVersionSupported(GL::Version::GL320) + #else + !GL::Context::current().isVersionSupported(GL::Version::GLES320) + #endif + ) CORRADE_SKIP("gl_PrimitiveID not supported."); + #endif + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + if((data.flags & MeshVisualizerGL2D::Flag::Wireframe) && !(data.flags & MeshVisualizerGL2D::Flag::NoGeometryShader)) { + #ifndef MAGNUM_TARGET_GLES + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); + #endif + + #ifdef MAGNUM_TARGET_GLES + if(GL::Context::current().isExtensionSupported()) + CORRADE_INFO("Using" << GL::Extensions::NV::shader_noperspective_interpolation::string()); + #endif + } + #endif + + auto compileState = MeshVisualizerGL2D::compile(data.flags); + CORRADE_COMPARE(compileState.flags(), data.flags); + + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + + MeshVisualizerGL2D shader{std::move(compileState)}; + CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} + #ifndef MAGNUM_TARGET_GLES2 void MeshVisualizerGLTest::constructUniformBuffers2D() { auto&& data = ConstructUniformBuffersData2D[testCaseInstanceId()]; @@ -1480,6 +1563,99 @@ void MeshVisualizerGLTest::constructUniformBuffers2D() { MAGNUM_VERIFY_NO_GL_ERROR(); } + + +void MeshVisualizerGLTest::constructUniformBuffers2DAsync() { + constexpr struct { + const char* name; + MeshVisualizerGL2D::Flags flags; + UnsignedInt materialCount, drawCount; + } data { + "multidraw with wireframe w/o GS and vertex ID", MeshVisualizerGL2D::Flag::MultiDraw|MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader|MeshVisualizerGL2D::Flag::VertexId, 8, 55 + }; + setTestCaseDescription(data.name); + + #ifndef MAGNUM_TARGET_GLES + if((data.flags & MeshVisualizerGL2D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); + #endif + + #ifndef MAGNUM_TARGET_WEBGL + if(data.flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId && + #ifndef MAGNUM_TARGET_GLES + !GL::Context::current().isVersionSupported(GL::Version::GL300) + #else + !GL::Context::current().isVersionSupported(GL::Version::GLES300) + #endif + ) CORRADE_SKIP("gl_VertexID not supported."); + #endif + + #ifndef MAGNUM_TARGET_WEBGL + if(data.flags & MeshVisualizerGL2D::Flag::PrimitiveId && !(data.flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId) && + #ifndef MAGNUM_TARGET_GLES + !GL::Context::current().isVersionSupported(GL::Version::GL320) + #else + !GL::Context::current().isVersionSupported(GL::Version::GLES320) + #endif + ) CORRADE_SKIP("gl_PrimitiveID not supported."); + #endif + + #ifndef MAGNUM_TARGET_WEBGL + if((data.flags & MeshVisualizerGL2D::Flag::Wireframe) && !(data.flags & MeshVisualizerGL2D::Flag::NoGeometryShader)) { + #ifndef MAGNUM_TARGET_GLES + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); + #endif + + #ifdef MAGNUM_TARGET_GLES + if(GL::Context::current().isExtensionSupported()) + CORRADE_INFO("Using" << GL::Extensions::NV::shader_noperspective_interpolation::string()); + #endif + } + #endif + + #ifndef MAGNUM_TARGET_GLES + if(data.flags & MeshVisualizerGL2D::Flag::UniformBuffers && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); + #endif + + if(data.flags >= MeshVisualizerGL2D::Flag::MultiDraw) { + #ifndef MAGNUM_TARGET_GLES + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); + #elif !defined(MAGNUM_TARGET_WEBGL) + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); + #endif + } + + auto compileState = MeshVisualizerGL2D::compile(data.flags, data.materialCount, data.drawCount); + CORRADE_COMPARE(compileState.flags(), data.flags); + CORRADE_COMPARE(compileState.materialCount(), data.materialCount); + CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + + MeshVisualizerGL2D shader{std::move(compileState)}; + CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} #endif void MeshVisualizerGLTest::construct3D() { @@ -1541,6 +1717,77 @@ void MeshVisualizerGLTest::construct3D() { MAGNUM_VERIFY_NO_GL_ERROR(); } +void MeshVisualizerGLTest::construct3DAsync() { + constexpr struct { + const char* name; + MeshVisualizerGL3D::Flags flags; + } data { + "object ID texture array", MeshVisualizerGL3D::Flag::ObjectIdTexture|MeshVisualizerGL3D::Flag::TextureArrays + }; + setTestCaseDescription(data.name); + + #ifndef MAGNUM_TARGET_GLES + if((data.flags & MeshVisualizerGL3D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); + #endif + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + if(data.flags >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId && + #ifndef MAGNUM_TARGET_GLES + !GL::Context::current().isVersionSupported(GL::Version::GL300) + #else + !GL::Context::current().isVersionSupported(GL::Version::GLES300) + #endif + ) CORRADE_SKIP("gl_VertexID not supported."); + #endif + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + if(data.flags & MeshVisualizerGL3D::Flag::PrimitiveId && !(data.flags >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId) && + #ifndef MAGNUM_TARGET_GLES + !GL::Context::current().isVersionSupported(GL::Version::GL320) + #else + !GL::Context::current().isVersionSupported(GL::Version::GLES320) + #endif + ) CORRADE_SKIP("gl_PrimitiveID not supported."); + #endif + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + if(((data.flags & MeshVisualizerGL3D::Flag::Wireframe) && !(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader)) || (data.flags & (MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::BitangentDirection|MeshVisualizerGL3D::Flag::BitangentFromTangentDirection|MeshVisualizerGL3D::Flag::NormalDirection))) { + #ifndef MAGNUM_TARGET_GLES + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); + #endif + + #ifdef MAGNUM_TARGET_GLES + if(GL::Context::current().isExtensionSupported()) + CORRADE_INFO("Using" << GL::Extensions::NV::shader_noperspective_interpolation::string()); + #endif + } + #endif + + auto compileState = MeshVisualizerGL3D::compile(data.flags); + CORRADE_COMPARE(compileState.flags(), data.flags); + + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + + MeshVisualizerGL3D shader{data.flags}; + CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_VERIFY(compileState.isLinkFinished()); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} + #ifndef MAGNUM_TARGET_GLES2 void MeshVisualizerGLTest::constructUniformBuffers3D() { auto&& data = ConstructUniformBuffersData3D[testCaseInstanceId()]; @@ -1618,6 +1865,98 @@ void MeshVisualizerGLTest::constructUniformBuffers3D() { MAGNUM_VERIFY_NO_GL_ERROR(); } + +void MeshVisualizerGLTest::constructUniformBuffers3DAsync() { + constexpr struct { + const char* name; + MeshVisualizerGL3D::Flags flags; + UnsignedInt materialCount, drawCount; + } data { + "multidraw with wireframe w/o GS and vertex ID", MeshVisualizerGL3D::Flag::MultiDraw|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader|MeshVisualizerGL3D::Flag::VertexId, 6, 28 + }; + setTestCaseDescription(data.name); + + #ifndef MAGNUM_TARGET_GLES + if((data.flags & MeshVisualizerGL3D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); + #endif + + #ifndef MAGNUM_TARGET_WEBGL + if(data.flags >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId && + #ifndef MAGNUM_TARGET_GLES + !GL::Context::current().isVersionSupported(GL::Version::GL300) + #else + !GL::Context::current().isVersionSupported(GL::Version::GLES300) + #endif + ) CORRADE_SKIP("gl_VertexID not supported."); + #endif + + #ifndef MAGNUM_TARGET_WEBGL + if(data.flags & MeshVisualizerGL3D::Flag::PrimitiveId && !(data.flags >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId) && + #ifndef MAGNUM_TARGET_GLES + !GL::Context::current().isVersionSupported(GL::Version::GL320) + #else + !GL::Context::current().isVersionSupported(GL::Version::GLES320) + #endif + ) CORRADE_SKIP("gl_PrimitiveID not supported."); + #endif + + #ifndef MAGNUM_TARGET_WEBGL + if(((data.flags & MeshVisualizerGL3D::Flag::Wireframe) && !(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader)) || (data.flags & (MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::BitangentDirection|MeshVisualizerGL3D::Flag::BitangentFromTangentDirection|MeshVisualizerGL3D::Flag::NormalDirection))) { + #ifndef MAGNUM_TARGET_GLES + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); + #endif + + #ifdef MAGNUM_TARGET_GLES + if(GL::Context::current().isExtensionSupported()) + CORRADE_INFO("Using" << GL::Extensions::NV::shader_noperspective_interpolation::string()); + #endif + } + #endif + + #ifndef MAGNUM_TARGET_GLES + if(data.flags & MeshVisualizerGL3D::Flag::UniformBuffers && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); + #endif + + if(data.flags >= MeshVisualizerGL3D::Flag::MultiDraw) { + #ifndef MAGNUM_TARGET_GLES + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); + #elif !defined(MAGNUM_TARGET_WEBGL) + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); + #endif + } + + auto compileState = MeshVisualizerGL3D::compile(data.flags, data.materialCount, data.drawCount); + CORRADE_COMPARE(compileState.flags(), data.flags); + CORRADE_COMPARE(compileState.materialCount(), data.materialCount); + CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + + MeshVisualizerGL3D shader{std::move(compileState)}; + CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} #endif void MeshVisualizerGLTest::construct2DInvalid() { diff --git a/src/Magnum/Shaders/VectorGL.cpp b/src/Magnum/Shaders/VectorGL.cpp index d5f8224fdf..af6b38550d 100644 --- a/src/Magnum/Shaders/VectorGL.cpp +++ b/src/Magnum/Shaders/VectorGL.cpp @@ -138,7 +138,7 @@ template typename VectorGL::CompileState Vec vert.submitCompile(); frag.submitCompile(); - + VectorGL out{NoInit}; out._flags = flags; #ifndef MAGNUM_TARGET_GLES2 @@ -162,10 +162,9 @@ template typename VectorGL::CompileState Vec out.submitLink(); return CompileState{std::move(out), std::move(vert), std::move(frag), version}; - } -template VectorGL::VectorGL(CompileState&& cs) +template VectorGL::VectorGL(CompileState&& cs) : VectorGL{static_cast(std::move(cs))} { if (id() == 0) return; From 3c899c16319f0ba8e1b5197f58166a2ad54c044f Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Sat, 13 Aug 2022 11:53:41 +0300 Subject: [PATCH 13/27] Small fixes --- src/Magnum/Shaders/MeshVisualizerGL.cpp | 8 +++++++- src/Magnum/Shaders/VectorGL.cpp | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Shaders/MeshVisualizerGL.cpp b/src/Magnum/Shaders/MeshVisualizerGL.cpp index eaec0dd12b..f428d83023 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.cpp +++ b/src/Magnum/Shaders/MeshVisualizerGL.cpp @@ -633,6 +633,9 @@ MeshVisualizer2D::MeshVisualizerGL2D(CompileState&& cs) #endif } #endif + + static_cast(context); + static_cast(version); } MeshVisualizerGL2D& MeshVisualizerGL2D::setViewportSize(const Vector2& size) { @@ -715,7 +718,7 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags "Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", CompileState{NoCreate}); #else CORRADE_ASSERT(flags & (Flag::Wireframe & ~Flag::NoGeometryShader), - "Shaders::MeshVisualizerGL3D: at least Flag::Wireframe has to be enabled", ); + "Shaders::MeshVisualizerGL3D: at least Flag::Wireframe has to be enabled", CompileState{NoCreate}); #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -1047,6 +1050,9 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& cs) #endif } #endif + + static_cast(context); + static_cast(version); } MeshVisualizerGL3D& MeshVisualizerGL3D::setTransformationMatrix(const Matrix4& matrix) { diff --git a/src/Magnum/Shaders/VectorGL.cpp b/src/Magnum/Shaders/VectorGL.cpp index af6b38550d..16d1e70404 100644 --- a/src/Magnum/Shaders/VectorGL.cpp +++ b/src/Magnum/Shaders/VectorGL.cpp @@ -225,6 +225,9 @@ template VectorGL::VectorGL(CompileState&& c setColor(Color4{1.0f}); } #endif + + static_cast(context); + static_cast(version); } template VectorGL& VectorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { From cf9b90ff9b7304cf72fba9bf775dca60d4bc5c92 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Sat, 13 Aug 2022 14:00:53 +0300 Subject: [PATCH 14/27] PhongGL & tests --- src/Magnum/Shaders/PhongGL.cpp | 162 +++++++++++++----------- src/Magnum/Shaders/PhongGL.h | 30 +++++ src/Magnum/Shaders/Test/PhongGLTest.cpp | 105 ++++++++++++++- 3 files changed, 225 insertions(+), 72 deletions(-) diff --git a/src/Magnum/Shaders/PhongGL.cpp b/src/Magnum/Shaders/PhongGL.cpp index a235614630..125e6a5529 100644 --- a/src/Magnum/Shaders/PhongGL.cpp +++ b/src/Magnum/Shaders/PhongGL.cpp @@ -37,7 +37,6 @@ #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" -#include "Magnum/GL/Shader.h" #include "Magnum/GL/Texture.h" #include "Magnum/Math/Color.h" #include "Magnum/Math/Matrix3.h" @@ -74,21 +73,11 @@ namespace { #endif } -PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount +PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt lightCount #ifndef MAGNUM_TARGET_GLES2 , const UnsignedInt materialCount, const UnsignedInt drawCount #endif -): - _flags{flags}, - _lightCount{lightCount}, - #ifndef MAGNUM_TARGET_GLES2 - _materialCount{materialCount}, - _drawCount{drawCount}, - #endif - _lightColorsUniform{_lightPositionsUniform + Int(lightCount)}, - _lightSpecularColorsUniform{_lightPositionsUniform + 2*Int(lightCount)}, - _lightRangesUniform{_lightPositionsUniform + 3*Int(lightCount)} -{ +) { { const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) #ifndef MAGNUM_TARGET_GLES2 @@ -96,32 +85,32 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount #endif ; CORRADE_ASSERT(textureTransformationNotEnabledOrTextured, - "Shaders::PhongGL: texture transformation enabled but the shader is not textured", ); + "Shaders::PhongGL: texture transformation enabled but the shader is not textured", CompileState{NoCreate}); } #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags >= Flag::InstancedObjectId) || !(flags & Flag::Bitangent), - "Shaders::PhongGL: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", ); + "Shaders::PhongGL: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, - "Shaders::PhongGL: material count can't be zero", ); + "Shaders::PhongGL: material count can't be zero", CompileState{NoCreate}); CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, - "Shaders::PhongGL: draw count can't be zero", ); + "Shaders::PhongGL: draw count can't be zero", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags & Flag::TextureArrays) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) || flags >= Flag::ObjectIdTexture, - "Shaders::PhongGL: texture arrays enabled but the shader is not textured", ); + "Shaders::PhongGL: texture arrays enabled but the shader is not textured", CompileState{NoCreate}); CORRADE_ASSERT(!(flags & Flag::UniformBuffers) || !(flags & Flag::TextureArrays) || flags >= (Flag::TextureArrays|Flag::TextureTransformation), - "Shaders::PhongGL: texture arrays require texture transformation enabled as well if uniform buffers are used", ); + "Shaders::PhongGL: texture arrays require texture transformation enabled as well if uniform buffers are used", CompileState{NoCreate}); CORRADE_ASSERT(!(flags & Flag::LightCulling) || (flags & Flag::UniformBuffers), - "Shaders::PhongGL: light culling requires uniform buffers to be enabled", ); + "Shaders::PhongGL: light culling requires uniform buffers to be enabled", CompileState{NoCreate}); #endif CORRADE_ASSERT(!(flags & Flag::SpecularTexture) || !(flags & (Flag::NoSpecular)), - "Shaders::PhongGL: specular texture requires the shader to not have specular disabled", ); + "Shaders::PhongGL: specular texture requires the shader to not have specular disabled", CompileState{NoCreate}); #ifndef MAGNUM_TARGET_GLES if(flags >= Flag::UniformBuffers) @@ -154,7 +143,7 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount #ifndef MAGNUM_TARGET_GLES CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || context.isExtensionSupported(), - "Shaders::PhongGL: uniform buffers require" << GL::Extensions::ARB::uniform_buffer_object::string(), ); + "Shaders::PhongGL: uniform buffers require" << GL::Extensions::ARB::uniform_buffer_object::string(), CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES @@ -163,6 +152,17 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); #endif + PhongGL out{NoInit}; + out._flags = flags; + out._lightCount = lightCount; + out._lightColorsUniform = out._lightPositionsUniform + Int(lightCount); + out._lightSpecularColorsUniform = out._lightPositionsUniform + 2*Int(lightCount); + out._lightRangesUniform = out._lightPositionsUniform + 3*Int(lightCount); + #ifndef MAGNUM_TARGET_GLES2 + out._materialCount = materialCount; + out._drawCount = drawCount; + #endif + GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); @@ -283,9 +283,9 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount "#define LIGHT_SPECULAR_COLORS_LOCATION {}\n" "#define LIGHT_RANGES_LOCATION {}\n", lightCount, - _lightPositionsUniform + lightCount, - _lightPositionsUniform + 2*lightCount, - _lightPositionsUniform + 3*lightCount)); + out._lightPositionsUniform + lightCount, + out._lightPositionsUniform + 2*lightCount, + out._lightPositionsUniform + 3*lightCount)); } #ifndef MAGNUM_TARGET_GLES if(!(flags >= Flag::UniformBuffers) && lightCount) @@ -294,9 +294,10 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount frag.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("Phong.frag")); - CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); + vert.submitCompile(); + frag.submitCompile(); - attachShaders({vert, frag}); + out.attachShaders({vert, frag}); /* ES3 has this done in the shader directly and doesn't even provide bindFragmentDataLocation() */ @@ -305,103 +306,115 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount if(!context.isExtensionSupported(version)) #endif { - bindAttributeLocation(Position::Location, "position"); + out.bindAttributeLocation(Position::Location, "position"); if(lightCount) - bindAttributeLocation(Normal::Location, "normal"); + out.bindAttributeLocation(Normal::Location, "normal"); if((flags & Flag::NormalTexture) && lightCount) { - bindAttributeLocation(Tangent::Location, "tangent"); + out.bindAttributeLocation(Tangent::Location, "tangent"); if(flags & Flag::Bitangent) - bindAttributeLocation(Bitangent::Location, "bitangent"); + out.bindAttributeLocation(Bitangent::Location, "bitangent"); } if(flags & Flag::VertexColor) - bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ + out.bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ if(flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture) #ifndef MAGNUM_TARGET_GLES2 || flags >= Flag::ObjectIdTexture #endif ) - bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); + out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); #ifndef MAGNUM_TARGET_GLES2 if(flags & Flag::ObjectId) { - bindFragmentDataLocation(ColorOutput, "color"); - bindFragmentDataLocation(ObjectIdOutput, "objectId"); + out.bindFragmentDataLocation(ColorOutput, "color"); + out.bindFragmentDataLocation(ObjectIdOutput, "objectId"); } if(flags >= Flag::InstancedObjectId) - bindAttributeLocation(ObjectId::Location, "instanceObjectId"); + out.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); #endif if(flags & Flag::InstancedTransformation) { - bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); + out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); if(lightCount) - bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix"); + out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix"); } if(flags >= Flag::InstancedTextureOffset) - bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); + out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); } #endif - CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + out.submitLink(); + + 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; + + CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); + + const GL::Context& context = GL::Context::current(); + const GL::Version version = cs._version; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) #endif { #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::UniformBuffers) { if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset"); } else #endif { _transformationMatrixUniform = uniformLocation("transformationMatrix"); - if(flags & Flag::TextureTransformation) + if(_flags & Flag::TextureTransformation) _textureMatrixUniform = uniformLocation("textureMatrix"); #ifndef MAGNUM_TARGET_GLES2 - if(flags & Flag::TextureArrays) + if(_flags & Flag::TextureArrays) _textureLayerUniform = uniformLocation("textureLayer"); #endif _projectionMatrixUniform = uniformLocation("projectionMatrix"); _ambientColorUniform = uniformLocation("ambientColor"); - if(lightCount) { + if(_lightCount) { _normalMatrixUniform = uniformLocation("normalMatrix"); _diffuseColorUniform = uniformLocation("diffuseColor"); - if(!(flags & Flag::NoSpecular)) { + if(!(_flags & Flag::NoSpecular)) { _specularColorUniform = uniformLocation("specularColor"); _shininessUniform = uniformLocation("shininess"); } - if(flags & Flag::NormalTexture) + if(_flags & Flag::NormalTexture) _normalTextureScaleUniform = uniformLocation("normalTextureScale"); _lightPositionsUniform = uniformLocation("lightPositions"); _lightColorsUniform = uniformLocation("lightColors"); - if(!(flags & Flag::NoSpecular)) + if(!(_flags & Flag::NoSpecular)) _lightSpecularColorsUniform = uniformLocation("lightSpecularColors"); _lightRangesUniform = uniformLocation("lightRanges"); } - if(flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask"); + if(_flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask"); #ifndef MAGNUM_TARGET_GLES2 - if(flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId"); + if(_flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId"); #endif } } #ifndef MAGNUM_TARGET_GLES - if(flags && !context.isExtensionSupported(version)) + if(_flags && !context.isExtensionSupported(version)) #endif { - if(flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureUnit); - if(lightCount) { - if(flags & Flag::DiffuseTexture) setUniform(uniformLocation("diffuseTexture"), DiffuseTextureUnit); - if(flags & Flag::SpecularTexture) setUniform(uniformLocation("specularTexture"), SpecularTextureUnit); - if(flags & Flag::NormalTexture) setUniform(uniformLocation("normalTexture"), NormalTextureUnit); + if(_flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureUnit); + if(_lightCount) { + if(_flags & Flag::DiffuseTexture) setUniform(uniformLocation("diffuseTexture"), DiffuseTextureUnit); + if(_flags & Flag::SpecularTexture) setUniform(uniformLocation("specularTexture"), SpecularTextureUnit); + if(_flags & Flag::NormalTexture) setUniform(uniformLocation("normalTexture"), NormalTextureUnit); } #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit); - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit); + if(_flags >= Flag::UniformBuffers) { setUniformBlockBinding(uniformBlockIndex("Projection"), ProjectionBufferBinding); setUniformBlockBinding(uniformBlockIndex("Transformation"), TransformationBufferBinding); setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding); setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding); - if(flags & Flag::TextureTransformation) + if(_flags & Flag::TextureTransformation) setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding); - if(lightCount) + if(_lightCount) setUniformBlockBinding(uniformBlockIndex("Light"), LightBufferBinding); } #endif @@ -410,44 +423,51 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ #ifdef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::UniformBuffers) { /* Draw offset is zero by default */ } else #endif { /* Default to fully opaque white so we can see the textures */ - if(flags & Flag::AmbientTexture) setAmbientColor(Magnum::Color4{1.0f}); + if(_flags & Flag::AmbientTexture) setAmbientColor(Magnum::Color4{1.0f}); else setAmbientColor(Magnum::Color4{0.0f}); setTransformationMatrix(Matrix4{Math::IdentityInit}); setProjectionMatrix(Matrix4{Math::IdentityInit}); - if(lightCount) { + if(_lightCount) { setDiffuseColor(Magnum::Color4{1.0f}); - if(!(flags & Flag::NoSpecular)) { + if(!(_flags & Flag::NoSpecular)) { setSpecularColor(Magnum::Color4{1.0f, 0.0f}); setShininess(80.0f); } - if(flags & Flag::NormalTexture) + if(_flags & Flag::NormalTexture) setNormalTextureScale(1.0f); - setLightPositions(Containers::Array{DirectInit, lightCount, Vector4{0.0f, 0.0f, 1.0f, 0.0f}}); - Containers::Array colors{DirectInit, lightCount, Magnum::Color3{1.0f}}; + setLightPositions(Containers::Array{DirectInit, _lightCount, Vector4{0.0f, 0.0f, 1.0f, 0.0f}}); + Containers::Array colors{DirectInit, _lightCount, Magnum::Color3{1.0f}}; setLightColors(colors); - if(!(flags & Flag::NoSpecular)) + if(!(_flags & Flag::NoSpecular)) setLightSpecularColors(colors); - setLightRanges(Containers::Array{DirectInit, lightCount, Constants::inf()}); + setLightRanges(Containers::Array{DirectInit, _lightCount, Constants::inf()}); /* Light position is zero by default */ setNormalMatrix(Matrix3x3{Math::IdentityInit}); } - if(flags & Flag::TextureTransformation) + if(_flags & Flag::TextureTransformation) setTextureMatrix(Matrix3{Math::IdentityInit}); /* Texture layer is zero by default */ - if(flags & Flag::AlphaMask) setAlphaMask(0.5f); + if(_flags & Flag::AlphaMask) setAlphaMask(0.5f); /* Object ID is zero by default */ } #endif } +PhongGL::PhongGL(Flags flags, UnsignedInt lightCount) : PhongGL{compile(flags, lightCount)} {} + #ifndef MAGNUM_TARGET_GLES2 -PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): PhongGL{flags, lightCount, 1, 1} {} +PhongGL::CompileState PhongGL::compile(Flags flags, UnsignedInt lightCount) { + return compile(flags, lightCount, 1, 1); +} + +PhongGL::PhongGL(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, 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 1a59c564bb..860e5f56c9 100644 --- a/src/Magnum/Shaders/PhongGL.h +++ b/src/Magnum/Shaders/PhongGL.h @@ -31,6 +31,7 @@ */ #include "Magnum/GL/AbstractShaderProgram.h" +#include "Magnum/GL/Shader.h" #include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/visibility.h" @@ -821,6 +822,20 @@ 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; @@ -1744,6 +1759,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { #endif private: + explicit PhongGL(NoInitT) {} + /* Prevent accidentally calling irrelevant functions */ #ifndef MAGNUM_TARGET_GLES using GL::AbstractShaderProgram::drawTransformFeedback; @@ -1784,6 +1801,19 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { #endif }; +class PhongGL::CompileState : public PhongGL { +private: + 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} {} + + GL::Shader _vert, _frag; + GL::Version _version; +}; + /** @debugoperatorclassenum{PhongGL,PhongGL::Flag} */ MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, PhongGL::Flag value); diff --git a/src/Magnum/Shaders/Test/PhongGLTest.cpp b/src/Magnum/Shaders/Test/PhongGLTest.cpp index e6414a2c25..6057fd7fe8 100644 --- a/src/Magnum/Shaders/Test/PhongGLTest.cpp +++ b/src/Magnum/Shaders/Test/PhongGLTest.cpp @@ -31,12 +31,12 @@ #include #include #include +#include #include #include #ifdef CORRADE_TARGET_APPLE #include -#include /* isSandboxed() */ #endif #include "Magnum/Image.h" @@ -83,8 +83,10 @@ struct PhongGLTest: GL::OpenGLTester { explicit PhongGLTest(); void construct(); + void constructAsync(); #ifndef MAGNUM_TARGET_GLES2 void constructUniformBuffers(); + void constructUniformBuffersAsync(); #endif void constructMove(); @@ -927,9 +929,13 @@ PhongGLTest::PhongGLTest() { addInstancedTests({&PhongGLTest::construct}, Containers::arraySize(ConstructData)); + addTests({&PhongGLTest::constructAsync}); + #ifndef MAGNUM_TARGET_GLES2 addInstancedTests({&PhongGLTest::constructUniformBuffers}, Containers::arraySize(ConstructUniformBuffersData)); + + addTests({&PhongGLTest::constructUniformBuffersAsync}); #endif addTests({ @@ -1192,6 +1198,45 @@ void PhongGLTest::construct() { MAGNUM_VERIFY_NO_GL_ERROR(); } +void PhongGLTest::constructAsync() { + constexpr struct { + const char* name; + PhongGL::Flags flags; + UnsignedInt lightCount; + } data { + "instanced specular texture offset", PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset, 3 + }; + setTestCaseDescription(data.name); + + #ifndef MAGNUM_TARGET_GLES + if((data.flags & PhongGL::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); + if((data.flags & PhongGL::Flag::TextureArrays) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::texture_array::string() << "is not supported."); + #endif + + auto compileState = PhongGL::compile(data.flags, data.lightCount); + CORRADE_COMPARE(compileState.flags(), data.flags); + CORRADE_COMPARE(compileState.lightCount(), data.lightCount); + + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + + PhongGL shader{std::move(compileState)}; + CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_COMPARE(shader.lightCount(), data.lightCount); + CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} + #ifndef MAGNUM_TARGET_GLES2 void PhongGLTest::constructUniformBuffers() { auto&& data = ConstructUniformBuffersData[testCaseInstanceId()]; @@ -1234,6 +1279,64 @@ void PhongGLTest::constructUniformBuffers() { MAGNUM_VERIFY_NO_GL_ERROR(); } + +void PhongGLTest::constructUniformBuffersAsync() { + constexpr struct { + const char* name; + PhongGL::Flags flags; + UnsignedInt lightCount, materialCount, drawCount; + } data { + "multiple lights, materials, draws + light culling", PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling, 8, 8, 24 + }; + setTestCaseDescription(data.name); + + #ifndef MAGNUM_TARGET_GLES + if((data.flags & PhongGL::Flag::UniformBuffers) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); + if((data.flags & PhongGL::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); + if((data.flags & PhongGL::Flag::TextureArrays) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::texture_array::string() << "is not supported."); + #endif + + if(data.flags >= PhongGL::Flag::MultiDraw) { + #ifndef MAGNUM_TARGET_GLES + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); + #elif !defined(MAGNUM_TARGET_WEBGL) + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); + #endif + } + + auto compileState = PhongGL::compile(data.flags, data.lightCount, data.materialCount, data.drawCount); + CORRADE_COMPARE(compileState.flags(), data.flags); + CORRADE_COMPARE(compileState.lightCount(), data.lightCount); + CORRADE_COMPARE(compileState.materialCount(), data.materialCount); + CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + + PhongGL shader{std::move(compileState)}; + CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_COMPARE(shader.lightCount(), data.lightCount); + CORRADE_COMPARE(shader.materialCount(), data.materialCount); + CORRADE_COMPARE(shader.drawCount(), data.drawCount); + CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} #endif void PhongGLTest::constructMove() { From 09ab0ef5795cdae32f5d629d7c61a024737e057a Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Sat, 13 Aug 2022 14:17:26 +0300 Subject: [PATCH 15/27] Fixes --- src/Magnum/Shaders/PhongGL.cpp | 7 +++++-- src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Shaders/PhongGL.cpp b/src/Magnum/Shaders/PhongGL.cpp index 125e6a5529..bc4ef5256c 100644 --- a/src/Magnum/Shaders/PhongGL.cpp +++ b/src/Magnum/Shaders/PhongGL.cpp @@ -345,7 +345,7 @@ 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::PhongGL(CompileState&& cs) : PhongGL{static_cast(std::move(cs))} { if (id() == 0) return; @@ -457,6 +457,9 @@ PhongGL::PhongGL(CompileState&& cs) /* Object ID is zero by default */ } #endif + + static_cast(context); + static_cast(version); } PhongGL::PhongGL(Flags flags, UnsignedInt lightCount) : PhongGL{compile(flags, lightCount)} {} @@ -464,7 +467,7 @@ PhongGL::PhongGL(Flags flags, UnsignedInt lightCount) : PhongGL{compile(flags, l #ifndef MAGNUM_TARGET_GLES2 PhongGL::CompileState PhongGL::compile(Flags flags, UnsignedInt lightCount) { return compile(flags, lightCount, 1, 1); -} +} PhongGL::PhongGL(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, UnsignedInt drawCount) : PhongGL{compile(flags, lightCount, materialCount, drawCount)} {} diff --git a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp index ce92897897..31319306ee 100644 --- a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp +++ b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp @@ -1722,7 +1722,7 @@ void MeshVisualizerGLTest::construct3DAsync() { const char* name; MeshVisualizerGL3D::Flags flags; } data { - "object ID texture array", MeshVisualizerGL3D::Flag::ObjectIdTexture|MeshVisualizerGL3D::Flag::TextureArrays + "wireframe w/o GS", MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader }; setTestCaseDescription(data.name); From fdb1dcaf3bcf4177373ab00994a2da24cd0cb23b Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Mon, 15 Aug 2022 19:18:11 +0300 Subject: [PATCH 16/27] VertexColor & tests --- src/Magnum/Shaders/Test/VertexColorGLTest.cpp | 84 ++++++++++++++++++- src/Magnum/Shaders/VertexColorGL.cpp | 56 ++++++++----- src/Magnum/Shaders/VertexColorGL.h | 37 +++++++- 3 files changed, 153 insertions(+), 24 deletions(-) diff --git a/src/Magnum/Shaders/Test/VertexColorGLTest.cpp b/src/Magnum/Shaders/Test/VertexColorGLTest.cpp index abbd56bf42..233850198d 100644 --- a/src/Magnum/Shaders/Test/VertexColorGLTest.cpp +++ b/src/Magnum/Shaders/Test/VertexColorGLTest.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #ifdef CORRADE_TARGET_APPLE @@ -74,8 +75,10 @@ struct VertexColorGLTest: GL::OpenGLTester { explicit VertexColorGLTest(); template void construct(); + template void constructAsync(); #ifndef MAGNUM_TARGET_GLES2 template void constructUniformBuffers(); + template void constructUniformBuffersAsync(); #endif template void constructMove(); @@ -190,13 +193,19 @@ constexpr struct { VertexColorGLTest::VertexColorGLTest() { addTests({ &VertexColorGLTest::construct<2>, - &VertexColorGLTest::construct<3>}); + &VertexColorGLTest::construct<3>, + &VertexColorGLTest::constructAsync<2>, + &VertexColorGLTest::constructAsync<3>}); #ifndef MAGNUM_TARGET_GLES2 addInstancedTests({ &VertexColorGLTest::constructUniformBuffers<2>, &VertexColorGLTest::constructUniformBuffers<3>}, Containers::arraySize(ConstructUniformBuffersData)); + + addTests({ + &VertexColorGLTest::constructUniformBuffersAsync<2>, + &VertexColorGLTest::constructUniformBuffersAsync<3>}); #endif addTests({ @@ -309,6 +318,28 @@ template void VertexColorGLTest::construct() { MAGNUM_VERIFY_NO_GL_ERROR(); } +template void VertexColorGLTest::constructAsync() { + setTestCaseTemplateName(Utility::format("{}", dimensions)); + + auto compileState = VertexColorGL::compile({}); + + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + + VertexColorGL shader{std::move(compileState)}; + CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} + + #ifndef MAGNUM_TARGET_GLES2 template void VertexColorGLTest::constructUniformBuffers() { setTestCaseTemplateName(Utility::format("{}", dimensions)); @@ -347,6 +378,57 @@ template void VertexColorGLTest::constructUniformBuffers MAGNUM_VERIFY_NO_GL_ERROR(); } + +template void VertexColorGLTest::constructUniformBuffersAsync() { + setTestCaseTemplateName(Utility::format("{}", dimensions)); + + constexpr struct { + const char* name; + VertexColorGL2D::Flags flags; + UnsignedInt drawCount; + } data { + "multiple draws", VertexColorGL2D::Flag::UniformBuffers, 63 + }; + setTestCaseDescription(data.name); + + #ifndef MAGNUM_TARGET_GLES + if((data.flags & VertexColorGL::Flag::UniformBuffers) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); + #endif + + if(data.flags >= VertexColorGL2D::Flag::MultiDraw) { + #ifndef MAGNUM_TARGET_GLES + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); + #elif !defined(MAGNUM_TARGET_WEBGL) + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); + #endif + } + auto compileState = VertexColorGL::compile(data.flags, data.drawCount); + CORRADE_COMPARE(compileState.flags(), data.flags); + CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + + VertexColorGL shader{std::move(compileState)}; + CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_COMPARE(shader.drawCount(), data.drawCount); + CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} #endif template void VertexColorGLTest::constructMove() { diff --git a/src/Magnum/Shaders/VertexColorGL.cpp b/src/Magnum/Shaders/VertexColorGL.cpp index 31d6e48219..70c502facd 100644 --- a/src/Magnum/Shaders/VertexColorGL.cpp +++ b/src/Magnum/Shaders/VertexColorGL.cpp @@ -31,7 +31,6 @@ #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" -#include "Magnum/GL/Shader.h" #include "Magnum/Math/Color.h" #include "Magnum/Math/Matrix3.h" #include "Magnum/Math/Matrix4.h" @@ -57,19 +56,14 @@ namespace { #endif } -template VertexColorGL::VertexColorGL(const Flags flags +template typename VertexColorGL::CompileState VertexColorGL::compile(const Flags flags #ifndef MAGNUM_TARGET_GLES2 , const UnsignedInt drawCount #endif -): - _flags{flags} - #ifndef MAGNUM_TARGET_GLES2 - , _drawCount{drawCount} - #endif -{ +) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, - "Shaders::VertexColorGL: draw count can't be zero", ); + "Shaders::VertexColorGL: draw count can't be zero", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES @@ -121,9 +115,16 @@ template VertexColorGL::VertexColorGL(const frag.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("VertexColor.frag")); - CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); + vert.submitCompile(); + frag.submitCompile(); + + VertexColorGL out{NoInit}; + out._flags = flags; + #ifndef MAGNUM_TARGET_GLES2 + out._drawCount = drawCount; + #endif - attachShaders({vert, frag}); + out.attachShaders({vert, frag}); /* ES3 has this done in the shader directly */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) @@ -131,19 +132,33 @@ template VertexColorGL::VertexColorGL(const if(!context.isExtensionSupported(version)) #endif { - bindAttributeLocation(Position::Location, "position"); - bindAttributeLocation(Color3::Location, "color"); /* Color4 is the same */ + out.bindAttributeLocation(Position::Location, "position"); + out.bindAttributeLocation(Color3::Location, "color"); /* Color4 is the same */ } #endif - CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + out.submitLink(); + + 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; + + CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); + CORRADE_INTERNAL_ASSERT_OUTPUT(cs._vert.checkCompile()); + CORRADE_INTERNAL_ASSERT_OUTPUT(cs._frag.checkCompile()); + + const GL::Context& context = GL::Context::current(); + const GL::Version version = cs._version; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) #endif { #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::UniformBuffers) { if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset"); } else #endif @@ -153,7 +168,7 @@ template VertexColorGL::VertexColorGL(const } #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers + if(_flags >= Flag::UniformBuffers #ifndef MAGNUM_TARGET_GLES && !context.isExtensionSupported(version) #endif @@ -165,7 +180,7 @@ template VertexColorGL::VertexColorGL(const /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ #ifdef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::UniformBuffers) { /* Draw offset is zero by default */ } else #endif @@ -173,11 +188,10 @@ template VertexColorGL::VertexColorGL(const setTransformationProjectionMatrix(MatrixTypeFor{Math::IdentityInit}); } #endif -} -#ifndef MAGNUM_TARGET_GLES2 -template VertexColorGL::VertexColorGL(const Flags flags): VertexColorGL{flags, 1} {} -#endif + static_cast(context); + static_cast(version); +} template VertexColorGL& VertexColorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { #ifndef MAGNUM_TARGET_GLES2 diff --git a/src/Magnum/Shaders/VertexColorGL.h b/src/Magnum/Shaders/VertexColorGL.h index 3ecdd673f7..69ad1e87a3 100644 --- a/src/Magnum/Shaders/VertexColorGL.h +++ b/src/Magnum/Shaders/VertexColorGL.h @@ -32,6 +32,7 @@ #include "Magnum/DimensionTraits.h" #include "Magnum/GL/AbstractShaderProgram.h" +#include "Magnum/GL/Shader.h" #include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/visibility.h" @@ -216,7 +217,7 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ * @ref VertexColorGL(Flags, UnsignedInt) with @p drawCount set to * @cpp 1 @ce. */ - explicit VertexColorGL(Flags flags = {}); + explicit VertexColorGL(Flags flags = {}): VertexColorGL{compile(flags)} {} #ifndef MAGNUM_TARGET_GLES2 /** @@ -247,7 +248,8 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ for this might be too confusing); what if some parameters won't be (unsigned) integers? like a string with shader extensions? make a whole Configuration class? */ - explicit VertexColorGL(Flags flags, UnsignedInt drawCount); + explicit VertexColorGL(Flags flags, UnsignedInt drawCount): + VertexColorGL{compile(flags, drawCount)} {} #endif /** @@ -264,6 +266,22 @@ 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) { + return compile(flags, 1); + } + #endif + /** @brief Copying is not allowed */ VertexColorGL(const VertexColorGL&) = delete; @@ -406,6 +424,8 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ #endif private: + explicit VertexColorGL(NoInitT) {} + /* Prevent accidentally calling irrelevant functions */ #ifndef MAGNUM_TARGET_GLES using GL::AbstractShaderProgram::drawTransformFeedback; @@ -426,6 +446,19 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ #endif }; +template class VertexColorGL::CompileState : public VertexColorGL { +private: + 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} {} + + GL::Shader _vert, _frag; + GL::Version _version; +}; + /** @brief 2D vertex color OpenGL shader @m_since_latest From e3e05cd1fd99ba99a46d4e0449a7be7381ddd584 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Mon, 15 Aug 2022 20:11:35 +0300 Subject: [PATCH 17/27] Small fix in PhongGL construct --- src/Magnum/Shaders/PhongGL.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Magnum/Shaders/PhongGL.cpp b/src/Magnum/Shaders/PhongGL.cpp index bc4ef5256c..c06d396d6b 100644 --- a/src/Magnum/Shaders/PhongGL.cpp +++ b/src/Magnum/Shaders/PhongGL.cpp @@ -78,6 +78,7 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh , const UnsignedInt materialCount, const UnsignedInt drawCount #endif ) { + #ifndef CORRADE_NO_ASSERT { const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) #ifndef MAGNUM_TARGET_GLES2 @@ -87,6 +88,7 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh CORRADE_ASSERT(textureTransformationNotEnabledOrTextured, "Shaders::PhongGL: texture transformation enabled but the shader is not textured", CompileState{NoCreate}); } + #endif #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags >= Flag::InstancedObjectId) || !(flags & Flag::Bitangent), From 511d869413d63e960e2f4942b76e6016e3220c66 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Sun, 21 Aug 2022 22:20:06 +0300 Subject: [PATCH 18/27] DistanceFieldVector & tests. Fix deprecated references --- src/Magnum/Shaders/DistanceFieldVectorGL.cpp | 68 ++++++++----- src/Magnum/Shaders/DistanceFieldVectorGL.h | 31 ++++++ src/Magnum/Shaders/MeshVisualizerGL.cpp | 4 +- .../Test/DistanceFieldVectorGLTest.cpp | 95 +++++++++++++++++++ 4 files changed, 173 insertions(+), 25 deletions(-) diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp index a33a9386d3..a404c52610 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp @@ -31,7 +31,6 @@ #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" -#include "Magnum/GL/Shader.h" #include "Magnum/GL/Texture.h" #include "Magnum/Math/Color.h" #include "Magnum/Math/Matrix3.h" @@ -63,22 +62,16 @@ namespace { #endif } -template DistanceFieldVectorGL::DistanceFieldVectorGL(const Flags flags +template typename DistanceFieldVectorGL::CompileState DistanceFieldVectorGL::compile(const Flags flags #ifndef MAGNUM_TARGET_GLES2 , const UnsignedInt materialCount, const UnsignedInt drawCount #endif -): - _flags{flags} - #ifndef MAGNUM_TARGET_GLES2 - , _materialCount{materialCount}, - _drawCount{drawCount} - #endif -{ +) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, - "Shaders::DistanceFieldVectorGL: material count can't be zero", ); + "Shaders::DistanceFieldVectorGL: material count can't be zero", CompileState{NoCreate}); CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, - "Shaders::DistanceFieldVectorGL: draw count can't be zero", ); + "Shaders::DistanceFieldVectorGL: draw count can't be zero", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES @@ -142,9 +135,17 @@ template DistanceFieldVectorGL::DistanceFiel frag.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("DistanceFieldVector.frag")); - CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); + vert.submitCompile(); + frag.submitCompile(); + + DistanceFieldVectorGL out{NoInit}; + out._flags = flags; + #ifndef MAGNUM_TARGET_GLES2 + out._materialCount = materialCount; + out._drawCount = drawCount; + #endif - attachShaders({vert, frag}); + out.attachShaders({vert, frag}); /* ES3 has this done in the shader directly */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) @@ -152,25 +153,38 @@ template DistanceFieldVectorGL::DistanceFiel if(!context.isExtensionSupported(version)) #endif { - bindAttributeLocation(Position::Location, "position"); - bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); + out.bindAttributeLocation(Position::Location, "position"); + out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); } #endif - CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + out.submitLink(); + 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; + + CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); + CORRADE_INTERNAL_ASSERT_OUTPUT(cs._vert.checkCompile()); + CORRADE_INTERNAL_ASSERT_OUTPUT(cs._frag.checkCompile()); + + const GL::Context& context = GL::Context::current(); + const GL::Version version = cs._version; #ifndef MAGNUM_TARGET_GLES if(!context.isExtensionSupported(version)) #endif { #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::UniformBuffers) { if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset"); } else #endif { _transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); - if(flags & Flag::TextureTransformation) + if(_flags & Flag::TextureTransformation) _textureMatrixUniform = uniformLocation("textureMatrix"); _colorUniform = uniformLocation("color"); _outlineColorUniform = uniformLocation("outlineColor"); @@ -185,11 +199,11 @@ template DistanceFieldVectorGL::DistanceFiel { setUniform(uniformLocation("vectorTexture"), TextureUnit); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::UniformBuffers) { setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding); setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding); setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding); - if(flags & Flag::TextureTransformation) + if(_flags & Flag::TextureTransformation) setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding); } #endif @@ -198,13 +212,13 @@ template DistanceFieldVectorGL::DistanceFiel /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ #ifdef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(_flags >= Flag::UniformBuffers) { /* Draw offset is zero by default */ } else #endif { setTransformationProjectionMatrix(MatrixTypeFor{Math::IdentityInit}); - if(flags & Flag::TextureTransformation) + if(_flags & Flag::TextureTransformation) setTextureMatrix(Matrix3{Math::IdentityInit}); setColor(Color4{1.0f}); /* Outline color is zero by default */ @@ -214,8 +228,16 @@ template DistanceFieldVectorGL::DistanceFiel #endif } +template DistanceFieldVectorGL::DistanceFieldVectorGL(NoInitT) {} + +template DistanceFieldVectorGL::DistanceFieldVectorGL(const Flags flags): DistanceFieldVectorGL{compile(flags)} {} + #ifndef MAGNUM_TARGET_GLES2 -template DistanceFieldVectorGL::DistanceFieldVectorGL(const Flags flags): DistanceFieldVectorGL{flags, 1, 1} {} +template typename DistanceFieldVectorGL::CompileState DistanceFieldVectorGL::compile(const Flags flags) { + return compile(flags, 1, 1); +} + +template DistanceFieldVectorGL::DistanceFieldVectorGL(const Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): DistanceFieldVectorGL{compile(flags, materialCount, drawCount)} {} #endif template DistanceFieldVectorGL& DistanceFieldVectorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.h b/src/Magnum/Shaders/DistanceFieldVectorGL.h index 1be8f0465d..2d180249f8 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.h +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.h @@ -32,6 +32,7 @@ #include "Magnum/DimensionTraits.h" #include "Magnum/GL/AbstractShaderProgram.h" +#include "Magnum/GL/Shader.h" #include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/visibility.h" @@ -280,6 +281,20 @@ 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; @@ -602,6 +617,8 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector #endif private: + explicit DistanceFieldVectorGL(NoInitT); + /* Prevent accidentally calling irrelevant functions */ #ifndef MAGNUM_TARGET_GLES using GL::AbstractShaderProgram::drawTransformFeedback; @@ -627,6 +644,20 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector #endif }; + +template class DistanceFieldVectorGL::CompileState : public DistanceFieldVectorGL { +private: + 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} {} + + GL::Shader _vert, _frag; + GL::Version _version; +}; + /** @brief Two-dimensional distance field vector OpenGL shader @m_since_latest diff --git a/src/Magnum/Shaders/MeshVisualizerGL.cpp b/src/Magnum/Shaders/MeshVisualizerGL.cpp index f428d83023..ce9d8b092f 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.cpp +++ b/src/Magnum/Shaders/MeshVisualizerGL.cpp @@ -522,7 +522,7 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags MeshVisualizerGL2D::MeshVisualizerGL2D(Flags flags) : MeshVisualizerGL2D{compile(flags)} {} #ifndef MAGNUM_TARGET_GLES2 -MeshVisualizer2D::CompileState MeshVisualizer2D::compile(Flags flags) { +MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags) { return compile(flags, 1, 1); } @@ -530,7 +530,7 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(Flags flags, UnsignedInt materialCount, U : MeshVisualizerGL2D{compile(flags, materialCount, drawCount)} {} #endif -MeshVisualizer2D::MeshVisualizerGL2D(CompileState&& cs) +MeshVisualizerGL2D::MeshVisualizerGL2D(CompileState&& cs) : MeshVisualizerGL2D{static_cast(std::move(cs))} { if (id() == 0) return; diff --git a/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp b/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp index d8bf027ac1..167c2446d3 100644 --- a/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp +++ b/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #ifdef CORRADE_TARGET_APPLE @@ -84,8 +85,10 @@ struct DistanceFieldVectorGLTest: GL::OpenGLTester { explicit DistanceFieldVectorGLTest(); template void construct(); + template void constructAsync(); #ifndef MAGNUM_TARGET_GLES2 template void constructUniformBuffers(); + template void constructUniformBuffersAsync(); #endif template void constructMove(); @@ -251,11 +254,19 @@ DistanceFieldVectorGLTest::DistanceFieldVectorGLTest() { &DistanceFieldVectorGLTest::construct<3>}, Containers::arraySize(ConstructData)); + addTests({ + &DistanceFieldVectorGLTest::constructAsync<2>, + &DistanceFieldVectorGLTest::constructAsync<3>}); + #ifndef MAGNUM_TARGET_GLES2 addInstancedTests({ &DistanceFieldVectorGLTest::constructUniformBuffers<2>, &DistanceFieldVectorGLTest::constructUniformBuffers<3>}, Containers::arraySize(ConstructUniformBuffersData)); + + addTests({ + &DistanceFieldVectorGLTest::constructUniformBuffersAsync<2>, + &DistanceFieldVectorGLTest::constructUniformBuffersAsync<3>}); #endif addTests({ @@ -374,6 +385,37 @@ template void DistanceFieldVectorGLTest::construct() { MAGNUM_VERIFY_NO_GL_ERROR(); } +template void DistanceFieldVectorGLTest::constructAsync() { + setTestCaseTemplateName(Utility::format("{}", dimensions)); + + constexpr struct { + const char* name; + DistanceFieldVectorGL2D::Flags flags; + } data{ + "texture transformation", DistanceFieldVectorGL2D::Flag::TextureTransformation + }; + setTestCaseDescription(data.name); + + auto compileState = DistanceFieldVectorGL::compile(data.flags); + CORRADE_COMPARE(compileState.flags(), data.flags); + + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + + DistanceFieldVectorGL shader{std::move(compileState)}; + CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} + #ifndef MAGNUM_TARGET_GLES2 template void DistanceFieldVectorGLTest::constructUniformBuffers() { setTestCaseTemplateName(Utility::format("{}", dimensions)); @@ -413,6 +455,59 @@ template void DistanceFieldVectorGLTest::constructUnifor MAGNUM_VERIFY_NO_GL_ERROR(); } + +template void DistanceFieldVectorGLTest::constructUniformBuffersAsync() { + setTestCaseTemplateName(Utility::format("{}", dimensions)); + + constexpr struct { + const char* name; + DistanceFieldVectorGL2D::Flags flags; + UnsignedInt materialCount, drawCount; + } data { + "multidraw with all the things", DistanceFieldVectorGL2D::Flag::MultiDraw|DistanceFieldVectorGL2D::Flag::TextureTransformation, 16, 48 + }; + setTestCaseDescription(data.name); + + #ifndef MAGNUM_TARGET_GLES + if((data.flags & DistanceFieldVectorGL2D::Flag::UniformBuffers) && !GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); + #endif + + if(data.flags >= DistanceFieldVectorGL2D::Flag::MultiDraw) { + #ifndef MAGNUM_TARGET_GLES + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); + #elif !defined(MAGNUM_TARGET_WEBGL) + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); + #endif + } + auto compileState = DistanceFieldVectorGL::compile(data.flags, data.materialCount, data.drawCount); + CORRADE_COMPARE(compileState.flags(), data.flags); + CORRADE_COMPARE(compileState.materialCount(), data.materialCount); + CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + + while(!compileState.isLinkFinished()) + Utility::System::sleep(100); + + DistanceFieldVectorGL shader{std::move(compileState)}; + CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_COMPARE(shader.materialCount(), data.materialCount); + CORRADE_COMPARE(shader.drawCount(), data.drawCount); + CORRADE_VERIFY(shader.isLinkFinished()); + CORRADE_VERIFY(shader.id()); + { + #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) + CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); + #endif + CORRADE_VERIFY(shader.validate().first); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); +} #endif template void DistanceFieldVectorGLTest::constructMove() { From 1d6c99da76851695e00533c1e1b9b050dc3f073d Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Tue, 23 Aug 2022 14:52:39 +0300 Subject: [PATCH 19/27] Move FlatGL impls from header --- src/Magnum/Shaders/FlatGL.cpp | 13 +++++++++++++ src/Magnum/Shaders/FlatGL.h | 11 ++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 29c34cb61e..2729642078 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -312,6 +312,19 @@ template FlatGL::FlatGL(CompileState&& cs) static_cast(context); } +template FlatGL::FlatGL(Flags flags) : FlatGL{compile(flags)} {} + +#ifndef MAGNUM_TARGET_GLES2 +template typename FlatGL::CompileState FlatGL::compile(Flags flags) { + return compile(flags, 1, 1); +} + +template FlatGL::FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount) + : FlatGL{compile(flags, materialCount, drawCount)} {} +#endif + +template FlatGL::FlatGL(NoInitT) {} + template FlatGL& FlatGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h index 6c6fe5d0e0..6b39cf907b 100644 --- a/src/Magnum/Shaders/FlatGL.h +++ b/src/Magnum/Shaders/FlatGL.h @@ -550,7 +550,7 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: * @ref FlatGL(Flags, UnsignedInt, UnsignedInt) with @p materialCount * and @p drawCount set to @cpp 1 @ce. */ - explicit FlatGL(Flags flags = {}) : FlatGL{compile(flags)} {} + explicit FlatGL(Flags flags = {}); #ifndef MAGNUM_TARGET_GLES2 /** @@ -586,8 +586,7 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: for this might be too confusing); what if some parameters won't be (unsigned) integers? like a string with shader extensions? make a whole Configuration class? */ - explicit FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): - FlatGL{compile(flags, materialCount, drawCount)} {} + explicit FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); #endif /** @@ -615,9 +614,7 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: ); #ifndef MAGNUM_TARGET_GLES2 - static CompileState compile(Flags flags) { - return compile(flags, 1, 1); - } + static CompileState compile(Flags flags); #endif /** @brief Copying is not allowed */ @@ -1030,7 +1027,7 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: private: /* Creates the GL shader program object but nothing else. Internal, used by compile(). */ - explicit FlatGL(NoInitT) {} + explicit FlatGL(NoInitT); /* Prevent accidentally calling irrelevant functions */ #ifndef MAGNUM_TARGET_GLES From b086162c6d2f88cff8ebe48aafe5cd5516a8b813 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Tue, 23 Aug 2022 14:58:24 +0300 Subject: [PATCH 20/27] Move VectorGL impls from header --- src/Magnum/Shaders/VectorGL.cpp | 14 ++++++++++++++ src/Magnum/Shaders/VectorGL.h | 11 ++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/Magnum/Shaders/VectorGL.cpp b/src/Magnum/Shaders/VectorGL.cpp index 16d1e70404..c443cf714d 100644 --- a/src/Magnum/Shaders/VectorGL.cpp +++ b/src/Magnum/Shaders/VectorGL.cpp @@ -230,6 +230,20 @@ template VectorGL::VectorGL(CompileState&& c static_cast(version); } +template VectorGL::VectorGL(Flags flags) : VectorGL{compile(flags)} {} + +#ifndef MAGNUM_TARGET_GLES2 +template typename VectorGL::CompileState VectorGL::compile(Flags flags) { + return compile(flags, 1, 1); +} + +template VectorGL::VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount) + : VectorGL{compile(flags, materialCount, drawCount)} {} +#endif + +template VectorGL::VectorGL(NoInitT) {} + + template VectorGL& VectorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), diff --git a/src/Magnum/Shaders/VectorGL.h b/src/Magnum/Shaders/VectorGL.h index ae4a3aa6c7..232a076d2b 100644 --- a/src/Magnum/Shaders/VectorGL.h +++ b/src/Magnum/Shaders/VectorGL.h @@ -222,7 +222,7 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL * @ref VectorGL(Flags, UnsignedInt, UnsignedInt) with @p materialCount * and @p drawCount set to @cpp 1 @ce. */ - explicit VectorGL(Flags flags = {}) : VectorGL{compile(flags)} {}; + explicit VectorGL(Flags flags = {}); #ifndef MAGNUM_TARGET_GLES2 /** @@ -257,8 +257,7 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL for this might be too confusing); what if some parameters won't be (unsigned) integers? like a string with shader extensions? make a whole Configuration class? */ - explicit VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount) : - VectorGL{compile(flags, materialCount, drawCount)} {} + explicit VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); #endif /** @@ -286,9 +285,7 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL ); #ifndef MAGNUM_TARGET_GLES2 - static CompileState compile(Flags flags) { - return compile(flags, 1, 1); - } + static CompileState compile(Flags flags); #endif /** @brief Copying is not allowed */ @@ -573,7 +570,7 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL private: /* Creates the GL shader program object but nothing else. Internal, used by compile(). */ - explicit VectorGL(NoInitT) {} + explicit VectorGL(NoInitT); /* Prevent accidentally calling irrelevant functions */ #ifndef MAGNUM_TARGET_GLES From b5da1e2abc82a2ee64d508134c19a3d1ea44df00 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Tue, 23 Aug 2022 15:24:21 +0300 Subject: [PATCH 21/27] Move VertexColorGL impls from header --- src/Magnum/Shaders/VertexColorGL.cpp | 14 ++++++++++++++ src/Magnum/Shaders/VertexColorGL.h | 11 ++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/Magnum/Shaders/VertexColorGL.cpp b/src/Magnum/Shaders/VertexColorGL.cpp index 70c502facd..15ebb23539 100644 --- a/src/Magnum/Shaders/VertexColorGL.cpp +++ b/src/Magnum/Shaders/VertexColorGL.cpp @@ -193,6 +193,20 @@ template VertexColorGL::VertexColorGL(Compil static_cast(version); } +template VertexColorGL::VertexColorGL(Flags flags): VertexColorGL{compile(flags)} {} + +#ifndef MAGNUM_TARGET_GLES2 +template typename VertexColorGL::CompileState VertexColorGL::compile(Flags flags) { + return compile(flags, 1); +} + +template VertexColorGL::VertexColorGL(Flags flags, UnsignedInt drawCount) + : VertexColorGL{compile(flags, drawCount)} {} +#endif + +template VertexColorGL::VertexColorGL(NoInitT) {} + + template VertexColorGL& VertexColorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), diff --git a/src/Magnum/Shaders/VertexColorGL.h b/src/Magnum/Shaders/VertexColorGL.h index 69ad1e87a3..e674f05a17 100644 --- a/src/Magnum/Shaders/VertexColorGL.h +++ b/src/Magnum/Shaders/VertexColorGL.h @@ -217,7 +217,7 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ * @ref VertexColorGL(Flags, UnsignedInt) with @p drawCount set to * @cpp 1 @ce. */ - explicit VertexColorGL(Flags flags = {}): VertexColorGL{compile(flags)} {} + explicit VertexColorGL(Flags flags = {}); #ifndef MAGNUM_TARGET_GLES2 /** @@ -248,8 +248,7 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ for this might be too confusing); what if some parameters won't be (unsigned) integers? like a string with shader extensions? make a whole Configuration class? */ - explicit VertexColorGL(Flags flags, UnsignedInt drawCount): - VertexColorGL{compile(flags, drawCount)} {} + explicit VertexColorGL(Flags flags, UnsignedInt drawCount); #endif /** @@ -277,9 +276,7 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ ); #ifndef MAGNUM_TARGET_GLES2 - static CompileState compile(Flags flags) { - return compile(flags, 1); - } + static CompileState compile(Flags flags); #endif /** @brief Copying is not allowed */ @@ -424,7 +421,7 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ #endif private: - explicit VertexColorGL(NoInitT) {} + explicit VertexColorGL(NoInitT); /* Prevent accidentally calling irrelevant functions */ #ifndef MAGNUM_TARGET_GLES From 3ab4b6fef350de727cef1322ea4e79bb3e11e9b6 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Tue, 23 Aug 2022 16:50:15 +0300 Subject: [PATCH 22/27] Refactor tests --- .../Test/DistanceFieldVectorGLTest.cpp | 50 +--- src/Magnum/Shaders/Test/FlatGLTest.cpp | 69 +---- .../Shaders/Test/MeshVisualizerGLTest.cpp | 264 ++---------------- src/Magnum/Shaders/Test/PhongGLTest.cpp | 72 +---- src/Magnum/Shaders/Test/VectorGLTest.cpp | 49 +--- src/Magnum/Shaders/Test/VertexColorGLTest.cpp | 33 +-- 6 files changed, 79 insertions(+), 458 deletions(-) diff --git a/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp b/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp index 167c2446d3..e23db4a99d 100644 --- a/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp +++ b/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp @@ -388,22 +388,14 @@ template void DistanceFieldVectorGLTest::construct() { template void DistanceFieldVectorGLTest::constructAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - constexpr struct { - const char* name; - DistanceFieldVectorGL2D::Flags flags; - } data{ - "texture transformation", DistanceFieldVectorGL2D::Flag::TextureTransformation - }; - setTestCaseDescription(data.name); - - auto compileState = DistanceFieldVectorGL::compile(data.flags); - CORRADE_COMPARE(compileState.flags(), data.flags); + auto compileState = DistanceFieldVectorGL::compile(DistanceFieldVectorGL2D::Flag::TextureTransformation); + CORRADE_COMPARE(compileState.flags(), DistanceFieldVectorGL2D::Flag::TextureTransformation); while(!compileState.isLinkFinished()) Utility::System::sleep(100); DistanceFieldVectorGL shader{std::move(compileState)}; - CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_COMPARE(shader.flags(), DistanceFieldVectorGL2D::Flag::TextureTransformation); CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); { @@ -459,44 +451,24 @@ template void DistanceFieldVectorGLTest::constructUnifor template void DistanceFieldVectorGLTest::constructUniformBuffersAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - constexpr struct { - const char* name; - DistanceFieldVectorGL2D::Flags flags; - UnsignedInt materialCount, drawCount; - } data { - "multidraw with all the things", DistanceFieldVectorGL2D::Flag::MultiDraw|DistanceFieldVectorGL2D::Flag::TextureTransformation, 16, 48 - }; - setTestCaseDescription(data.name); #ifndef MAGNUM_TARGET_GLES - if((data.flags & DistanceFieldVectorGL2D::Flag::UniformBuffers) && !GL::Context::current().isExtensionSupported()) + if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif - if(data.flags >= DistanceFieldVectorGL2D::Flag::MultiDraw) { - #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); - #elif !defined(MAGNUM_TARGET_WEBGL) - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); - #else - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); - #endif - } - auto compileState = DistanceFieldVectorGL::compile(data.flags, data.materialCount, data.drawCount); - CORRADE_COMPARE(compileState.flags(), data.flags); - CORRADE_COMPARE(compileState.materialCount(), data.materialCount); - CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + 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); while(!compileState.isLinkFinished()) Utility::System::sleep(100); DistanceFieldVectorGL shader{std::move(compileState)}; - CORRADE_COMPARE(shader.flags(), data.flags); - CORRADE_COMPARE(shader.materialCount(), data.materialCount); - CORRADE_COMPARE(shader.drawCount(), data.drawCount); + CORRADE_COMPARE(shader.flags(), DistanceFieldVectorGL2D::Flag::UniformBuffers); + CORRADE_COMPARE(shader.materialCount(), 16); + CORRADE_COMPARE(shader.drawCount(), 4); 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 2828e2dbf4..192c5fca2d 100644 --- a/src/Magnum/Shaders/Test/FlatGLTest.cpp +++ b/src/Magnum/Shaders/Test/FlatGLTest.cpp @@ -866,32 +866,14 @@ template void FlatGLTest::construct() { template void FlatGLTest::constructAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - - constexpr struct { - const char* name; - FlatGL2D::Flags flags; - } data { - "textured + texture transformation", - FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation - }; - - setTestCaseDescription(data.name); - - #ifndef MAGNUM_TARGET_GLES - if((data.flags & FlatGL2D::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); - if((data.flags & FlatGL2D::Flag::TextureArrays) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::texture_array::string() << "is not supported."); - #endif - - auto compileState = FlatGL::compile(data.flags); - CORRADE_COMPARE(compileState.flags(), data.flags); + auto compileState = FlatGL::compile(FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation); + CORRADE_COMPARE(compileState.flags(), FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation); while(!compileState.isLinkFinished()) Utility::System::sleep(100); FlatGL shader{std::move(compileState)}; - CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_COMPARE(shader.flags(), FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation); CORRADE_VERIFY(shader.id()); { @@ -951,52 +933,23 @@ template void FlatGLTest::constructUniformBuffers() { template void FlatGLTest::constructUniformBuffersAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - constexpr struct { - const char* name; - FlatGL2D::Flags flags; - UnsignedInt materialCount, drawCount; - } data { - "alpha mask", - FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::AlphaMask, - 1, 1 - }; - - setTestCaseDescription(data.name); - #ifndef MAGNUM_TARGET_GLES - if((data.flags & FlatGL2D::Flag::UniformBuffers) && !GL::Context::current().isExtensionSupported()) + if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); - if((data.flags & FlatGL2D::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); - if((data.flags & FlatGL2D::Flag::TextureArrays) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::texture_array::string() << "is not supported."); #endif - if(data.flags >= FlatGL2D::Flag::MultiDraw) { - #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); - #elif !defined(MAGNUM_TARGET_WEBGL) - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); - #else - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); - #endif - } - - auto compileState = FlatGL::compile(data.flags, data.materialCount, data.drawCount); - CORRADE_COMPARE(compileState.flags(), data.flags); - CORRADE_COMPARE(compileState.materialCount(), data.materialCount); - CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + 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); while(!compileState.isLinkFinished()) Utility::System::sleep(100); FlatGL shader{std::move(compileState)}; - CORRADE_COMPARE(shader.flags(), data.flags); - CORRADE_COMPARE(shader.materialCount(), data.materialCount); - CORRADE_COMPARE(shader.drawCount(), data.drawCount); + CORRADE_COMPARE(shader.flags(), FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::AlphaMask); + CORRADE_COMPARE(shader.materialCount(), 1); + CORRADE_COMPARE(shader.drawCount(), 1); 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 31319306ee..f822d91ed9 100644 --- a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp +++ b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp @@ -1416,64 +1416,14 @@ void MeshVisualizerGLTest::construct2D() { void MeshVisualizerGLTest::construct2DAsync() { - constexpr struct { - const char* name; - MeshVisualizerGL2D::Flags flags; - } data { - "wireframe w/o GS", MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader - }; - setTestCaseDescription(data.name); - - #ifndef MAGNUM_TARGET_GLES - if((data.flags & MeshVisualizerGL2D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); - #endif - - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(data.flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId && - #ifndef MAGNUM_TARGET_GLES - !GL::Context::current().isVersionSupported(GL::Version::GL300) - #else - !GL::Context::current().isVersionSupported(GL::Version::GLES300) - #endif - ) CORRADE_SKIP("gl_VertexID not supported."); - #endif - - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(data.flags & MeshVisualizerGL2D::Flag::PrimitiveId && !(data.flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId) && - #ifndef MAGNUM_TARGET_GLES - !GL::Context::current().isVersionSupported(GL::Version::GL320) - #else - !GL::Context::current().isVersionSupported(GL::Version::GLES320) - #endif - ) CORRADE_SKIP("gl_PrimitiveID not supported."); - #endif - - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if((data.flags & MeshVisualizerGL2D::Flag::Wireframe) && !(data.flags & MeshVisualizerGL2D::Flag::NoGeometryShader)) { - #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); - #else - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); - #endif - - #ifdef MAGNUM_TARGET_GLES - if(GL::Context::current().isExtensionSupported()) - CORRADE_INFO("Using" << GL::Extensions::NV::shader_noperspective_interpolation::string()); - #endif - } - #endif - - auto compileState = MeshVisualizerGL2D::compile(data.flags); - CORRADE_COMPARE(compileState.flags(), data.flags); + auto compileState = MeshVisualizerGL2D::compile(MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); + CORRADE_COMPARE(compileState.flags(), MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); while(!compileState.isLinkFinished()) Utility::System::sleep(100); MeshVisualizerGL2D shader{std::move(compileState)}; - CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_COMPARE(shader.flags(), MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); { @@ -1566,85 +1516,23 @@ void MeshVisualizerGLTest::constructUniformBuffers2D() { void MeshVisualizerGLTest::constructUniformBuffers2DAsync() { - constexpr struct { - const char* name; - MeshVisualizerGL2D::Flags flags; - UnsignedInt materialCount, drawCount; - } data { - "multidraw with wireframe w/o GS and vertex ID", MeshVisualizerGL2D::Flag::MultiDraw|MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader|MeshVisualizerGL2D::Flag::VertexId, 8, 55 - }; - setTestCaseDescription(data.name); - #ifndef MAGNUM_TARGET_GLES - if((data.flags & MeshVisualizerGL2D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); - #endif - - #ifndef MAGNUM_TARGET_WEBGL - if(data.flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId && - #ifndef MAGNUM_TARGET_GLES - !GL::Context::current().isVersionSupported(GL::Version::GL300) - #else - !GL::Context::current().isVersionSupported(GL::Version::GLES300) - #endif - ) CORRADE_SKIP("gl_VertexID not supported."); - #endif - - #ifndef MAGNUM_TARGET_WEBGL - if(data.flags & MeshVisualizerGL2D::Flag::PrimitiveId && !(data.flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId) && - #ifndef MAGNUM_TARGET_GLES - !GL::Context::current().isVersionSupported(GL::Version::GL320) - #else - !GL::Context::current().isVersionSupported(GL::Version::GLES320) - #endif - ) CORRADE_SKIP("gl_PrimitiveID not supported."); - #endif - - #ifndef MAGNUM_TARGET_WEBGL - if((data.flags & MeshVisualizerGL2D::Flag::Wireframe) && !(data.flags & MeshVisualizerGL2D::Flag::NoGeometryShader)) { - #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); - #else - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); - #endif - - #ifdef MAGNUM_TARGET_GLES - if(GL::Context::current().isExtensionSupported()) - CORRADE_INFO("Using" << GL::Extensions::NV::shader_noperspective_interpolation::string()); - #endif - } - #endif - - #ifndef MAGNUM_TARGET_GLES - if(data.flags & MeshVisualizerGL2D::Flag::UniformBuffers && !GL::Context::current().isExtensionSupported()) + if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif - if(data.flags >= MeshVisualizerGL2D::Flag::MultiDraw) { - #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); - #elif !defined(MAGNUM_TARGET_WEBGL) - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); - #else - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); - #endif - } - - auto compileState = MeshVisualizerGL2D::compile(data.flags, data.materialCount, data.drawCount); - CORRADE_COMPARE(compileState.flags(), data.flags); - CORRADE_COMPARE(compileState.materialCount(), data.materialCount); - CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + 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); while(!compileState.isLinkFinished()) Utility::System::sleep(100); MeshVisualizerGL2D shader{std::move(compileState)}; - CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_COMPARE(shader.flags(), MeshVisualizerGL2D::Flag::UniformBuffers|MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); + CORRADE_COMPARE(shader.materialCount(), 8); + CORRADE_COMPARE(shader.drawCount(), 55); CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); { @@ -1718,64 +1606,15 @@ void MeshVisualizerGLTest::construct3D() { } void MeshVisualizerGLTest::construct3DAsync() { - constexpr struct { - const char* name; - MeshVisualizerGL3D::Flags flags; - } data { - "wireframe w/o GS", MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader - }; - setTestCaseDescription(data.name); - - #ifndef MAGNUM_TARGET_GLES - if((data.flags & MeshVisualizerGL3D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); - #endif - - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(data.flags >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId && - #ifndef MAGNUM_TARGET_GLES - !GL::Context::current().isVersionSupported(GL::Version::GL300) - #else - !GL::Context::current().isVersionSupported(GL::Version::GLES300) - #endif - ) CORRADE_SKIP("gl_VertexID not supported."); - #endif - - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(data.flags & MeshVisualizerGL3D::Flag::PrimitiveId && !(data.flags >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId) && - #ifndef MAGNUM_TARGET_GLES - !GL::Context::current().isVersionSupported(GL::Version::GL320) - #else - !GL::Context::current().isVersionSupported(GL::Version::GLES320) - #endif - ) CORRADE_SKIP("gl_PrimitiveID not supported."); - #endif - - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(((data.flags & MeshVisualizerGL3D::Flag::Wireframe) && !(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader)) || (data.flags & (MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::BitangentDirection|MeshVisualizerGL3D::Flag::BitangentFromTangentDirection|MeshVisualizerGL3D::Flag::NormalDirection))) { - #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); - #else - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); - #endif - - #ifdef MAGNUM_TARGET_GLES - if(GL::Context::current().isExtensionSupported()) - CORRADE_INFO("Using" << GL::Extensions::NV::shader_noperspective_interpolation::string()); - #endif - } - #endif - - auto compileState = MeshVisualizerGL3D::compile(data.flags); - CORRADE_COMPARE(compileState.flags(), data.flags); + auto compileState = MeshVisualizerGL3D::compile(MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); + CORRADE_COMPARE(compileState.flags(), MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); while(!compileState.isLinkFinished()) Utility::System::sleep(100); - MeshVisualizerGL3D shader{data.flags}; - CORRADE_COMPARE(shader.flags(), data.flags); + // TODO: FIXME MeshVisualizerGL3D shader{std::move(compileState)}; + MeshVisualizerGL3D shader{MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader}; + CORRADE_COMPARE(shader.flags(), MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); CORRADE_VERIFY(compileState.isLinkFinished()); CORRADE_VERIFY(shader.id()); { @@ -1872,80 +1711,27 @@ void MeshVisualizerGLTest::constructUniformBuffers3DAsync() { MeshVisualizerGL3D::Flags flags; UnsignedInt materialCount, drawCount; } data { - "multidraw with wireframe w/o GS and vertex ID", MeshVisualizerGL3D::Flag::MultiDraw|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader|MeshVisualizerGL3D::Flag::VertexId, 6, 28 + "multiple materials, draws", MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader, 8, 55 }; setTestCaseDescription(data.name); #ifndef MAGNUM_TARGET_GLES - if((data.flags & MeshVisualizerGL3D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); - #endif - - #ifndef MAGNUM_TARGET_WEBGL - if(data.flags >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId && - #ifndef MAGNUM_TARGET_GLES - !GL::Context::current().isVersionSupported(GL::Version::GL300) - #else - !GL::Context::current().isVersionSupported(GL::Version::GLES300) - #endif - ) CORRADE_SKIP("gl_VertexID not supported."); - #endif - - #ifndef MAGNUM_TARGET_WEBGL - if(data.flags & MeshVisualizerGL3D::Flag::PrimitiveId && !(data.flags >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId) && - #ifndef MAGNUM_TARGET_GLES - !GL::Context::current().isVersionSupported(GL::Version::GL320) - #else - !GL::Context::current().isVersionSupported(GL::Version::GLES320) - #endif - ) CORRADE_SKIP("gl_PrimitiveID not supported."); - #endif - - #ifndef MAGNUM_TARGET_WEBGL - if(((data.flags & MeshVisualizerGL3D::Flag::Wireframe) && !(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader)) || (data.flags & (MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::BitangentDirection|MeshVisualizerGL3D::Flag::BitangentFromTangentDirection|MeshVisualizerGL3D::Flag::NormalDirection))) { - #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); - #else - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); - #endif - - #ifdef MAGNUM_TARGET_GLES - if(GL::Context::current().isExtensionSupported()) - CORRADE_INFO("Using" << GL::Extensions::NV::shader_noperspective_interpolation::string()); - #endif - } - #endif - - #ifndef MAGNUM_TARGET_GLES - if(data.flags & MeshVisualizerGL3D::Flag::UniformBuffers && !GL::Context::current().isExtensionSupported()) + if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif - if(data.flags >= MeshVisualizerGL3D::Flag::MultiDraw) { - #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); - #elif !defined(MAGNUM_TARGET_WEBGL) - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); - #else - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); - #endif - } - - auto compileState = MeshVisualizerGL3D::compile(data.flags, data.materialCount, data.drawCount); - CORRADE_COMPARE(compileState.flags(), data.flags); - CORRADE_COMPARE(compileState.materialCount(), data.materialCount); - CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + auto compileState = MeshVisualizerGL3D::compile(MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader, 8, 55); + CORRADE_COMPARE(compileState.flags(), MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); + CORRADE_COMPARE(compileState.materialCount(), 8); + CORRADE_COMPARE(compileState.drawCount(), 55); while(!compileState.isLinkFinished()) Utility::System::sleep(100); MeshVisualizerGL3D shader{std::move(compileState)}; - CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_COMPARE(shader.flags(), MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); + CORRADE_COMPARE(compileState.materialCount(), 8); + CORRADE_COMPARE(compileState.drawCount(), 55); 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 6057fd7fe8..d0df58ec40 100644 --- a/src/Magnum/Shaders/Test/PhongGLTest.cpp +++ b/src/Magnum/Shaders/Test/PhongGLTest.cpp @@ -1199,32 +1199,16 @@ void PhongGLTest::construct() { } void PhongGLTest::constructAsync() { - constexpr struct { - const char* name; - PhongGL::Flags flags; - UnsignedInt lightCount; - } data { - "instanced specular texture offset", PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset, 3 - }; - setTestCaseDescription(data.name); - - #ifndef MAGNUM_TARGET_GLES - if((data.flags & PhongGL::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); - if((data.flags & PhongGL::Flag::TextureArrays) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::texture_array::string() << "is not supported."); - #endif - - auto compileState = PhongGL::compile(data.flags, data.lightCount); - CORRADE_COMPARE(compileState.flags(), data.flags); - CORRADE_COMPARE(compileState.lightCount(), data.lightCount); + 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); while(!compileState.isLinkFinished()) Utility::System::sleep(100); PhongGL shader{std::move(compileState)}; - CORRADE_COMPARE(shader.flags(), data.flags); - CORRADE_COMPARE(shader.lightCount(), data.lightCount); + CORRADE_COMPARE(shader.flags(), PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset); + CORRADE_COMPARE(shader.lightCount(), 3); CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); { @@ -1281,51 +1265,25 @@ void PhongGLTest::constructUniformBuffers() { } void PhongGLTest::constructUniformBuffersAsync() { - constexpr struct { - const char* name; - PhongGL::Flags flags; - UnsignedInt lightCount, materialCount, drawCount; - } data { - "multiple lights, materials, draws + light culling", PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling, 8, 8, 24 - }; - setTestCaseDescription(data.name); - #ifndef MAGNUM_TARGET_GLES - if((data.flags & PhongGL::Flag::UniformBuffers) && !GL::Context::current().isExtensionSupported()) + if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); - if((data.flags & PhongGL::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); - if((data.flags & PhongGL::Flag::TextureArrays) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::texture_array::string() << "is not supported."); #endif - if(data.flags >= PhongGL::Flag::MultiDraw) { - #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); - #elif !defined(MAGNUM_TARGET_WEBGL) - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); - #else - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); - #endif - } - - auto compileState = PhongGL::compile(data.flags, data.lightCount, data.materialCount, data.drawCount); - CORRADE_COMPARE(compileState.flags(), data.flags); - CORRADE_COMPARE(compileState.lightCount(), data.lightCount); - CORRADE_COMPARE(compileState.materialCount(), data.materialCount); - CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + 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); while(!compileState.isLinkFinished()) Utility::System::sleep(100); PhongGL shader{std::move(compileState)}; - CORRADE_COMPARE(shader.flags(), data.flags); - CORRADE_COMPARE(shader.lightCount(), data.lightCount); - CORRADE_COMPARE(shader.materialCount(), data.materialCount); - CORRADE_COMPARE(shader.drawCount(), data.drawCount); + CORRADE_COMPARE(shader.flags(), PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling); + CORRADE_COMPARE(shader.lightCount(), 8); + CORRADE_COMPARE(shader.materialCount(), 8); + CORRADE_COMPARE(shader.drawCount(), 24); CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); { diff --git a/src/Magnum/Shaders/Test/VectorGLTest.cpp b/src/Magnum/Shaders/Test/VectorGLTest.cpp index 7b8bff18fc..715688e1e3 100644 --- a/src/Magnum/Shaders/Test/VectorGLTest.cpp +++ b/src/Magnum/Shaders/Test/VectorGLTest.cpp @@ -384,23 +384,15 @@ template void VectorGLTest::construct() { template void VectorGLTest::constructAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - constexpr struct { - const char* name; - VectorGL2D::Flags flags; - } data { - "texture transformation", VectorGL2D::Flag::TextureTransformation - }; - setTestCaseDescription(data.name); - - auto compileState = VectorGL::compile(data.flags); - CORRADE_COMPARE(compileState.flags(), data.flags); + auto compileState = VectorGL::compile(VectorGL2D::Flag::TextureTransformation); + CORRADE_COMPARE(compileState.flags(), VectorGL2D::Flag::TextureTransformation); while(!compileState.isLinkFinished()) Utility::System::sleep(100); VectorGL shader{std::move(compileState)}; CORRADE_VERIFY(shader.isLinkFinished()); - CORRADE_COMPARE(shader.flags(), data.flags); + CORRADE_COMPARE(shader.flags(), VectorGL2D::Flag::TextureTransformation); CORRADE_VERIFY(shader.id()); { #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) @@ -455,43 +447,24 @@ template void VectorGLTest::constructUniformBuffers() { template void VectorGLTest::constructUniformBuffersAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - constexpr struct { - const char* name; - VectorGL2D::Flags flags; - UnsignedInt materialCount, drawCount; - } data {"texture transformation", VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation, 1, 1}; - setTestCaseDescription(data.name); - #ifndef MAGNUM_TARGET_GLES - if((data.flags & VectorGL::Flag::UniformBuffers) && !GL::Context::current().isExtensionSupported()) + if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif - if(data.flags >= VectorGL2D::Flag::MultiDraw) { - #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); - #elif !defined(MAGNUM_TARGET_WEBGL) - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); - #else - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); - #endif - } - - auto compileState = VectorGL::compile(data.flags, data.materialCount, data.drawCount); - CORRADE_COMPARE(compileState.flags(), data.flags); - CORRADE_COMPARE(compileState.materialCount(), data.materialCount); - CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + 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); while(!compileState.isLinkFinished()) Utility::System::sleep(100); VectorGL shader{std::move(compileState)}; CORRADE_VERIFY(shader.isLinkFinished()); - CORRADE_COMPARE(shader.flags(), data.flags); - CORRADE_COMPARE(shader.drawCount(), data.drawCount); + CORRADE_COMPARE(shader.flags(), VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation); + CORRADE_COMPARE(shader.materialCount(), 1); + CORRADE_COMPARE(shader.drawCount(), 1); 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 233850198d..451c7348ff 100644 --- a/src/Magnum/Shaders/Test/VertexColorGLTest.cpp +++ b/src/Magnum/Shaders/Test/VertexColorGLTest.cpp @@ -382,42 +382,21 @@ template void VertexColorGLTest::constructUniformBuffers template void VertexColorGLTest::constructUniformBuffersAsync() { setTestCaseTemplateName(Utility::format("{}", dimensions)); - constexpr struct { - const char* name; - VertexColorGL2D::Flags flags; - UnsignedInt drawCount; - } data { - "multiple draws", VertexColorGL2D::Flag::UniformBuffers, 63 - }; - setTestCaseDescription(data.name); - #ifndef MAGNUM_TARGET_GLES - if((data.flags & VertexColorGL::Flag::UniformBuffers) && !GL::Context::current().isExtensionSupported()) + if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif - if(data.flags >= VertexColorGL2D::Flag::MultiDraw) { - #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported."); - #elif !defined(MAGNUM_TARGET_WEBGL) - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported."); - #else - if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported."); - #endif - } - auto compileState = VertexColorGL::compile(data.flags, data.drawCount); - CORRADE_COMPARE(compileState.flags(), data.flags); - CORRADE_COMPARE(compileState.drawCount(), data.drawCount); + auto compileState = VertexColorGL::compile(VertexColorGL2D::Flag::UniformBuffers, 63); + CORRADE_COMPARE(compileState.flags(), VertexColorGL2D::Flag::UniformBuffers); + CORRADE_COMPARE(compileState.drawCount(), 63); while(!compileState.isLinkFinished()) Utility::System::sleep(100); VertexColorGL shader{std::move(compileState)}; - CORRADE_COMPARE(shader.flags(), data.flags); - CORRADE_COMPARE(shader.drawCount(), data.drawCount); + CORRADE_COMPARE(shader.flags(), VertexColorGL2D::Flag::UniformBuffers); + CORRADE_COMPARE(shader.drawCount(), 63); CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); { From b592fcbff38a216ad8c79a86ea502b12da4829f3 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Wed, 24 Aug 2022 18:57:37 +0300 Subject: [PATCH 23/27] Fix formatting --- src/Magnum/Shaders/DistanceFieldVectorGL.cpp | 6 +++--- src/Magnum/Shaders/DistanceFieldVectorGL.h | 6 +++--- src/Magnum/Shaders/FlatGL.cpp | 9 ++++----- src/Magnum/Shaders/FlatGL.h | 6 +++--- src/Magnum/Shaders/PhongGL.cpp | 9 ++++----- src/Magnum/Shaders/PhongGL.h | 6 +++--- src/Magnum/Shaders/VectorGL.cpp | 10 ++++------ src/Magnum/Shaders/VectorGL.h | 6 +++--- src/Magnum/Shaders/VertexColorGL.cpp | 8 +++----- src/Magnum/Shaders/VertexColorGL.h | 6 +++--- 10 files changed, 33 insertions(+), 39 deletions(-) diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp index a404c52610..2d1dbf70ff 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp @@ -162,8 +162,7 @@ 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))} { +template DistanceFieldVectorGL::DistanceFieldVectorGL(CompileState&& cs): DistanceFieldVectorGL{static_cast(std::move(cs))} { if (id() == 0) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); @@ -237,7 +236,8 @@ template typename DistanceFieldVectorGL::Com return compile(flags, 1, 1); } -template DistanceFieldVectorGL::DistanceFieldVectorGL(const Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): DistanceFieldVectorGL{compile(flags, materialCount, drawCount)} {} +template DistanceFieldVectorGL::DistanceFieldVectorGL(const Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): + DistanceFieldVectorGL{compile(flags, materialCount, drawCount)} {} #endif template DistanceFieldVectorGL& DistanceFieldVectorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.h b/src/Magnum/Shaders/DistanceFieldVectorGL.h index 2d180249f8..067be3383f 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.h +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.h @@ -645,13 +645,13 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector }; -template class DistanceFieldVectorGL::CompileState : public DistanceFieldVectorGL { +template class DistanceFieldVectorGL::CompileState: public DistanceFieldVectorGL { private: friend class DistanceFieldVectorGL; - explicit CompileState(NoCreateT) : DistanceFieldVectorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} + explicit CompileState(NoCreateT): DistanceFieldVectorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} - CompileState(DistanceFieldVectorGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version) : + 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; diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 2729642078..11718dc635 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -237,8 +237,7 @@ 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))} { +template FlatGL::FlatGL(CompileState&& cs): FlatGL{static_cast(std::move(cs))} { if (id() == 0) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); @@ -312,15 +311,15 @@ template FlatGL::FlatGL(CompileState&& cs) static_cast(context); } -template FlatGL::FlatGL(Flags flags) : FlatGL{compile(flags)} {} +template FlatGL::FlatGL(Flags flags): FlatGL{compile(flags)} {} #ifndef MAGNUM_TARGET_GLES2 template typename FlatGL::CompileState FlatGL::compile(Flags flags) { return compile(flags, 1, 1); } -template FlatGL::FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount) - : FlatGL{compile(flags, materialCount, drawCount)} {} +template FlatGL::FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): + FlatGL{compile(flags, materialCount, drawCount)} {} #endif template FlatGL::FlatGL(NoInitT) {} diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h index 6b39cf907b..354d432405 100644 --- a/src/Magnum/Shaders/FlatGL.h +++ b/src/Magnum/Shaders/FlatGL.h @@ -1056,13 +1056,13 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: #endif }; -template class FlatGL::CompileState : public FlatGL { +template class FlatGL::CompileState: public FlatGL { private: friend class FlatGL; - explicit CompileState(NoCreateT) : FlatGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} + explicit CompileState(NoCreateT): FlatGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} - CompileState(FlatGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version) : + 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; diff --git a/src/Magnum/Shaders/PhongGL.cpp b/src/Magnum/Shaders/PhongGL.cpp index c06d396d6b..bd8bf9e65d 100644 --- a/src/Magnum/Shaders/PhongGL.cpp +++ b/src/Magnum/Shaders/PhongGL.cpp @@ -347,8 +347,7 @@ 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))} { +PhongGL::PhongGL(CompileState&& cs): PhongGL{static_cast(std::move(cs))} { if (id() == 0) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); @@ -464,15 +463,15 @@ PhongGL::PhongGL(CompileState&& cs) static_cast(version); } -PhongGL::PhongGL(Flags flags, UnsignedInt lightCount) : PhongGL{compile(flags, lightCount)} {} +PhongGL::PhongGL(Flags flags, UnsignedInt lightCount): PhongGL{compile(flags, lightCount)} {} #ifndef MAGNUM_TARGET_GLES2 PhongGL::CompileState PhongGL::compile(Flags flags, 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(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, 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 860e5f56c9..8a06e2cccd 100644 --- a/src/Magnum/Shaders/PhongGL.h +++ b/src/Magnum/Shaders/PhongGL.h @@ -1801,13 +1801,13 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { #endif }; -class PhongGL::CompileState : public PhongGL { +class PhongGL::CompileState: public PhongGL { private: friend class PhongGL; - explicit CompileState(NoCreateT) : PhongGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} + explicit CompileState(NoCreateT): PhongGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} - CompileState(PhongGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version) : + 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; diff --git a/src/Magnum/Shaders/VectorGL.cpp b/src/Magnum/Shaders/VectorGL.cpp index c443cf714d..b52aee517f 100644 --- a/src/Magnum/Shaders/VectorGL.cpp +++ b/src/Magnum/Shaders/VectorGL.cpp @@ -164,8 +164,7 @@ 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))} { +template VectorGL::VectorGL(CompileState&& cs): VectorGL{static_cast(std::move(cs))} { if (id() == 0) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); @@ -230,20 +229,19 @@ template VectorGL::VectorGL(CompileState&& c static_cast(version); } -template VectorGL::VectorGL(Flags flags) : VectorGL{compile(flags)} {} +template VectorGL::VectorGL(Flags flags): VectorGL{compile(flags)} {} #ifndef MAGNUM_TARGET_GLES2 template typename VectorGL::CompileState VectorGL::compile(Flags flags) { return compile(flags, 1, 1); } -template VectorGL::VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount) - : VectorGL{compile(flags, materialCount, drawCount)} {} +template VectorGL::VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): + VectorGL{compile(flags, materialCount, drawCount)} {} #endif template VectorGL::VectorGL(NoInitT) {} - template VectorGL& VectorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), diff --git a/src/Magnum/Shaders/VectorGL.h b/src/Magnum/Shaders/VectorGL.h index 232a076d2b..74dd27b38c 100644 --- a/src/Magnum/Shaders/VectorGL.h +++ b/src/Magnum/Shaders/VectorGL.h @@ -595,13 +595,13 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL #endif }; -template class VectorGL::CompileState : public VectorGL { +template class VectorGL::CompileState: public VectorGL { private: friend class VectorGL; - explicit CompileState(NoCreateT) : VectorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} + explicit CompileState(NoCreateT): VectorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} - CompileState(VectorGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version) : + 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; diff --git a/src/Magnum/Shaders/VertexColorGL.cpp b/src/Magnum/Shaders/VertexColorGL.cpp index 15ebb23539..d796a8aaa2 100644 --- a/src/Magnum/Shaders/VertexColorGL.cpp +++ b/src/Magnum/Shaders/VertexColorGL.cpp @@ -142,8 +142,7 @@ 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))} { +template VertexColorGL::VertexColorGL(CompileState&& cs): VertexColorGL{static_cast(std::move(cs))} { if (id() == 0) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); @@ -200,13 +199,12 @@ template typename VertexColorGL::CompileStat return compile(flags, 1); } -template VertexColorGL::VertexColorGL(Flags flags, UnsignedInt drawCount) - : VertexColorGL{compile(flags, drawCount)} {} +template VertexColorGL::VertexColorGL(Flags flags, UnsignedInt drawCount): + VertexColorGL{compile(flags, drawCount)} {} #endif template VertexColorGL::VertexColorGL(NoInitT) {} - template VertexColorGL& VertexColorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), diff --git a/src/Magnum/Shaders/VertexColorGL.h b/src/Magnum/Shaders/VertexColorGL.h index e674f05a17..988af78114 100644 --- a/src/Magnum/Shaders/VertexColorGL.h +++ b/src/Magnum/Shaders/VertexColorGL.h @@ -443,13 +443,13 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ #endif }; -template class VertexColorGL::CompileState : public VertexColorGL { +template class VertexColorGL::CompileState: public VertexColorGL { private: friend class VertexColorGL; - explicit CompileState(NoCreateT) : VertexColorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} + explicit CompileState(NoCreateT): VertexColorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} - CompileState(VertexColorGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version) : + 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; From dd51e272473aa3c0722fb11a432ca8ce1e1b36e2 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Wed, 24 Aug 2022 19:21:44 +0300 Subject: [PATCH 24/27] Fix MeshVisualizer & tests --- src/Magnum/Shaders/MeshVisualizerGL.cpp | 25 +++++++++---------- src/Magnum/Shaders/MeshVisualizerGL.h | 6 ++--- .../Shaders/Test/MeshVisualizerGLTest.cpp | 6 ++--- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/Magnum/Shaders/MeshVisualizerGL.cpp b/src/Magnum/Shaders/MeshVisualizerGL.cpp index ce9d8b092f..6aaaac536f 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.cpp +++ b/src/Magnum/Shaders/MeshVisualizerGL.cpp @@ -903,19 +903,7 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags return CompileState{std::move(out), std::move(vert), std::move(frag), std::move(geom), flags, version}; } -MeshVisualizerGL3D::MeshVisualizerGL3D(Flags flags) : MeshVisualizerGL3D{compile(flags)} {} - -#ifndef MAGNUM_TARGET_GLES2 -MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags) { - return compile(flags, 1, 1); -} - -MeshVisualizerGL3D::MeshVisualizerGL3D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount) - : MeshVisualizerGL3D{compile(flags, materialCount, drawCount)} {} -#endif - -MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& cs) -: MeshVisualizerGL3D{static_cast(std::move(cs))} { +MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& cs): MeshVisualizerGL3D{static_cast(std::move(cs))} { if (id() == 0) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); @@ -1055,6 +1043,17 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& cs) static_cast(version); } +MeshVisualizerGL3D::MeshVisualizerGL3D(Flags flags) : MeshVisualizerGL3D{compile(flags)} {} + +#ifndef MAGNUM_TARGET_GLES2 +MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags) { + return compile(flags, 1, 1); +} + +MeshVisualizerGL3D::MeshVisualizerGL3D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): + MeshVisualizerGL3D{compile(flags, materialCount, drawCount)} {} +#endif + MeshVisualizerGL3D& MeshVisualizerGL3D::setTransformationMatrix(const Matrix4& matrix) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(flags() >= Flag::UniformBuffers), diff --git a/src/Magnum/Shaders/MeshVisualizerGL.h b/src/Magnum/Shaders/MeshVisualizerGL.h index 33ec8e3298..aa58e7f450 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.h +++ b/src/Magnum/Shaders/MeshVisualizerGL.h @@ -886,13 +886,13 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua Int _transformationProjectionMatrixUniform{9}; }; -class MeshVisualizerGL2D::CompileState : public MeshVisualizerGL2D { +class MeshVisualizerGL2D::CompileState: public MeshVisualizerGL2D { private: friend class MeshVisualizerGL2D; - explicit CompileState(NoCreateT) : MeshVisualizerGL2D{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} + 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) : + 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; diff --git a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp index f822d91ed9..e08e7bd82f 100644 --- a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp +++ b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp @@ -1546,6 +1546,7 @@ void MeshVisualizerGLTest::constructUniformBuffers2DAsync() { } #endif + void MeshVisualizerGLTest::construct3D() { auto&& data = ConstructData3D[testCaseInstanceId()]; setTestCaseDescription(data.name); @@ -1612,10 +1613,9 @@ void MeshVisualizerGLTest::construct3DAsync() { while(!compileState.isLinkFinished()) Utility::System::sleep(100); - // TODO: FIXME MeshVisualizerGL3D shader{std::move(compileState)}; - MeshVisualizerGL3D shader{MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader}; + MeshVisualizerGL3D shader{std::move(compileState)}; CORRADE_COMPARE(shader.flags(), MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); - CORRADE_VERIFY(compileState.isLinkFinished()); + CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); { #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) From 9a0af4d3bbfdf040b109d1c761f4a661ce9f10fa Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Wed, 24 Aug 2022 19:48:15 +0300 Subject: [PATCH 25/27] Fix unused vars --- src/Magnum/Shaders/DistanceFieldVectorGL.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp index 2d1dbf70ff..91ebe3acf1 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp @@ -225,6 +225,9 @@ template DistanceFieldVectorGL::DistanceFiel setSmoothness(0.04f); } #endif + + static_cast(context); + static_cast(version); } template DistanceFieldVectorGL::DistanceFieldVectorGL(NoInitT) {} From 1e363fdab833f2dbfc9561949984d6eba5027e63 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Wed, 24 Aug 2022 20:05:53 +0300 Subject: [PATCH 26/27] Fix MeshVisualizer test case --- .../Shaders/Test/MeshVisualizerGLTest.cpp | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp index e08e7bd82f..fbe96056e2 100644 --- a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp +++ b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp @@ -1706,32 +1706,23 @@ void MeshVisualizerGLTest::constructUniformBuffers3D() { } void MeshVisualizerGLTest::constructUniformBuffers3DAsync() { - constexpr struct { - const char* name; - MeshVisualizerGL3D::Flags flags; - UnsignedInt materialCount, drawCount; - } data { - "multiple materials, draws", MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader, 8, 55 - }; - setTestCaseDescription(data.name); - #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) 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, 8, 55); + 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(), 8); - CORRADE_COMPARE(compileState.drawCount(), 55); + CORRADE_COMPARE(compileState.materialCount(), 6); + CORRADE_COMPARE(compileState.drawCount(), 28); while(!compileState.isLinkFinished()) Utility::System::sleep(100); MeshVisualizerGL3D shader{std::move(compileState)}; CORRADE_COMPARE(shader.flags(), MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); - CORRADE_COMPARE(compileState.materialCount(), 8); - CORRADE_COMPARE(compileState.drawCount(), 55); + CORRADE_COMPARE(compileState.materialCount(), 6); + CORRADE_COMPARE(compileState.drawCount(), 28); CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.id()); { From ebbed673b2a919e494d0fbe22c8a294f0e492c2a Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Sat, 3 Sep 2022 23:49:59 +0300 Subject: [PATCH 27/27] Fixes --- src/Magnum/GL/AbstractShaderProgram.h | 2 +- src/Magnum/GL/Implementation/ShaderProgramState.h | 4 +++- src/Magnum/GL/Implementation/ShaderState.h | 4 +++- src/Magnum/GL/Shader.h | 2 +- src/Magnum/Shaders/DistanceFieldVectorGL.cpp | 2 -- src/Magnum/Shaders/FlatGL.cpp | 2 -- src/Magnum/Shaders/VectorGL.cpp | 2 -- src/Magnum/Shaders/VertexColorGL.cpp | 2 -- src/MagnumExternal/OpenGL/GL/flextGL.h | 2 +- 9 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.h b/src/Magnum/GL/AbstractShaderProgram.h index f72621ecac..4bde9b65d5 100644 --- a/src/Magnum/GL/AbstractShaderProgram.h +++ b/src/Magnum/GL/AbstractShaderProgram.h @@ -1699,7 +1699,7 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { static MAGNUM_GL_LOCAL void cleanLogImplementationAngle(std::string& message); #endif - static MAGNUM_GL_LOCAL void completionStatusImplementationFallback(GLuint, GLenum, GLint*); + static MAGNUM_GL_LOCAL APIENTRY void completionStatusImplementationFallback(GLuint, GLenum, GLint*); MAGNUM_GL_LOCAL static void use(GLuint id); void use(); diff --git a/src/Magnum/GL/Implementation/ShaderProgramState.h b/src/Magnum/GL/Implementation/ShaderProgramState.h index e057e5aad0..95001ea806 100644 --- a/src/Magnum/GL/Implementation/ShaderProgramState.h +++ b/src/Magnum/GL/Implementation/ShaderProgramState.h @@ -47,7 +47,9 @@ struct ShaderProgramState { void(AbstractShaderProgram::*transformFeedbackVaryingsImplementation)(Containers::ArrayView, AbstractShaderProgram::TransformFeedbackBufferMode); #endif void(*cleanLogImplementation)(std::string&); - void(*completionStatusImplementation)(GLuint, GLenum, GLint* value); + /* This is a direct pointer to a GL function, so needs a __stdcall on + Windows to compile properly on 32 bits */ + void(APIENTRY *completionStatusImplementation)(GLuint, GLenum, GLint* value); #ifndef MAGNUM_TARGET_WEBGL void(APIENTRY *uniform1fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); diff --git a/src/Magnum/GL/Implementation/ShaderState.h b/src/Magnum/GL/Implementation/ShaderState.h index caddd741d3..4d37c764dc 100644 --- a/src/Magnum/GL/Implementation/ShaderState.h +++ b/src/Magnum/GL/Implementation/ShaderState.h @@ -53,7 +53,9 @@ struct ShaderState { void(Shader::*addSourceImplementation)(std::string); void(*cleanLogImplementation)(std::string&); - void(*completionStatusImplementation)(GLuint, GLenum, GLint* value); + /* This is a direct pointer to a GL function, so needs a __stdcall on + Windows to compile properly on 32 bits */ + void(APIENTRY *completionStatusImplementation)(GLuint, GLenum, GLint* value); GLint maxVertexOutputComponents, maxFragmentInputComponents; diff --git a/src/Magnum/GL/Shader.h b/src/Magnum/GL/Shader.h index 045d822bdd..0272c25991 100644 --- a/src/Magnum/GL/Shader.h +++ b/src/Magnum/GL/Shader.h @@ -680,7 +680,7 @@ class MAGNUM_GL_EXPORT Shader: public AbstractObject { static MAGNUM_GL_LOCAL void cleanLogImplementationIntelWindows(std::string& message); #endif - static MAGNUM_GL_LOCAL void completionStatusImplementationFallback(GLuint, GLenum, GLint*); + static MAGNUM_GL_LOCAL APIENTRY void completionStatusImplementationFallback(GLuint, GLenum, GLint*); Type _type; GLuint _id; diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp index 91ebe3acf1..6c627cf98b 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp @@ -166,8 +166,6 @@ template DistanceFieldVectorGL::DistanceFiel if (id() == 0) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); - CORRADE_INTERNAL_ASSERT_OUTPUT(cs._vert.checkCompile()); - CORRADE_INTERNAL_ASSERT_OUTPUT(cs._frag.checkCompile()); const GL::Context& context = GL::Context::current(); const GL::Version version = cs._version; diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 11718dc635..645d7eade1 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -241,8 +241,6 @@ template FlatGL::FlatGL(CompileState&& cs): if (id() == 0) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); - CORRADE_INTERNAL_ASSERT_OUTPUT(cs._vert.checkCompile()); - CORRADE_INTERNAL_ASSERT_OUTPUT(cs._frag.checkCompile()); const GL::Context& context = GL::Context::current(); const GL::Version version = cs._version; diff --git a/src/Magnum/Shaders/VectorGL.cpp b/src/Magnum/Shaders/VectorGL.cpp index b52aee517f..dd6ff2c074 100644 --- a/src/Magnum/Shaders/VectorGL.cpp +++ b/src/Magnum/Shaders/VectorGL.cpp @@ -168,8 +168,6 @@ template VectorGL::VectorGL(CompileState&& c if (id() == 0) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); - CORRADE_INTERNAL_ASSERT_OUTPUT(cs._vert.checkCompile()); - CORRADE_INTERNAL_ASSERT_OUTPUT(cs._frag.checkCompile()); const GL::Context& context = GL::Context::current(); const GL::Version version = cs._version; diff --git a/src/Magnum/Shaders/VertexColorGL.cpp b/src/Magnum/Shaders/VertexColorGL.cpp index d796a8aaa2..01af44cd11 100644 --- a/src/Magnum/Shaders/VertexColorGL.cpp +++ b/src/Magnum/Shaders/VertexColorGL.cpp @@ -146,8 +146,6 @@ template VertexColorGL::VertexColorGL(Compil if (id() == 0) return; CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink()); - CORRADE_INTERNAL_ASSERT_OUTPUT(cs._vert.checkCompile()); - CORRADE_INTERNAL_ASSERT_OUTPUT(cs._frag.checkCompile()); const GL::Context& context = GL::Context::current(); const GL::Version version = cs._version; diff --git a/src/MagnumExternal/OpenGL/GL/flextGL.h b/src/MagnumExternal/OpenGL/GL/flextGL.h index 626c8aff59..d11cc18804 100644 --- a/src/MagnumExternal/OpenGL/GL/flextGL.h +++ b/src/MagnumExternal/OpenGL/GL/flextGL.h @@ -1523,7 +1523,7 @@ typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum /* GL_VERSION_4_5 */ -#define GL_CONTEXT_LOST 0x0507 +#define GL_CONTEXT_LOST 0x0507 #define GL_LOWER_LEFT 0x8CA1 #define GL_UPPER_LEFT 0x8CA2 #define GL_NEGATIVE_ONE_TO_ONE 0x935E