From cd989c7c8b3ea4a000902c992c5bb284e151ddc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 30 Sep 2024 18:48:55 +0200 Subject: [PATCH] GL: fix various Mesh test failures specific to WebGL 1. Annoying, nothing else. --- src/Magnum/GL/Test/MeshGLTest.cpp | 97 +++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 18 deletions(-) diff --git a/src/Magnum/GL/Test/MeshGLTest.cpp b/src/Magnum/GL/Test/MeshGLTest.cpp index 04e428c75..b2f5da65c 100644 --- a/src/Magnum/GL/Test/MeshGLTest.cpp +++ b/src/Magnum/GL/Test/MeshGLTest.cpp @@ -784,7 +784,12 @@ void MeshGLTest::construct() { } struct FloatShader: AbstractShaderProgram { - explicit FloatShader(Containers::StringView type, Containers::StringView conversion); + explicit FloatShader(Containers::StringView type, Containers::StringView conversion + /* See the definition for details */ + #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) + , bool dummy = false + #endif + ); }; void MeshGLTest::constructMove() { @@ -994,7 +999,15 @@ struct Checker { }; #ifndef DOXYGEN_GENERATING_OUTPUT -FloatShader::FloatShader(Containers::StringView type, Containers::StringView conversion) { +FloatShader::FloatShader(Containers::StringView type, Containers::StringView conversion + /* WebGL 1 requires that at least one attribute is not instanced. The + addVertexBufferInstancedFloat() and drawInstancedAttributeSingleInstance() + tests set this to true to add a dummy input (that isn't even present in + the mesh) to fix that. */ + #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) + , bool dummy + #endif +) { /* We need special version for ES3, because GLSL in ES2 doesn't support rectangle matrices */ #ifndef MAGNUM_TARGET_GLES @@ -1021,20 +1034,39 @@ FloatShader::FloatShader(Containers::StringView type, Containers::StringView con #endif vert.addSource(Utility::format( - "#if !defined(GL_ES) && __VERSION__ == 120\n" - "#define mediump\n" - "#endif\n" - "#if (defined(GL_ES) && __VERSION__ < 300) || __VERSION__ == 120\n" - "#define in attribute\n" - "#define out varying\n" - "#endif\n" - "in mediump {0} value;\n" - "out mediump {0} valueInterpolated;\n" - "void main() {{\n" - " valueInterpolated = value;\n" - " gl_PointSize = 1.0;\n" - " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" - "}}\n", type)); + #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) + dummy ? + "#if !defined(GL_ES) && __VERSION__ == 120\n" + "#define mediump\n" + "#endif\n" + "#if (defined(GL_ES) && __VERSION__ < 300) || __VERSION__ == 120\n" + "#define in attribute\n" + "#define out varying\n" + "#endif\n" + "in mediump {0} value;\n" + "in mediump float dummy;\n" + "out mediump {0} valueInterpolated;\n" + "void main() {{\n" + " valueInterpolated = value;\n" + " gl_PointSize = 1.0;\n" + " gl_Position = vec4(0.0, 0.0, dummy, 1.0);\n" + "}}\n" : + #endif + "#if !defined(GL_ES) && __VERSION__ == 120\n" + "#define mediump\n" + "#endif\n" + "#if (defined(GL_ES) && __VERSION__ < 300) || __VERSION__ == 120\n" + "#define in attribute\n" + "#define out varying\n" + "#endif\n" + "in mediump {0} value;\n" + "out mediump {0} valueInterpolated;\n" + "void main() {{\n" + " valueInterpolated = value;\n" + " gl_PointSize = 1.0;\n" + " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" + "}}\n", + type)); frag.addSource(Utility::format( "#if !defined(GL_ES) && __VERSION__ == 120\n" "#define mediump\n" @@ -3550,7 +3582,13 @@ void MeshGLTest::addVertexBufferInstancedFloat() { MAGNUM_VERIFY_NO_GL_ERROR(); - const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"), + const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)" + /* WebGL 1 requires that at least one attribute is not instanced. Add + a dummy input (that isn't even present in the mesh) to fix that. */ + #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) + , /* dummy */ true + #endif + ), #ifndef MAGNUM_TARGET_GLES2 RenderbufferFormat::RGBA8, #else @@ -3768,7 +3806,13 @@ void MeshGLTest::drawInstancedAttributeSingleInstance() { framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment{0}, renderbuffer) .bind(); - FloatShader shader{"float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"}; + FloatShader shader{"float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)" + /* WebGL 1 requires that at least one attribute is not instanced. Add + a dummy input (that isn't even present in the mesh) to fix that. */ + #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) + , /* dummy */ true + #endif + }; MAGNUM_VERIFY_NO_GL_ERROR(); @@ -3838,7 +3882,17 @@ MultiDrawShader::MultiDrawShader(bool vertexId, bool drawId) { "in mediump vec4 value;\n" "out mediump float valueInterpolated;\n" "void main() {\n" + /* WebGL 1 doesn't allow dynamic indexing into a vec4. Similar thing is + in MultiDrawInstancedShader below or in the SUBSCRIPTING_WORKAROUND + in Shaders/MeshVisualizer.vert. */ + #if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2) + " if(vertexOrDrawId == 0) valueInterpolated = value.x;\n" + " else if(vertexOrDrawId == 1) valueInterpolated = value.y;\n" + " else if(vertexOrDrawId == 2) valueInterpolated = value.z;\n" + " else valueInterpolated = value.w;\n" + #else " valueInterpolated = value[vertexOrDrawId];\n" + #endif " gl_PointSize = 1.0;\n" " gl_Position = vec4(position, 0.0, 1.0);\n" "}\n"); @@ -4644,6 +4698,13 @@ MultiDrawInstancedShader::MultiDrawInstancedShader(bool vertexId, bool drawId "void main() {\n" #ifndef MAGNUM_TARGET_GLES2 " valueInterpolated = value[vertexOrDrawIdOrInstanceOffset + gl_InstanceID];\n" + /* WebGL 1 doesn't allow dynamic indexing into a vec3. Similar thing is + in MultiDrawShader above or in the SUBSCRIPTING_WORKAROUND in + Shaders/MeshVisualizer.vert. */ + #elif defined(MAGNUM_TARGET_WEBGL) + " if(vertexOrDrawIdOrInstanceOffset + int(instanceId) == 0) valueInterpolated = value.x;\n" + " else if(vertexOrDrawIdOrInstanceOffset + int(instanceId) == 1) valueInterpolated = value.y;\n" + " else valueInterpolated = value.z;\n" #else " valueInterpolated = value[vertexOrDrawIdOrInstanceOffset + int(instanceId)];\n" #endif