summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLauren Budorick <lauren@mapbox.com>2017-06-29 11:29:48 -0700
committerGitHub <noreply@github.com>2017-06-29 11:29:48 -0700
commitb5fed1172d77bac0ba122c73a9d30739a51e5028 (patch)
tree525af4167d907342f3c1ff00d9cf5ef7bbc6f385 /src
parentf836425be467ac9830d8f6b4caa98700ce87c19b (diff)
downloadqtlocation-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.cpp46
-rw-r--r--src/mbgl/gl/attribute.hpp12
-rw-r--r--src/mbgl/gl/program.hpp12
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