diff --git a/src/Magnum/GL/AbstractShaderProgram.cpp b/src/Magnum/GL/AbstractShaderProgram.cpp index 3714f7b24..39e6ad7c6 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 54db33c86..60d2f1386 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 1b1441361..ec2510356 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 1b481ef06..9d61d2a40 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 152104c07..650c583c7 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