summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2017-03-16 17:00:43 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2017-03-17 08:27:53 -0700
commitff413f6b99d7cb7b7482d56479f10e0a8fe83046 (patch)
treea0a7aab5a9eb785565b6d8c90632d864aa1101a5
parent0dca6cd9bfdb1fb77f7755d639f92a6a1ba06dc1 (diff)
downloadqtlocation-mapboxgl-ff413f6b99d7cb7b7482d56479f10e0a8fe83046.tar.gz
[core] Fix overspecialization of PaintPropertyBinder template
PaintPropertyBinder and subclass templates were being instantiated for every unique attribute type (e.g. a_color, a_fill_color, a_halo_color) even though they behave identically for a given property value type (e.g. Color). To fix this, a unique type such as a_color no longer derives from gl::Attribute<...> -- instead it has an inner Type typedef, which should be used wherever neither a unique type nor attribute name is required. This reduces binary size substantially: VM SIZE FILE SIZE ++++++++++++++ GROWING ++++++++++++++ -------------- SHRINKING -------------- -2.0% -49.3Ki __TEXT,__text -49.3Ki -2.0% -3.1% -5.21Ki [None] -2.79Ki -1.6% -2.1% -4.12Ki __TEXT,__const -4.12Ki -2.1% -1.4% -4.04Ki __TEXT,__gcc_except_tab -4.04Ki -1.4% -19.3% -3.62Ki __DATA,__data -3.62Ki -19.3% -2.5% -1.65Ki __TEXT,__unwind_info -1.65Ki -2.5% -4.2% -8 __DATA,__mod_init_func 0 [ = ] -1.9% -68.0Ki TOTAL -65.6Ki -1.9%
-rw-r--r--src/mbgl/gl/attribute.hpp27
-rw-r--r--src/mbgl/programs/attributes.hpp181
-rw-r--r--src/mbgl/style/paint_property_binder.hpp134
3 files changed, 150 insertions, 192 deletions
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp
index 43e2c2d794..ab97ada0f2 100644
--- a/src/mbgl/gl/attribute.hpp
+++ b/src/mbgl/gl/attribute.hpp
@@ -113,8 +113,11 @@ public:
}
};
-#define MBGL_DEFINE_ATTRIBUTE(type_, n_, name_) \
- struct name_ : ::mbgl::gl::Attribute<type_, n_> { static auto name() { return #name_; } }
+#define MBGL_DEFINE_ATTRIBUTE(type_, n_, name_) \
+ struct name_ { \
+ static auto name() { return #name_; } \
+ using Type = ::mbgl::gl::Attribute<type_, n_>; \
+ }
namespace detail {
@@ -234,15 +237,15 @@ public:
using Types = TypeList<As...>;
using Locations = IndexedTuple<
TypeList<As...>,
- TypeList<typename As::Location...>>;
+ TypeList<typename As::Type::Location...>>;
using Bindings = IndexedTuple<
TypeList<As...>,
- TypeList<typename As::Binding...>>;
+ TypeList<typename As::Type::Binding...>>;
using VariableBindings = IndexedTuple<
TypeList<As...>,
- TypeList<optional<typename As::VariableBinding>...>>;
+ TypeList<optional<typename As::Type::VariableBinding>...>>;
- using Vertex = detail::Vertex<As...>;
+ using Vertex = detail::Vertex<typename As::Type...>;
template <class A>
static constexpr std::size_t Index = TypeIndex<A, As...>::value;
@@ -253,7 +256,7 @@ public:
template <class DrawMode>
static Bindings allVariableBindings(const VertexBuffer<Vertex, DrawMode>& buffer) {
- return Bindings { As::variableBinding(buffer, Index<As>)... };
+ return Bindings { As::Type::variableBinding(buffer, Index<As>)... };
}
static void bind(Context& context,
@@ -261,11 +264,11 @@ public:
VariableBindings& oldBindings,
const Bindings& newBindings,
std::size_t vertexOffset) {
- util::ignore({ (As::bind(context,
- locations.template get<As>(),
- oldBindings.template get<As>(),
- newBindings.template get<As>(),
- vertexOffset), 0)... });
+ util::ignore({ (As::Type::bind(context,
+ locations.template get<As>(),
+ oldBindings.template get<As>(),
+ newBindings.template get<As>(),
+ vertexOffset), 0)... });
}
};
diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp
index b015c06366..7d39c04395 100644
--- a/src/mbgl/programs/attributes.hpp
+++ b/src/mbgl/programs/attributes.hpp
@@ -16,209 +16,104 @@ MBGL_DEFINE_ATTRIBUTE(int16_t, 4, a_pos_offset);
MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, a_texture_pos);
template <std::size_t N>
-struct a_data : gl::Attribute<uint8_t, N> {
+struct a_data {
static auto name() { return "a_data"; }
+ using Type = gl::Attribute<uint8_t, N>;
};
template <std::size_t N>
-struct a_offset : gl::Attribute<int16_t, N> {
+struct a_offset {
static auto name() { return "a_offset"; }
+ using Type = gl::Attribute<int16_t, N>;
};
// Paint attributes
-/*
- ZoomInterpolatedAttribute<Attr> is a 'compound' attribute, representing two values of the
- the base attribute Attr. These two values are provided to the shader to allow interpolation
- between zoom levels, without the need to repopulate vertex buffers each frame as the map is
- being zoomed.
-*/
-template <class Attr>
-struct ZoomInterpolatedAttribute : gl::Attribute<typename Attr::ValueType, Attr::Dimensions * 2> {
- using Value = typename gl::Attribute<typename Attr::ValueType, Attr::Dimensions * 2>::Value;
-
- static auto name() {
- return Attr::name();
- }
-
- template <class InputType>
- static Value value(const InputType& min, const InputType& max){
- auto minValue = Attr::value(min);
- auto maxValue = Attr::value(max);
- Value result = {{}};
- for (size_t i = 0; i < Attr::Dimensions; i++) {
- result[i] = minValue[i];
- result[Attr::Dimensions+i] = maxValue[i];
- }
- return result;
- }
-};
-
-template <class Attr>
-struct InterpolationUniform : gl::UniformScalar<InterpolationUniform<Attr>, float> {
- static auto name() {
- static const std::string name = Attr::name() + std::string("_t");
- return name.c_str();
- }
-};
-
-/*
- Encode a four-component color value into a pair of floats. Since csscolorparser
- uses 8-bit precision for each color component, for each float we use the upper 8
- bits for one component (e.g. (color.r * 255) * 256), and the lower 8 for another.
-
- Also note:
- - Colors come in as floats 0..1, so we scale by 255.
- - Casting the scaled values to ints is important: without doing this, e.g., the
- fractional part of the `r` component would corrupt the lower-8 bits of the encoded
- value, which must be reserved for the `g` component.
-*/
-static std::array<float, 2> encodeColor (const Color& color) {
- const auto v1 = static_cast<uint16_t>( static_cast<uint16_t>(color.r*255)*256 + color.g*255);
- const auto v2 = static_cast<uint16_t>( static_cast<uint16_t>(color.b*255)*256 + color.a*255);
- return {{ static_cast<float>(v1), static_cast<float>(v2) }};
-}
-
-struct a_color : gl::Attribute<float, 2> {
+struct a_color {
static auto name() { return "a_color"; }
-
- static Value value(const Color& color) {
- return encodeColor(color);
- }
+ using Type = gl::Attribute<float, 2>;
};
-// used in the symbol sdf shader
-struct a_fill_color : gl::Attribute<float, 2> {
+struct a_fill_color {
static auto name() { return "a_fill_color"; }
-
- static Value value(const Color& color) {
- return encodeColor(color);
- }
+ using Type = gl::Attribute<float, 2>;
};
-// used in the symbol sdf shader
-struct a_halo_color : gl::Attribute<float, 2> {
+struct a_halo_color {
static auto name() { return "a_halo_color"; }
-
- static Value value(const Color& color) {
- return encodeColor(color);
- }
+ using Type = gl::Attribute<float, 2>;
};
-struct a_stroke_color : gl::Attribute<float, 2> {
+struct a_stroke_color {
static auto name() { return "a_stroke_color"; }
-
- static Value value(const Color& color) {
- return encodeColor(color);
- }
+ using Type = gl::Attribute<float, 2>;
};
-struct a_outline_color : gl::Attribute<float, 2> {
+struct a_outline_color {
static auto name() { return "a_outline_color"; }
-
- static Value value(const Color& color) {
- return encodeColor(color);
- }
+ using Type = gl::Attribute<float, 2>;
};
-struct a_opacity : gl::Attribute<float, 1> {
+struct a_opacity {
static auto name() { return "a_opacity"; }
-
- static Value value(float opacity) {
- return {{ opacity }};
- }
+ using Type = gl::Attribute<float, 1>;
};
-struct a_stroke_opacity : gl::Attribute<float, 1> {
+struct a_stroke_opacity {
static auto name() { return "a_stroke_opacity"; }
-
- static Value value(float opacity) {
- return {{ opacity }};
- }
+ using Type = gl::Attribute<float, 1>;
};
-struct a_blur : gl::Attribute<float, 1> {
+struct a_blur {
static auto name() { return "a_blur"; }
-
- static Value value(float blur) {
- return {{ blur }};
- }
+ using Type = gl::Attribute<float, 1>;
};
-struct a_radius : gl::Attribute<float, 1> {
+struct a_radius {
static auto name() { return "a_radius"; }
-
- static Value value(float radius) {
- return {{ radius }};
- }
+ using Type = gl::Attribute<float, 1>;
};
-struct a_width : gl::Attribute<float, 1> {
+struct a_width {
static auto name() { return "a_width"; }
-
- static Value value(float width) {
- return {{ width }};
- }
+ using Type = gl::Attribute<float, 1>;
};
-struct a_height : gl::Attribute<float, 1> {
+struct a_height {
static auto name() { return "a_height"; }
-
- static Value value(float width) {
- return {{ width }};
- }
+ using Type = gl::Attribute<float, 1>;
};
-struct a_base : gl::Attribute<float, 1> {
+struct a_base {
static auto name() { return "a_base"; }
-
- static Value value(float width) {
- return {{ width }};
- }
+ using Type = gl::Attribute<float, 1>;
};
-struct a_gap_width : gl::Attribute<float, 1> {
+struct a_gap_width {
static auto name() { return "a_gapwidth"; }
-
- static Value value(float width) {
- return {{ width }};
- }
+ using Type = gl::Attribute<float, 1>;
};
-struct a_stroke_width : gl::Attribute<float, 1> {
+struct a_stroke_width {
static auto name() { return "a_stroke_width"; }
-
- static Value value(float width) {
- return {{ width }};
- }
+ using Type = gl::Attribute<float, 1>;
};
template <>
-struct a_offset<1> : gl::Attribute<float, 1> {
+struct a_offset<1> {
static auto name() { return "a_offset"; }
-
- static Value value(float offset) {
- return {{ offset }};
- }
+ using Type = gl::Attribute<float, 1>;
};
-struct a_halo_width : gl::Attribute<float, 1> {
+struct a_halo_width {
static auto name() { return "a_halo_width"; }
-
- static Value value(float width) {
- return {{ width }};
- }
+ using Type = gl::Attribute<float, 1>;
};
-struct a_halo_blur : gl::Attribute<float, 1> {
+struct a_halo_blur {
static auto name() { return "a_halo_blur"; }
-
- static Value value(float blur) {
- return {{ blur }};
- }
+ using Type = gl::Attribute<float, 1>;
};
-
-
} // namespace attributes
} // namespace mbgl
diff --git a/src/mbgl/style/paint_property_binder.hpp b/src/mbgl/style/paint_property_binder.hpp
index 630c1104f0..e6e957958c 100644
--- a/src/mbgl/style/paint_property_binder.hpp
+++ b/src/mbgl/style/paint_property_binder.hpp
@@ -8,11 +8,51 @@
namespace mbgl {
namespace style {
+/*
+ ZoomInterpolatedAttribute<Attr> is a 'compound' attribute, representing two values of the
+ the base attribute Attr. These two values are provided to the shader to allow interpolation
+ between zoom levels, without the need to repopulate vertex buffers each frame as the map is
+ being zoomed.
+*/
+template <class A>
+using ZoomInterpolatedAttributeType = gl::Attribute<typename A::ValueType, A::Dimensions * 2>;
+
+inline std::array<float, 1> attributeValue(float v) {
+ return {{ v }};
+}
+
+/*
+ Encode a four-component color value into a pair of floats. Since csscolorparser
+ uses 8-bit precision for each color component, for each float we use the upper 8
+ bits for one component (e.g. (color.r * 255) * 256), and the lower 8 for another.
+
+ Also note:
+ - Colors come in as floats 0..1, so we scale by 255.
+ - Casting the scaled values to ints is important: without doing this, e.g., the
+ fractional part of the `r` component would corrupt the lower-8 bits of the encoded
+ value, which must be reserved for the `g` component.
+*/
+inline std::array<float, 2> attributeValue(const Color& color) {
+ return {{
+ static_cast<float>(static_cast<uint16_t>(color.r * 255) * 256 + static_cast<uint16_t>(color.g * 255)),
+ static_cast<float>(static_cast<uint16_t>(color.b * 255) * 256 + static_cast<uint16_t>(color.a * 255))
+ }};
+}
+
+template <size_t N>
+std::array<float, N*2> zoomInterpolatedAttributeValue(const std::array<float, N>& min, const std::array<float, N>& max) {
+ std::array<float, N*2> result;
+ for (size_t i = 0; i < N; i++) {
+ result[i] = min[i];
+ result[i+N] = max[i];
+ }
+ return result;
+}
+
template <class T, class A>
class PaintPropertyBinder {
public:
- using BaseAttribute = A;
- using Attribute = attributes::ZoomInterpolatedAttribute<BaseAttribute>;
+ using Attribute = ZoomInterpolatedAttributeType<A>;
using AttributeBinding = typename Attribute::Binding;
virtual ~PaintPropertyBinder() = default;
@@ -21,16 +61,14 @@ public:
virtual void upload(gl::Context& context) = 0;
virtual AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const = 0;
virtual float interpolationFactor(float currentZoom) const = 0;
+
+ static std::unique_ptr<PaintPropertyBinder> create(const PossiblyEvaluatedPropertyValue<T>& value, float zoom, T defaultValue);
};
template <class T, class A>
class ConstantPaintPropertyBinder : public PaintPropertyBinder<T, A> {
public:
- using BaseAttribute = A;
- using BaseAttributeValue = typename BaseAttribute::Value;
- using BaseAttributeBinding = typename BaseAttribute::Binding;
-
- using Attribute = attributes::ZoomInterpolatedAttribute<BaseAttribute>;
+ using Attribute = ZoomInterpolatedAttributeType<A>;
using AttributeBinding = typename Attribute::Binding;
ConstantPaintPropertyBinder(T constant_)
@@ -41,9 +79,9 @@ public:
void upload(gl::Context&) override {}
AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
- auto val = currentValue.constantOr(constant);
+ auto value = attributeValue(currentValue.constantOr(constant));
return typename Attribute::ConstantBinding {
- Attribute::value(val, val)
+ zoomInterpolatedAttributeValue(value, value)
};
}
@@ -60,10 +98,9 @@ class SourceFunctionPaintPropertyBinder : public PaintPropertyBinder<T, A> {
public:
using BaseAttribute = A;
using BaseAttributeValue = typename BaseAttribute::Value;
- using BaseAttributeBinding = typename BaseAttribute::Binding;
- using BaseVertex = typename gl::Attributes<BaseAttribute>::Vertex;
+ using BaseVertex = gl::detail::Vertex<BaseAttribute>;
- using Attribute = attributes::ZoomInterpolatedAttribute<BaseAttribute>;
+ using Attribute = ZoomInterpolatedAttributeType<A>;
using AttributeBinding = typename Attribute::Binding;
SourceFunctionPaintPropertyBinder(SourceFunction<T> function_, T defaultValue_)
@@ -72,8 +109,7 @@ public:
}
void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) override {
- auto val = function.evaluate(feature, defaultValue);
- BaseAttributeValue value = BaseAttribute::value(val);
+ auto value = attributeValue(function.evaluate(feature, defaultValue));
for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) {
vertexVector.emplace_back(BaseVertex { value });
}
@@ -85,9 +121,9 @@ public:
AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
if (currentValue.isConstant()) {
- auto val = *currentValue.constant();
+ BaseAttributeValue value = attributeValue(*currentValue.constant());
return typename Attribute::ConstantBinding {
- Attribute::value(val, val)
+ zoomInterpolatedAttributeValue(value, value)
};
} else {
return Attribute::variableBinding(*vertexBuffer, 0, BaseAttribute::Dimensions);
@@ -108,10 +144,13 @@ private:
template <class T, class A>
class CompositeFunctionPaintPropertyBinder : public PaintPropertyBinder<T, A> {
public:
- using Attribute = attributes::ZoomInterpolatedAttribute<A>;
+ using BaseAttribute = A;
+ using BaseAttributeValue = typename BaseAttribute::Value;
+
+ using Attribute = ZoomInterpolatedAttributeType<A>;
using AttributeValue = typename Attribute::Value;
using AttributeBinding = typename Attribute::Binding;
- using Vertex = typename gl::Attributes<Attribute>::Vertex;
+ using Vertex = gl::detail::Vertex<Attribute>;
CompositeFunctionPaintPropertyBinder(CompositeFunction<T> function_, float zoom, T defaultValue_)
: function(std::move(function_)),
@@ -121,9 +160,11 @@ public:
void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) override {
Range<T> range = function.evaluate(std::get<1>(coveringRanges), feature, defaultValue);
- AttributeValue minMax = Attribute::value(range.min, range.max);
+ AttributeValue value = zoomInterpolatedAttributeValue(
+ attributeValue(range.min),
+ attributeValue(range.max));
for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) {
- vertexVector.emplace_back(Vertex { minMax });
+ vertexVector.emplace_back(Vertex { value });
}
}
@@ -133,9 +174,9 @@ public:
AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
if (currentValue.isConstant()) {
- auto val = *currentValue.constant();
+ BaseAttributeValue value = attributeValue(*currentValue.constant());
return typename Attribute::ConstantBinding {
- Attribute::value(val, val)
+ zoomInterpolatedAttributeValue(value, value)
};
} else {
return Attribute::variableBinding(*vertexBuffer, 0);
@@ -155,36 +196,52 @@ private:
optional<gl::VertexBuffer<Vertex>> vertexBuffer;
};
-template <class PaintProperty>
-auto createPaintPropertyBinder(const typename PaintProperty::EvaluatedType& value, float zoom) {
- using Type = typename PaintProperty::Type;
- using Attribute = typename PaintProperty::Attribute;
+template <class T, class A>
+std::unique_ptr<PaintPropertyBinder<T, A>>
+PaintPropertyBinder<T, A>::create(const PossiblyEvaluatedPropertyValue<T>& value, float zoom, T defaultValue) {
return value.match(
- [&] (const Type& constant) -> std::unique_ptr<PaintPropertyBinder<Type, Attribute>> {
- return std::make_unique<ConstantPaintPropertyBinder<Type, Attribute>>(constant);
+ [&] (const T& constant) -> std::unique_ptr<PaintPropertyBinder<T, A>> {
+ return std::make_unique<ConstantPaintPropertyBinder<T, A>>(constant);
},
- [&] (const SourceFunction<Type>& function) {
- return std::make_unique<SourceFunctionPaintPropertyBinder<Type, Attribute>>(function, PaintProperty::defaultValue());
+ [&] (const SourceFunction<T>& function) {
+ return std::make_unique<SourceFunctionPaintPropertyBinder<T, A>>(function, defaultValue);
},
- [&] (const CompositeFunction<Type>& function) {
- return std::make_unique<CompositeFunctionPaintPropertyBinder<Type, Attribute>>(function, zoom, PaintProperty::defaultValue());
+ [&] (const CompositeFunction<T>& function) {
+ return std::make_unique<CompositeFunctionPaintPropertyBinder<T, A>>(function, zoom, defaultValue);
}
);
}
+template <class Attr>
+struct ZoomInterpolatedAttribute {
+ static auto name() { return Attr::name(); }
+ using Type = ZoomInterpolatedAttributeType<typename Attr::Type>;
+};
+
+template <class Attr>
+struct InterpolationUniform : gl::UniformScalar<InterpolationUniform<Attr>, float> {
+ static auto name() {
+ static const std::string name = Attr::name() + std::string("_t");
+ return name.c_str();
+ }
+};
+
template <class Ps>
class PaintPropertyBinders;
template <class... Ps>
class PaintPropertyBinders<TypeList<Ps...>> {
public:
+ template <class P>
+ using Binder = PaintPropertyBinder<typename P::Type, typename P::Attribute::Type>;
+
using Binders = IndexedTuple<
TypeList<Ps...>,
- TypeList<std::unique_ptr<PaintPropertyBinder<typename Ps::Type, typename Ps::Attribute>>...>>;
+ TypeList<std::unique_ptr<Binder<Ps>>...>>;
template <class EvaluatedProperties>
PaintPropertyBinders(const EvaluatedProperties& properties, float z)
- : binders(createPaintPropertyBinder<Ps>(properties.template get<Ps>(), z)...) {
+ : binders(Binder<Ps>::create(properties.template get<Ps>(), z, Ps::defaultValue())...) {
(void)z; // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56958
}
@@ -203,7 +260,10 @@ public:
});
}
- using Attributes = gl::Attributes<typename PaintPropertyBinder<typename Ps::Type, typename Ps::Attribute>::Attribute...>;
+ template <class P>
+ using Attribute = ZoomInterpolatedAttribute<typename P::Attribute>;
+
+ using Attributes = gl::Attributes<Attribute<Ps>...>;
using AttributeBindings = typename Attributes::Bindings;
template <class EvaluatedProperties>
@@ -213,13 +273,13 @@ public:
};
}
- using Uniforms = gl::Uniforms<attributes::InterpolationUniform<typename Ps::Attribute>...>;
+ using Uniforms = gl::Uniforms<InterpolationUniform<typename Ps::Attribute>...>;
using UniformValues = typename Uniforms::Values;
UniformValues uniformValues(float currentZoom) const {
(void)currentZoom; // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56958
return UniformValues {
- typename attributes::InterpolationUniform<typename Ps::Attribute>::Value {
+ typename InterpolationUniform<typename Ps::Attribute>::Value {
binders.template get<Ps>()->interpolationFactor(currentZoom)
}...
};