From b5fed1172d77bac0ba122c73a9d30739a51e5028 Mon Sep 17 00:00:00 2001 From: Lauren Budorick Date: Thu, 29 Jun 2017 11:29:48 -0700 Subject: [core] Bind only active attributes in order to avoid exceeding attribute limits (#9373) Introducing two new attributes to enable property functions for line-width (#9250) pushed the attribute count over GL_MAX_VERTEX_ATTRIBS on some devices. Now we selectively bind only attributes that are used, making it unlikely to surpass GL_MAX_VERTEX_ATTRIBS. --- src/mbgl/gl/attribute.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/mbgl/gl/attribute.hpp | 12 +++++++++++- src/mbgl/gl/program.hpp | 12 +++++++----- 3 files changed, 64 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/mbgl/gl/attribute.cpp b/src/mbgl/gl/attribute.cpp index e05ca75866..4e6f78e689 100644 --- a/src/mbgl/gl/attribute.cpp +++ b/src/mbgl/gl/attribute.cpp @@ -2,14 +2,55 @@ #include #include +#include + namespace mbgl { namespace gl { AttributeLocation bindAttributeLocation(ProgramID id, AttributeLocation location, const char* name) { + assert(location < 8); MBGL_CHECK_ERROR(glBindAttribLocation(id, location, name)); return location; } +int32_t getActiveAttributeCount(ProgramID id) { + GLint numAttributes; + MBGL_CHECK_ERROR(glGetProgramiv(id, GL_ACTIVE_ATTRIBUTES, &numAttributes)); + return numAttributes; +} + +int32_t getMaxAttributeNameLength(ProgramID id) { + GLint nameLength; + MBGL_CHECK_ERROR(glGetProgramiv(id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &nameLength)); + return nameLength; +} + +std::string getAttributeName(ProgramID id, int32_t maxLength, AttributeLocation location) { + std::string attributeName; + attributeName.resize(maxLength); + GLsizei actualLength; + GLint size; + GLenum type; + MBGL_CHECK_ERROR(glGetActiveAttrib(id, static_cast(location), + static_cast(maxLength), &actualLength, &size, &type, + const_cast(attributeName.data()))); + attributeName.resize(actualLength); + return attributeName; +} + +std::set getActiveAttributes(ProgramID id) { + std::set activeAttributes; + + GLint attributeCount = getActiveAttributeCount(id); + GLint maxAttributeLength = getMaxAttributeNameLength(id); + + for (int32_t i = 0; i < attributeCount; i++) { + activeAttributes.emplace(getAttributeName(id, maxAttributeLength, i)); + } + + return activeAttributes; +} + void DisabledAttribute::bind(Context&, AttributeLocation location, std::size_t) const { MBGL_CHECK_ERROR(glDisableVertexAttribArray(location)); } @@ -25,6 +66,11 @@ template <> DataType DataTypeOf = DataType::Float; template void AttributeBinding::bind(Context& context, AttributeLocation location, std::size_t vertexOffset) const { + // FillProgram will attempt to bind at location -1 because it includes + // a fill-outline-color paint property but does not use it or have an + // a_outline_color shader attribute - in this case, we have nothing to bind. + if (location == -1) return; + context.vertexBuffer = vertexBuffer; MBGL_CHECK_ERROR(glEnableVertexAttribArray(location)); MBGL_CHECK_ERROR(glVertexAttribPointer( diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index 48222146fa..f018a1d261 100644 --- a/src/mbgl/gl/attribute.hpp +++ b/src/mbgl/gl/attribute.hpp @@ -8,6 +8,7 @@ #include #include +#include #include namespace mbgl { @@ -223,6 +224,7 @@ const std::size_t Vertex::attributeOffsets[5] = { } // namespace detail AttributeLocation bindAttributeLocation(ProgramID, AttributeLocation, const char * name); +std::set getActiveAttributes(ProgramID); template class Attributes { @@ -242,7 +244,15 @@ public: static constexpr std::size_t Index = TypeIndex::value; static Locations bindLocations(const ProgramID& id) { - return Locations { bindAttributeLocation(id, Index, As::name())... }; + std::set activeAttributes = getActiveAttributes(id); + + AttributeLocation location = -1; + auto bindAndIncrement = [&](const char* name) { + location++; + return bindAttributeLocation(id, location, name); + }; + return Locations{ (activeAttributes.count(As::name()) ? bindAndIncrement(As::name()) + : -1)... }; } template diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp index 47ad39de7c..583d53e4ec 100644 --- a/src/mbgl/gl/program.hpp +++ b/src/mbgl/gl/program.hpp @@ -33,15 +33,17 @@ public: : program( context.createProgram(context.createShader(ShaderType::Vertex, vertexSource), context.createShader(ShaderType::Fragment, fragmentSource))), - attributeLocations(Attributes::bindLocations(program)), - uniformsState((context.linkProgram(program), Uniforms::bindLocations(program))) { + uniformsState((context.linkProgram(program), Uniforms::bindLocations(program))), + attributeLocations(Attributes::bindLocations(program)) { + // Re-link program after manually binding only active attributes in Attributes::bindLocations + context.linkProgram(program); } template Program(Context& context, const BinaryProgram& binaryProgram) : program(context.createProgram(binaryProgram.format(), binaryProgram.code())), - attributeLocations(Attributes::loadNamedLocations(binaryProgram)), - uniformsState(Uniforms::loadNamedLocations(binaryProgram)) { + uniformsState(Uniforms::loadNamedLocations(binaryProgram)), + attributeLocations(Attributes::loadNamedLocations(binaryProgram)) { } static Program createProgram(gl::Context& context, @@ -144,8 +146,8 @@ public: private: UniqueProgram program; - typename Attributes::Locations attributeLocations; typename Uniforms::State uniformsState; + typename Attributes::Locations attributeLocations; }; } // namespace gl -- cgit v1.2.1