From 32e0a2991c018f35b7156660e7074350400cfc3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Tue, 17 Mar 2020 17:01:26 +0200 Subject: [PATCH] Avoid redundant GL calls to glEnableVertexAttribArray() and glDisableVertexAttribArray(). #1960 --- src/renderer_gl.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++--- src/renderer_gl.h | 5 +++- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 17767ba56d..f145671582 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -1175,6 +1175,69 @@ namespace bgfx { namespace gl return 0 == err ? result : 0; } + static uint64_t currentlyEnabledVertexAttribArrays = 0; + static uint64_t vertexAttribArraysPendingDisable = 0; + static uint64_t vertexAttribArraysPendingEnable = 0; + + void lazyEnableVertexAttribArray(GLuint index) + { +#if BX_PLATFORM_EMSCRIPTEN + // On WebGL platform calling out to WebGL API is detrimental to performance, so optimize + // out redundant API calls to glEnable/DisableVertexAttribArray. + if (index >= 64) + { + glEnableVertexAttribArray(index); + return; + } + uint64_t mask = 1ULL << index; + vertexAttribArraysPendingEnable |= mask & (~currentlyEnabledVertexAttribArrays); + vertexAttribArraysPendingDisable &= ~mask; +#else + glEnableVertexAttribArray(index); +#endif + } + + void lazyDisableVertexAttribArray(GLuint index) + { +#if BX_PLATFORM_EMSCRIPTEN + // On WebGL platform calling out to WebGL API is detrimental to performance, so optimize + // out redundant API calls to glEnable/DisableVertexAttribArray. + if (index >= 64) + { + glDisableVertexAttribArray(index); + return; + } + uint64_t mask = 1ULL << index; + vertexAttribArraysPendingDisable |= mask & currentlyEnabledVertexAttribArrays; + vertexAttribArraysPendingEnable &= ~mask; +#else + glDisableVertexAttribArray(index); +#endif + } + + void applyLazyEnabledVertexAttributes() + { +#if BX_PLATFORM_EMSCRIPTEN + while(vertexAttribArraysPendingDisable) + { + int index = __builtin_ctzll(vertexAttribArraysPendingDisable); + uint64_t mask = ~(1ULL << index); + vertexAttribArraysPendingDisable &= mask; + currentlyEnabledVertexAttribArrays &= mask; + glDisableVertexAttribArray(index); + } + + while(vertexAttribArraysPendingEnable) + { + int index = __builtin_ctzll(vertexAttribArraysPendingEnable); + uint64_t mask = 1ULL << index; + vertexAttribArraysPendingEnable &= ~mask; + currentlyEnabledVertexAttribArrays |= mask; + glEnableVertexAttribArray(index); + } +#endif + } + void setTextureFormat(TextureFormat::Enum _format, GLenum _internalFmt, GLenum _fmt, GLenum _type = GL_ZERO) { TextureFormatInfo& tfi = s_textureFormat[_format]; @@ -4570,7 +4633,7 @@ namespace bgfx { namespace gl { if (UINT16_MAX != _layout.m_attributes[attr]) { - GL_CHECK(glEnableVertexAttribArray(loc) ); + GL_CHECK(lazyEnableVertexAttribArray(loc) ); GL_CHECK(glVertexAttribDivisor(loc, 0) ); uint32_t baseVertex = _baseVertex*_layout.m_stride + _layout.m_offset[attr]; @@ -4600,6 +4663,7 @@ namespace bgfx { namespace gl } } } + applyLazyEnabledVertexAttributes(); } void ProgramGL::unbindAttributes() @@ -4610,7 +4674,7 @@ namespace bgfx { namespace gl { Attrib::Enum attr = Attrib::Enum(m_used[ii]); GLint loc = m_attributes[attr]; - GL_CHECK(glDisableVertexAttribArray(loc)); + GL_CHECK(lazyDisableVertexAttribArray(loc)); } } } @@ -4621,7 +4685,7 @@ namespace bgfx { namespace gl for (uint32_t ii = 0; 0xffff != m_instanceData[ii]; ++ii) { GLint loc = m_instanceData[ii]; - GL_CHECK(glEnableVertexAttribArray(loc) ); + GL_CHECK(lazyEnableVertexAttribArray(loc) ); GL_CHECK(glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, _stride, (void*)(uintptr_t)baseVertex) ); GL_CHECK(glVertexAttribDivisor(loc, 1) ); baseVertex += 16; @@ -4633,7 +4697,7 @@ namespace bgfx { namespace gl for(uint32_t ii = 0; 0xffff != m_instanceData[ii]; ++ii) { GLint loc = m_instanceData[ii]; - GL_CHECK(glDisableVertexAttribArray(loc)); + GL_CHECK(lazyDisableVertexAttribArray(loc)); } } diff --git a/src/renderer_gl.h b/src/renderer_gl.h index aa20a5b568..ab552563ac 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -1094,6 +1094,9 @@ namespace bgfx { namespace gl { void dumpExtensions(const char* _extensions); + void lazyEnableVertexAttribArray(GLuint index); + void lazyDisableVertexAttribArray(GLuint index); + const char* glEnumName(GLenum _enum); #define _GL_CHECK(_check, _call) \ @@ -1392,7 +1395,7 @@ namespace bgfx { namespace gl { Attrib::Enum attr = Attrib::Enum(m_unboundUsedAttrib[ii]); GLint loc = m_attributes[attr]; - GL_CHECK(glDisableVertexAttribArray(loc) ); + GL_CHECK(lazyDisableVertexAttribArray(loc) ); } } }