From cf9b90ff9b7304cf72fba9bf775dca60d4bc5c92 Mon Sep 17 00:00:00 2001 From: Vladislav Oleshko Date: Sat, 13 Aug 2022 14:00:53 +0300 Subject: [PATCH] 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 a23561463..125e6a552 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 1a59c564b..860e5f56c 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 e6414a2c2..6057fd7fe 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() {