#pragma once #include #include #include #include #include #include namespace mbgl { namespace gl { template void bindUniform(UniformLocation, const T&); template class UniformValue { public: explicit UniformValue(T t_) : t(std::move(t_)) {} T t; }; template class Uniform { public: using Value = UniformValue; class State { public: void operator=(const Value& value) { if (!current || *current != value.t) { current = value.t; bindUniform(location, value.t); } } UniformLocation location; optional current = {}; }; }; template using UniformScalar = Uniform; template using UniformVector = Uniform>; template using UniformMatrix = Uniform>; #define MBGL_DEFINE_UNIFORM_SCALAR(type_, name_) \ struct name_ : ::mbgl::gl::UniformScalar { static auto name() { return #name_; } } #define MBGL_DEFINE_UNIFORM_VECTOR(type_, n_, name_) \ struct name_ : ::mbgl::gl::UniformVector { static auto name() { return #name_; } } #define MBGL_DEFINE_UNIFORM_MATRIX(type_, n_, name_) \ struct name_ : ::mbgl::gl::UniformMatrix { static auto name() { return #name_; } } UniformLocation uniformLocation(ProgramID, const char * name); template class Uniforms { public: using Types = TypeList; using State = IndexedTuple, TypeList>; using Values = IndexedTuple, TypeList>; static State state(const ProgramID& id) { return State { { uniformLocation(id, Us::name()) }... }; } static void bind(State& state, Values&& values) { util::ignore({ (state.template get() = values.template get(), 0)... }); } }; namespace detail { template struct ConcatenateUniforms; template struct ConcatenateUniforms, TypeList> { using Type = Uniforms; }; } // namespace detail template using ConcatenateUniforms = typename detail::ConcatenateUniforms< typename A::Types, typename B::Types>::Type; } // namespace gl } // namespace mbgl