summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mbgl/gl/attribute.cpp38
-rw-r--r--src/mbgl/gl/attribute.hpp47
-rw-r--r--src/mbgl/gl/context.cpp8
-rw-r--r--src/mbgl/gl/context.hpp2
-rw-r--r--src/mbgl/gl/program.hpp11
5 files changed, 35 insertions, 71 deletions
diff --git a/src/mbgl/gl/attribute.cpp b/src/mbgl/gl/attribute.cpp
index 4983a8c204..d5240b5b7a 100644
--- a/src/mbgl/gl/attribute.cpp
+++ b/src/mbgl/gl/attribute.cpp
@@ -1,47 +1,19 @@
#include <mbgl/gl/attribute.hpp>
#include <mbgl/gl/context.hpp>
-#include <mbgl/gl/defines.hpp>
namespace mbgl {
namespace gl {
using namespace platform;
-void bindAttributeLocation(Context& context, ProgramID id, AttributeLocation location, const char* name) {
- // We're using sequentially numberered attribute locations starting with 0. Therefore we can use
- // the location as a proxy for the number of attributes.
- if (location >= context.maximumVertexBindingCount) {
- // Don't bind the location on this hardware since it exceeds the limit (otherwise we'd get
- // an OpenGL error). This means we'll see rendering errors, and possibly slow rendering due
- // to unbound attributes.
+optional<AttributeLocation> queryLocation(ProgramID id, const char* name) {
+ GLint attributeLocation = MBGL_CHECK_ERROR(glGetAttribLocation(id, name));
+ if (attributeLocation != -1) {
+ return attributeLocation;
} else {
- MBGL_CHECK_ERROR(glBindAttribLocation(id, location, name));
+ return {};
}
}
-std::set<std::string> getActiveAttributes(ProgramID id) {
- std::set<std::string> activeAttributes;
-
- GLint attributeCount;
- MBGL_CHECK_ERROR(glGetProgramiv(id, GL_ACTIVE_ATTRIBUTES, &attributeCount));
-
- GLint maxAttributeLength;
- MBGL_CHECK_ERROR(glGetProgramiv(id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeLength));
-
- std::string attributeName;
- attributeName.resize(maxAttributeLength);
-
- GLsizei actualLength;
- GLint size;
- GLenum type;
-
- for (int32_t i = 0; i < attributeCount; i++) {
- MBGL_CHECK_ERROR(glGetActiveAttrib(id, i, maxAttributeLength, &actualLength, &size, &type, &attributeName[0]));
- activeAttributes.emplace(std::string(attributeName, 0, actualLength));
- }
-
- return activeAttributes;
-}
-
} // namespace gl
} // namespace mbgl
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp
index c7f9ba3fd4..c2e362da63 100644
--- a/src/mbgl/gl/attribute.hpp
+++ b/src/mbgl/gl/attribute.hpp
@@ -2,18 +2,12 @@
#include <mbgl/gfx/attribute.hpp>
#include <mbgl/gl/types.hpp>
-#include <mbgl/util/ignore.hpp>
+#include <mbgl/programs/attributes.hpp>
#include <mbgl/util/literal.hpp>
-#include <mbgl/util/indexed_tuple.hpp>
#include <mbgl/util/optional.hpp>
-#include <cstddef>
#include <vector>
-#include <set>
-#include <functional>
#include <string>
-#include <array>
-#include <limits>
namespace mbgl {
namespace gl {
@@ -21,9 +15,7 @@ namespace gl {
using AttributeBindingArray = std::vector<optional<gfx::AttributeBinding>>;
using NamedAttributeLocations = std::vector<std::pair<const std::string, AttributeLocation>>;
-class Context;
-void bindAttributeLocation(Context&, ProgramID, AttributeLocation, const char * name);
-std::set<std::string> getActiveAttributes(ProgramID);
+optional<AttributeLocation> queryLocation(ProgramID id, const char* name);
template <class>
class AttributeLocations;
@@ -37,24 +29,7 @@ private:
Locations locations;
public:
- AttributeLocations(Context& context, const ProgramID& id)
- : locations([&] {
- std::set<std::string> activeAttributes = getActiveAttributes(id);
-
- AttributeLocation location = 0;
- auto maybeBindLocation = [&](const char* name) -> optional<AttributeLocation> {
- if (activeAttributes.count(name)) {
- bindAttributeLocation(context, id, location, name);
- return location++;
- } else {
- return {};
- }
- };
-
- return Locations{ maybeBindLocation(
- concat_literals<&string_literal<'a', '_'>::value, &As::name>::value())... };
- }()) {
- }
+ AttributeLocations() = default;
template <class BinaryProgram>
AttributeLocations(const BinaryProgram& program)
@@ -62,6 +37,22 @@ public:
concat_literals<&string_literal<'a', '_'>::value, &As::name>::value())... } {
}
+ void queryLocations(const ProgramID& id) {
+ locations = Locations{
+ queryLocation(id, concat_literals<&string_literal<'a', '_'>::value, &As::name>::value())... };
+ using TypeOfFirst = typename std::tuple_element<0, std::tuple<As...>>::type;
+ auto first = locations.template get<TypeOfFirst>();
+ assert(first && first.value() == 0);
+ }
+
+ static constexpr const char* getFirstAttribName() {
+ // Static assert that attribute list starts with position: we bind it on location 0.
+ using TypeOfFirst = typename std::tuple_element<0, std::tuple<As...>>::type;
+ static_assert(std::is_same<attributes::pos, TypeOfFirst>::value || std::is_same<attributes::pos_offset, TypeOfFirst>::value ||
+ std::is_same<attributes::pos_normal, TypeOfFirst>::value, "Program must start with position related attribute.");
+ return concat_literals<&string_literal<'a', '_'>::value, TypeOfFirst::name>::value();
+ }
+
NamedAttributeLocations getNamedLocations() const {
NamedAttributeLocations result;
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index f1288dc7ed..da72bad41d 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -169,12 +169,18 @@ UniqueShader Context::createShader(ShaderType type, const std::initializer_list<
throw std::runtime_error("shader failed to compile");
}
-UniqueProgram Context::createProgram(ShaderID vertexShader, ShaderID fragmentShader) {
+UniqueProgram Context::createProgram(ShaderID vertexShader, ShaderID fragmentShader, const char* location0AttribName) {
UniqueProgram result { MBGL_CHECK_ERROR(glCreateProgram()), { this } };
MBGL_CHECK_ERROR(glAttachShader(result, vertexShader));
MBGL_CHECK_ERROR(glAttachShader(result, fragmentShader));
+ // It is important to have attribute at position 0 enabled: conveniently,
+ // position attribute is always first and always enabled. The integrity of
+ // this assumption is verified in AttributeLocations::queryLocations and
+ // AttributeLocations::getFirstAttribName.
+ MBGL_CHECK_ERROR(glBindAttribLocation(result, 0, location0AttribName));
+
linkProgram(result);
return result;
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index 41e5b5f22d..cf01733adf 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -50,7 +50,7 @@ public:
void enableDebugging();
UniqueShader createShader(ShaderType type, const std::initializer_list<const char*>& sources);
- UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader);
+ UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader, const char* location0AttribName);
UniqueProgram createProgram(BinaryProgramFormat binaryFormat, const std::string& binaryProgram);
void verifyProgramLinkage(ProgramID);
void linkProgram(ProgramID);
diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp
index 3757c442de..8540385e97 100644
--- a/src/mbgl/gl/program.hpp
+++ b/src/mbgl/gl/program.hpp
@@ -49,15 +49,10 @@ public:
const std::initializer_list<const char*>& fragmentSource)
: program(context.createProgram(
context.createShader(ShaderType::Vertex, vertexSource),
- context.createShader(ShaderType::Fragment, fragmentSource))),
- attributeLocations(context, program) {
- // Re-link program after manually binding only active attributes in Attributes::queryLocations
- context.linkProgram(program);
-
- // We have to re-initialize the uniforms state from the bindings as the uniform locations
- // get shifted on some implementations
+ context.createShader(ShaderType::Fragment, fragmentSource),
+ attributeLocations.getFirstAttribName())) {
+ attributeLocations.queryLocations(program);
uniformStates.queryLocations(program);
-
// Texture units are specified via uniforms as well, so we need query their locations
textureStates.queryLocations(program);
}