#pragma once #include #include #include #include #include #include #include namespace mbgl { namespace gl { using AttributeBindingArray = std::vector>; using NamedAttributeLocations = std::vector>; optional queryLocation(ProgramID id, const char* name); template class AttributeLocations; template class AttributeLocations> final { private: using Locations = IndexedTuple, TypeList>...>>; Locations locations; public: AttributeLocations() = default; 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>::type; auto first = locations.template get(); 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>::type; static_assert(std::is_same::value || std::is_same::value || std::is_same::value, "Program must start with position related attribute."); return concat_literals<&string_literal<'a', '_'>::value, TypeOfFirst::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