From 5f184bb6994a41c6f6f747314b8020143c06c2d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 19 Oct 2021 20:07:16 +0200 Subject: [PATCH] GL: fully implement ANGLE_base_vertex_base_instance on ES. It was used just for certain corner cases that weren't covered by {EXT,OES}_draw_elements_base_vertex already, but because of a wrongly understood extension interaction the EXT/OES multidraw entrypoint (which isn't implemented on ANGLE) was used from these as well. And while trying to disable the two extensions for the MeshGLTest I discovered the test half-expects the ANGLE variant to be implemented and so I finished it for both the single-draw and multi-draw case. The extension interaction that makes base-vertex multidraw calls broken on ANGLE will be fixed in the following commit. --- src/Magnum/GL/Implementation/MeshState.cpp | 28 +++++++-- src/Magnum/GL/Mesh.cpp | 8 +-- src/Magnum/GL/Mesh.h | 8 +-- src/Magnum/GL/Test/MeshGLTest.cpp | 73 ++++++++++++++++++++-- 4 files changed, 100 insertions(+), 17 deletions(-) diff --git a/src/Magnum/GL/Implementation/MeshState.cpp b/src/Magnum/GL/Implementation/MeshState.cpp index 55a86458b..6fecd4388 100644 --- a/src/Magnum/GL/Implementation/MeshState.cpp +++ b/src/Magnum/GL/Implementation/MeshState.cpp @@ -143,14 +143,25 @@ MeshState::MeshState(Context& context, ContextState& contextState, Containers::S drawElementsInstancedBaseVertexImplementation = glDrawElementsInstancedBaseVertexOES; #endif } else + #ifndef MAGNUM_TARGET_GLES2 + if(context.isExtensionSupported()) { + extensions[Extensions::ANGLE::base_vertex_base_instance::Index] = + Extensions::ANGLE::base_vertex_base_instance::string(); + + /* Have to wrap it to supply trivial instance count because there's no + non-instanced variant */ + drawElementsBaseVertexImplementation = Mesh::drawElementsBaseVertexImplementationANGLE; + drawRangeElementsBaseVertexImplementation = Mesh::drawRangeElementsBaseVertexImplementationANGLE; + drawElementsInstancedBaseVertexImplementation = Mesh::drawElementsInstancedBaseVertexImplementationANGLE; + } else + #endif #else if(context.isExtensionSupported()) { extensions[Extensions::WEBGL::draw_instanced_base_vertex_base_instance::Index] = Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string(); /* The WEBGL extension uses the same entrypoints as the ANGLE extension - it was based on, however we wrap it to supply trivial instance count - because there's no non-instanced variant. Only available since + it was based on, so it's the same as above. Only available since 1.39.15: https://github.com/emscripten-core/emscripten/pull/11054 */ #if __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 13915 drawElementsBaseVertexImplementation = Mesh::drawElementsBaseVertexImplementationANGLE; @@ -280,14 +291,23 @@ MeshState::MeshState(Context& context, ContextState& contextState, Containers::S extensions exist and why it isn't just one. */ multiDrawElementsBaseVertexImplementation = glMultiDrawElementsBaseVertexEXT; } else + #ifndef MAGNUM_TARGET_GLES2 + if(context.isExtensionSupported()) { + extensions[Extensions::ANGLE::base_vertex_base_instance::Index] = + Extensions::ANGLE::base_vertex_base_instance::string(); + + /* Have to wrap it to supply trivial instance counts because + there's no non-instanced variant */ + multiDrawElementsBaseVertexImplementation = Mesh::multiDrawElementsBaseVertexImplementationANGLE; + } else + #endif #else if(context.isExtensionSupported()) { extensions[Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::Index] = Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::string(); /* The WEBGL extension uses the same entrypoints as the ANGLE - extension it was based on, however we wrap it and supply trivial - instance counts because there's no non-instanced variant. Only + extension it was based on, so it's the same as above. Only available since 2.0.5: https://github.com/emscripten-core/emscripten/pull/12282 */ #if __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20005 multiDrawElementsBaseVertexImplementation = Mesh::multiDrawElementsBaseVertexImplementationANGLE; diff --git a/src/Magnum/GL/Mesh.cpp b/src/Magnum/GL/Mesh.cpp index e629f2366..37a984488 100644 --- a/src/Magnum/GL/Mesh.cpp +++ b/src/Magnum/GL/Mesh.cpp @@ -1281,7 +1281,7 @@ void Mesh::unbindImplementationVAO() {} #ifdef MAGNUM_TARGET_GLES #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) -#if defined(MAGNUM_TARGET_WEBGL) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915 +#if !defined(MAGNUM_TARGET_GLES2) && (!defined(MAGNUM_TARGET_WEBGL) || __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915) void Mesh::drawElementsBaseVertexImplementationANGLE(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint baseVertex) { glDrawElementsInstancedBaseVertexBaseInstanceANGLE(mode, count, type, indices, 1, baseVertex, 0); } @@ -1293,7 +1293,7 @@ void Mesh::drawElementsBaseVertexImplementationAssert(GLenum, GLsizei, GLenum, c #endif #ifndef MAGNUM_TARGET_GLES2 -#if defined(MAGNUM_TARGET_WEBGL) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915 +#if !defined(MAGNUM_TARGET_WEBGL) || __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915 void Mesh::drawRangeElementsBaseVertexImplementationANGLE(const GLenum mode, GLuint, GLuint, GLsizei count, GLenum type, const void* indices, GLint baseVertex) { glDrawElementsInstancedBaseVertexBaseInstanceANGLE(mode, count, type, indices, 1, baseVertex, 0); } @@ -1321,7 +1321,7 @@ void Mesh::drawElementsInstancedBaseVertexBaseInstanceImplementationAssert(GLenu CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): no extension available for instanced indexed mesh draw with base vertex and base instance specification", ); } -#if defined(MAGNUM_TARGET_WEBGL) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915 +#if !defined(MAGNUM_TARGET_WEBGL) || __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915 void Mesh::drawElementsInstancedBaseVertexImplementationANGLE(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instanceCount, GLint baseVertex) { glDrawElementsInstancedBaseVertexBaseInstanceANGLE(mode, count, type, indices, instanceCount, baseVertex, 0); } @@ -1334,7 +1334,7 @@ void Mesh::drawElementsInstancedBaseVertexImplementationAssert(GLenum, GLsizei, #endif #ifdef MAGNUM_TARGET_GLES -#if defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20005 +#if !defined(MAGNUM_TARGET_GLES2) && (!defined(MAGNUM_TARGET_WEBGL) || __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20005) void Mesh::multiDrawElementsBaseVertexImplementationANGLE(const GLenum mode, const GLsizei* const count, const GLenum type, const void* const* const indices, const GLsizei drawCount, const GLint* const baseVertex) { /** @todo merge with the allocation in multiDrawImplementationDefault */ Containers::ArrayView instanceCount; diff --git a/src/Magnum/GL/Mesh.h b/src/Magnum/GL/Mesh.h index 7eb2cf68e..d5082554c 100644 --- a/src/Magnum/GL/Mesh.h +++ b/src/Magnum/GL/Mesh.h @@ -1186,14 +1186,14 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { #ifdef MAGNUM_TARGET_GLES #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) - #if defined(MAGNUM_TARGET_WEBGL) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 13915 + #if !defined(MAGNUM_TARGET_GLES2) && (!defined(MAGNUM_TARGET_WEBGL) || __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915) static void MAGNUM_GL_LOCAL drawElementsBaseVertexImplementationANGLE(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint baseVertex); #endif static void MAGNUM_GL_LOCAL drawElementsBaseVertexImplementationAssert(GLenum, GLsizei, GLenum, const void*, GLint); #endif #ifndef MAGNUM_TARGET_GLES2 - #if defined(MAGNUM_TARGET_WEBGL) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 13915 + #if !defined(MAGNUM_TARGET_WEBGL) || __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915 static void MAGNUM_GL_LOCAL drawRangeElementsBaseVertexImplementationANGLE(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices, GLint baseVertex); #endif static void MAGNUM_GL_LOCAL drawRangeElementsBaseVertexImplementationAssert(GLenum, GLuint, GLuint, GLsizei, GLenum, const void*, GLint); @@ -1207,7 +1207,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { static void MAGNUM_GL_LOCAL drawElementsInstancedBaseVertexBaseInstanceImplementationAssert(GLenum, GLsizei, GLenum, const void*, GLsizei, GLint, GLuint); - #if defined(MAGNUM_TARGET_WEBGL) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 13915 + #if !defined(MAGNUM_TARGET_WEBGL) || __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915 static void MAGNUM_GL_LOCAL drawElementsInstancedBaseVertexImplementationANGLE(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instanceCount, GLint baseVertex); #endif static void MAGNUM_GL_LOCAL drawElementsInstancedBaseVertexImplementationAssert(GLenum, GLsizei, GLenum, const void*, GLsizei, GLint); @@ -1215,7 +1215,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { #endif #ifdef MAGNUM_TARGET_GLES - #if defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20005 + #if !defined(MAGNUM_TARGET_GLES2) && (!defined(MAGNUM_TARGET_WEBGL) || __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20005) static MAGNUM_GL_LOCAL void multiDrawElementsBaseVertexImplementationANGLE(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices, GLsizei drawCount, const GLint* baseVertex); #endif static MAGNUM_GL_LOCAL void multiDrawElementsBaseVertexImplementationAssert(GLenum, const GLsizei*, GLenum, const void* const*, GLsizei, const GLint*); diff --git a/src/Magnum/GL/Test/MeshGLTest.cpp b/src/Magnum/GL/Test/MeshGLTest.cpp index 4a0b968ae..74a368104 100644 --- a/src/Magnum/GL/Test/MeshGLTest.cpp +++ b/src/Magnum/GL/Test/MeshGLTest.cpp @@ -2970,9 +2970,18 @@ void MeshGLTest::setBaseVertex() { if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() << "is not supported."); #elif !defined(MAGNUM_TARGET_WEBGL) + #ifndef MAGNUM_TARGET_GLES2 + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported() + ) + CORRADE_SKIP("Neither" << Extensions::OES::draw_elements_base_vertex::string() << "nor" << Extensions::EXT::draw_elements_base_vertex::string() << "nor" << Extensions::ANGLE::base_vertex_base_instance::string() << "is supported."); + #else if(!Context::current().isExtensionSupported() && - !Context::current().isExtensionSupported()) + !Context::current().isExtensionSupported() + ) CORRADE_SKIP("Neither" << Extensions::OES::draw_elements_base_vertex::string() << "nor" << Extensions::EXT::draw_elements_base_vertex::string() << "is supported."); + #endif #else if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() << "is not supported."); @@ -3010,6 +3019,10 @@ void MeshGLTest::setBaseVertexNoExtensionAvailable() { CORRADE_SKIP(Extensions::EXT::draw_elements_base_vertex::string() << "is supported."); if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::OES::draw_elements_base_vertex::string() << "is supported."); + #ifndef MAGNUM_TARGET_GLES2 + if(Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() << "is supported."); + #endif #elif !defined(MAGNUM_TARGET_GLES2) if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() << "is supported."); @@ -3042,6 +3055,10 @@ void MeshGLTest::setBaseVertexRangeNoExtensionAvailable() { CORRADE_SKIP(Extensions::EXT::draw_elements_base_vertex::string() << "is supported."); if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::OES::draw_elements_base_vertex::string() << "is supported."); + #ifndef MAGNUM_TARGET_GLES2 + if(Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() << "is supported."); + #endif #elif !defined(MAGNUM_TARGET_GLES2) if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() << "is supported."); @@ -3314,9 +3331,18 @@ void MeshGLTest::setInstanceCountIndexedBaseVertex() { if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() << "is not supported."); #elif !defined(MAGNUM_TARGET_WEBGL) + #ifndef MAGNUM_TARGET_GLES2 + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported() + ) + CORRADE_SKIP("Neither" << Extensions::OES::draw_elements_base_vertex::string() << "nor" << Extensions::EXT::draw_elements_base_vertex::string() << "nor" << Extensions::ANGLE::base_vertex_base_instance::string() << "is supported."); + #else if(!Context::current().isExtensionSupported() && - !Context::current().isExtensionSupported()) + !Context::current().isExtensionSupported() + ) CORRADE_SKIP("Neither" << Extensions::OES::draw_elements_base_vertex::string() << "nor" << Extensions::EXT::draw_elements_base_vertex::string() << "is supported."); + #endif #else if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() << "is not supported."); @@ -3356,6 +3382,8 @@ void MeshGLTest::setInstanceCountIndexedBaseVertexNoExtensionAvailable() { CORRADE_SKIP(Extensions::EXT::draw_elements_base_vertex::string() << "is supported."); if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::OES::draw_elements_base_vertex::string() << "is supported."); + if(Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() << "is supported."); #else if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() << "is supported."); @@ -4022,9 +4050,18 @@ template void MeshGLTest::multiDrawIndexed() { if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() << "is not supported."); #elif !defined(MAGNUM_TARGET_WEBGL) + #ifndef MAGNUM_TARGET_GLES2 + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported() + ) + CORRADE_SKIP("Neither" << Extensions::OES::draw_elements_base_vertex::string() << "nor" << Extensions::EXT::draw_elements_base_vertex::string() << "nor" << Extensions::ANGLE::base_vertex_base_instance::string() << "is supported."); + #else if(!Context::current().isExtensionSupported() && - !Context::current().isExtensionSupported()) + !Context::current().isExtensionSupported() + ) CORRADE_SKIP("Neither" << Extensions::OES::draw_elements_base_vertex::string() << "nor" << Extensions::EXT::draw_elements_base_vertex::string() << "is supported."); + #endif #elif !defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::string() << "is not supported."); @@ -4100,9 +4137,18 @@ template void MeshGLTest::multiDrawIndexedSparseArrays() { if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() << "is not supported."); #elif !defined(MAGNUM_TARGET_WEBGL) + #ifndef MAGNUM_TARGET_GLES2 + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported() + ) + CORRADE_SKIP("Neither" << Extensions::OES::draw_elements_base_vertex::string() << "nor" << Extensions::EXT::draw_elements_base_vertex::string() << "nor" << Extensions::ANGLE::base_vertex_base_instance::string() << "is supported."); + #else if(!Context::current().isExtensionSupported() && - !Context::current().isExtensionSupported()) + !Context::current().isExtensionSupported() + ) CORRADE_SKIP("Neither" << Extensions::OES::draw_elements_base_vertex::string() << "nor" << Extensions::EXT::draw_elements_base_vertex::string() << "is supported."); + #endif #elif !defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::string() << "is not supported."); @@ -4174,9 +4220,18 @@ void MeshGLTest::multiDrawIndexedViews() { if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() << "is not supported."); #elif !defined(MAGNUM_TARGET_WEBGL) + #ifndef MAGNUM_TARGET_GLES2 + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported() + ) + CORRADE_SKIP("Neither" << Extensions::OES::draw_elements_base_vertex::string() << "nor" << Extensions::EXT::draw_elements_base_vertex::string() << "nor" << Extensions::ANGLE::base_vertex_base_instance::string() << "is supported."); + #else if(!Context::current().isExtensionSupported() && - !Context::current().isExtensionSupported()) + !Context::current().isExtensionSupported() + ) CORRADE_SKIP("Neither" << Extensions::OES::draw_elements_base_vertex::string() << "nor" << Extensions::EXT::draw_elements_base_vertex::string() << "is supported."); + #endif #elif !defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::string() << "is not supported."); @@ -4320,6 +4375,10 @@ void MeshGLTest::multiDrawIndexedBaseVertexNoExtensionAvailable() { CORRADE_SKIP(Extensions::EXT::draw_elements_base_vertex::string() << "is supported."); if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::OES::draw_elements_base_vertex::string() << "is supported."); + #ifndef MAGNUM_TARGET_GLES2 + if(Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() << "is supported."); + #endif #elif !defined(MAGNUM_TARGET_GLES2) if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::string() << "is supported."); @@ -4361,6 +4420,10 @@ void MeshGLTest::multiDrawIndexedViewsBaseVertexNoExtensionAvailable() { CORRADE_SKIP(Extensions::EXT::draw_elements_base_vertex::string() << "is supported."); if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::OES::draw_elements_base_vertex::string() << "is supported."); + #ifndef MAGNUM_TARGET_GLES2 + if(Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() << "is supported."); + #endif #elif !defined(MAGNUM_TARGET_GLES2) if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::string() << "is supported.");