#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { namespace gl { using AttributeBindingArray = std::vector>; using NamedAttributeLocations = std::vector>; class Context; void bindAttributeLocation(Context&, ProgramID, AttributeLocation, const char * name); std::set getActiveAttributes(ProgramID); template class AttributeLocations; template class AttributeLocations> final { private: using Locations = IndexedTuple, TypeList>...>>; Locations locations; public: AttributeLocations(Context& context, const ProgramID& id) : locations([&] { std::set activeAttributes = getActiveAttributes(id); AttributeLocation location = 0; auto maybeBindLocation = [&](const char* name) -> optional { 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())... }; }()) { } template AttributeLocations(const BinaryProgram& program) : locations{ program.attributeLocation( concat_literals<&string_literal<'a', '_'>::value, &As::name>::value())... } { } NamedAttributeLocations getNamedLocations() const { NamedAttributeLocations result; auto maybeAddLocation = [&] (const std::string& name, const optional& location) { if (location) { result.emplace_back(name, *location); } }; util::ignore({ (maybeAddLocation(concat_literals<&string_literal<'a', '_'>::value, &As::name>::value(), locations.template get()), 0)... }); return result; } AttributeBindingArray toBindingArray(const gfx::AttributeBindings>& bindings) const { AttributeBindingArray result; result.resize(sizeof...(As)); auto maybeAddBinding = [&] (const optional& location, const optional& binding) { if (location) { result.at(*location) = binding; } }; util::ignore({ (maybeAddBinding(locations.template get(), bindings.template get()), 0)... }); return result; } }; template class AttributeKey; constexpr auto attributeDefinePrefix() { return "#define HAS_UNIFORM_u_"; } template class AttributeKey> final { public: static_assert(sizeof...(As) <= 32, "attribute count exceeds 32"); static uint32_t compute(const gfx::AttributeBindings>& bindings) { uint32_t value = 0; util::ignore( { (bindings.template get() ? (void)(value |= 1 << TypeIndex::value) : (void)0, 0)... }); return value; } static std::string defines(const gfx::AttributeBindings>& bindings) { std::string result; util::ignore({ (!bindings.template get() ? (void)(result += concat_literals<&attributeDefinePrefix, &As::name, &string_literal<'\n'>::value>::value()) : (void)0, 0)... }); return result; } }; } // namespace gl } // namespace mbgl