From c8b31b846817b0176e8df3f5773e8aa2ecbd2f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 5 Jun 2017 19:22:32 +0200 Subject: [PATCH] Test that binding index buffer internally doesn't affect bound VAOs. Fails. Problem spotted on WebGL 2 and is an unfortunate consequence of these events: 1. Neither EXT_DSA nor ARB_DSA is available, but VAOs are available, which means virtually all ES 3 and WebGL 2 implementations and also ES 2 / WebGL 1 with OES_VAO available. 2. Index buffer gets created with TargetHint::ElementArray, bound to GL_ELEMENT_ARRAY_BUFFER and filled with data. 3. Mesh object with VAO inside is created and the index buffer from above gets bound to GL_ELEMENT_ARRAY_BUFFER again to attach it to the VAO. 4. Another index buffer, possibly for another mesh, gets created with TargetHint::ElementArray and bound to GL_ELEMENT_ARRAY_BUFFER in order to be filled with data. But because the VAO from above is still bound, the index buffer attachment is then stomped on. 5. Rendering such mesh will use a different index buffer, most probably causing some out-of-range GL error and nothing rendered. --- src/Magnum/Test/MeshGLTest.cpp | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/Magnum/Test/MeshGLTest.cpp b/src/Magnum/Test/MeshGLTest.cpp index c82cfe9f5..c998fc0a2 100644 --- a/src/Magnum/Test/MeshGLTest.cpp +++ b/src/Magnum/Test/MeshGLTest.cpp @@ -111,6 +111,8 @@ struct MeshGLTest: OpenGLTester { void setIndexBufferRange(); void setIndexBufferUnsignedInt(); + void unbindVAOWhenSettingIndexBufferData(); + #ifndef MAGNUM_TARGET_GLES void setBaseVertex(); #endif @@ -202,6 +204,8 @@ MeshGLTest::MeshGLTest() { &MeshGLTest::setIndexBufferRange, &MeshGLTest::setIndexBufferUnsignedInt, + &MeshGLTest::unbindVAOWhenSettingIndexBufferData, + #ifndef MAGNUM_TARGET_GLES &MeshGLTest::setBaseVertex, #endif @@ -1454,6 +1458,50 @@ void MeshGLTest::setIndexBufferUnsignedInt() { CORRADE_COMPARE(value, indexedResult); } +void MeshGLTest::unbindVAOWhenSettingIndexBufferData() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::vertex_array_object::string() + std::string(" is not available.")); + if(Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::direct_state_access::string() + std::string(" is active with circumvents the issue tested here.")); + if(Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::direct_state_access::string() + std::string(" is active with circumvents the issue tested here.")); + #elif defined(MAGNUM_TARGET_GLES2) + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::OES::vertex_array_object::string() + std::string(" is not available.")); + #endif + + typedef Attribute<0, Float> Attribute; + + const Float data[] = { -0.7f, Math::unpack(92), Math::unpack(32) }; + Buffer buffer{Buffer::TargetHint::Array}; + buffer.setData(data, BufferUsage::StaticDraw); + + Buffer indices{Buffer::TargetHint::ElementArray}; + indices.setData(std::vector{5, 0}, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.addVertexBuffer(buffer, 4, Attribute{}) + .setIndexBuffer(indices, 0, Mesh::IndexType::UnsignedByte); + + /* This buffer should have no effect on the mesh above */ + Buffer otherIndices{Buffer::TargetHint::ElementArray}; + otherIndices.setData(std::vector{100, 1}, BufferUsage::StaticDraw); + + MAGNUM_VERIFY_NO_ERROR(); + + const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"), + #ifndef MAGNUM_TARGET_GLES2 + RenderbufferFormat::RGBA8, + #else + RenderbufferFormat::RGBA4, + #endif + mesh).get(PixelFormat::RGBA, PixelType::UnsignedByte); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(value, 92); +} + #ifndef MAGNUM_TARGET_GLES void MeshGLTest::setBaseVertex() { if(!Context::current().isExtensionSupported())