From 6fe87cc7bf2cb19c6cd9dfe76d22f0f4b648bc10 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Mon, 1 Aug 2022 14:27:31 +0300 Subject: [PATCH] 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 658fa112e..18ec7b602 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 5c7978b77..32ad1a28b 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 c17fccd13..29c34cb61 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 730bb0fad..003ab2eb8 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() {