diff options
-rw-r--r-- | src/mbgl/gl/attribute.cpp | 38 | ||||
-rw-r--r-- | src/mbgl/gl/attribute.hpp | 47 | ||||
-rw-r--r-- | src/mbgl/gl/context.cpp | 8 | ||||
-rw-r--r-- | src/mbgl/gl/context.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/gl/program.hpp | 11 |
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); } |