diff options
author | Lauren Budorick <lauren@mapbox.com> | 2017-06-29 11:29:48 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-29 11:29:48 -0700 |
commit | b5fed1172d77bac0ba122c73a9d30739a51e5028 (patch) | |
tree | 525af4167d907342f3c1ff00d9cf5ef7bbc6f385 /src | |
parent | f836425be467ac9830d8f6b4caa98700ce87c19b (diff) | |
download | qtlocation-mapboxgl-b5fed1172d77bac0ba122c73a9d30739a51e5028.tar.gz |
[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.
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/gl/attribute.cpp | 46 | ||||
-rw-r--r-- | src/mbgl/gl/attribute.hpp | 12 | ||||
-rw-r--r-- | src/mbgl/gl/program.hpp | 12 |
3 files changed, 64 insertions, 6 deletions
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 <mbgl/gl/context.hpp> #include <mbgl/gl/gl.hpp> +#include <cstring> + 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<GLuint>(location), + static_cast<GLsizei>(maxLength), &actualLength, &size, &type, + const_cast<char*>(attributeName.data()))); + attributeName.resize(actualLength); + return attributeName; +} + +std::set<std::string> getActiveAttributes(ProgramID id) { + std::set<std::string> 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<float> = DataType::Float; template <class T, std::size_t N> void AttributeBinding<T, N>::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 <cstddef> #include <vector> +#include <set> #include <functional> namespace mbgl { @@ -223,6 +224,7 @@ const std::size_t Vertex<A1, A2, A3, A4, A5>::attributeOffsets[5] = { } // namespace detail AttributeLocation bindAttributeLocation(ProgramID, AttributeLocation, const char * name); +std::set<std::string> getActiveAttributes(ProgramID); template <class... As> class Attributes { @@ -242,7 +244,15 @@ public: static constexpr std::size_t Index = TypeIndex<A, As...>::value; static Locations bindLocations(const ProgramID& id) { - return Locations { bindAttributeLocation(id, Index<As>, As::name())... }; + std::set<std::string> 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 <class Program> 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 <class BinaryProgram> 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 |