diff options
author | Asheem Mamoowala <asheem.mamoowala@mapbox.com> | 2018-09-07 10:31:00 -0700 |
---|---|---|
committer | Asheem Mamoowala <asheem.mamoowala@mapbox.com> | 2018-10-09 16:17:03 -0700 |
commit | 0ab4b69b75f602991cd49ebdd1979543523d1021 (patch) | |
tree | 0846829f79290fdfeb8a40bb10d1980eb3e6658d | |
parent | 7452747583d3121c90d4affc154477fa7a57d08f (diff) |
Updateable paint property binders
-rw-r--r-- | src/mbgl/gl/vertex_buffer.hpp | 6 | ||||
-rw-r--r-- | src/mbgl/layout/pattern_layout.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/layout/symbol_layout.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/renderer/bucket.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/circle_bucket.cpp | 3 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/circle_bucket.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/fill_bucket.cpp | 5 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/fill_bucket.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp | 5 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/heatmap_bucket.cpp | 3 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/heatmap_bucket.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/line_bucket.cpp | 5 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/line_bucket.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/paint_property_binder.hpp | 89 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile_worker.cpp | 2 |
16 files changed, 112 insertions, 18 deletions
diff --git a/src/mbgl/gl/vertex_buffer.hpp b/src/mbgl/gl/vertex_buffer.hpp index 9f8b156b2..807776fc8 100644 --- a/src/mbgl/gl/vertex_buffer.hpp +++ b/src/mbgl/gl/vertex_buffer.hpp @@ -22,6 +22,12 @@ public: util::ignore({(v.emplace_back(std::forward<Args>(args)), 0)...}); } + template<class... Args> + void emplace(size_t startAt, Args&&... args) { + static_assert(sizeof...(args) == groupSize, "wrong buffer element count"); + auto emplaceIter = v.begin() + (startAt * groupSize); + util::ignore({(v.emplace(emplaceIter++, std::forward<Args>(args)), 0)...}); + } std::size_t vertexSize() const { return v.size(); } std::size_t byteSize() const { return v.size() * sizeof(Vertex); } diff --git a/src/mbgl/layout/pattern_layout.hpp b/src/mbgl/layout/pattern_layout.hpp index 50c4bc25b..0ae16ed79 100644 --- a/src/mbgl/layout/pattern_layout.hpp +++ b/src/mbgl/layout/pattern_layout.hpp @@ -106,7 +106,7 @@ public: PatternLayerMap patterns = patternFeature.patterns; GeometryCollection geometries = feature->getGeometries(); - bucket->addFeature(*feature, geometries, patternPositions, patterns); + bucket->addFeature(*feature, geometries, i, patternPositions, patterns); featureIndex->insert(geometries, i, sourceLayerID, groupID); } if (bucket->hasData()) { diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index c67c30bca..54416d17a 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -468,8 +468,8 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn } for (auto& pair : bucket->paintPropertyBinders) { - pair.second.first.populateVertexVectors(feature, bucket->icon.vertices.vertexSize(), {}, {}); - pair.second.second.populateVertexVectors(feature, bucket->text.vertices.vertexSize(), {}, {}); + pair.second.first.populateVertexVectors(feature, feature.index, bucket->icon.vertices.vertexSize(), {}, {}); + pair.second.second.populateVertexVectors(feature, feature.index, bucket->text.vertices.vertexSize(), {}, {}); } } diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp index 7ccab8672..dd9460274 100644 --- a/src/mbgl/renderer/bucket.hpp +++ b/src/mbgl/renderer/bucket.hpp @@ -45,6 +45,7 @@ public: // pass-by-const-ref the geometries as a second parameter. virtual void addFeature(const GeometryTileFeature&, const GeometryCollection&, + size_t, const ImagePositions&, const PatternLayerMap&) {}; diff --git a/src/mbgl/renderer/buckets/circle_bucket.cpp b/src/mbgl/renderer/buckets/circle_bucket.cpp index 820cf9f52..a0e81c00b 100644 --- a/src/mbgl/renderer/buckets/circle_bucket.cpp +++ b/src/mbgl/renderer/buckets/circle_bucket.cpp @@ -40,6 +40,7 @@ bool CircleBucket::hasData() const { void CircleBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, + size_t featureIndex, const ImagePositions&, const PatternLayerMap&) { constexpr const uint16_t vertexLength = 4; @@ -89,7 +90,7 @@ void CircleBucket::addFeature(const GeometryTileFeature& feature, } for (auto& pair : paintPropertyBinders) { - pair.second.populateVertexVectors(feature, vertices.vertexSize(), {}, {}); + pair.second.populateVertexVectors(feature, featureIndex, vertices.vertexSize(), {}, {}); } } diff --git a/src/mbgl/renderer/buckets/circle_bucket.hpp b/src/mbgl/renderer/buckets/circle_bucket.hpp index db61a0c11..0247103ca 100644 --- a/src/mbgl/renderer/buckets/circle_bucket.hpp +++ b/src/mbgl/renderer/buckets/circle_bucket.hpp @@ -19,6 +19,7 @@ public: void addFeature(const GeometryTileFeature&, const GeometryCollection&, + size_t, const ImagePositions&, const PatternLayerMap&) override; diff --git a/src/mbgl/renderer/buckets/fill_bucket.cpp b/src/mbgl/renderer/buckets/fill_bucket.cpp index 3b1b7ec00..71831c141 100644 --- a/src/mbgl/renderer/buckets/fill_bucket.cpp +++ b/src/mbgl/renderer/buckets/fill_bucket.cpp @@ -45,6 +45,7 @@ FillBucket::FillBucket(const FillBucket::PossiblyEvaluatedLayoutProperties, void FillBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, + size_t featureIndex, const ImagePositions& patternPositions, const PatternLayerMap& patternDependencies) { for (auto& polygon : classifyRings(geometry)) { @@ -113,9 +114,9 @@ void FillBucket::addFeature(const GeometryTileFeature& feature, for (auto& pair : paintPropertyBinders) { const auto it = patternDependencies.find(pair.first); if (it != patternDependencies.end()){ - pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions, it->second); + pair.second.populateVertexVectors(feature, featureIndex, vertices.vertexSize(), patternPositions, it->second); } else { - pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions, {}); + pair.second.populateVertexVectors(feature, featureIndex, vertices.vertexSize(), patternPositions, {}); } } } diff --git a/src/mbgl/renderer/buckets/fill_bucket.hpp b/src/mbgl/renderer/buckets/fill_bucket.hpp index 47e273d4d..790b8d138 100644 --- a/src/mbgl/renderer/buckets/fill_bucket.hpp +++ b/src/mbgl/renderer/buckets/fill_bucket.hpp @@ -30,6 +30,7 @@ public: void addFeature(const GeometryTileFeature&, const GeometryCollection&, + size_t, const mbgl::ImagePositions&, const PatternLayerMap&) override; diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp index fb491e0db..224809d59 100644 --- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp +++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp @@ -52,6 +52,7 @@ FillExtrusionBucket::FillExtrusionBucket(const FillExtrusionBucket::PossiblyEval void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, + size_t featureIndex, const ImagePositions& patternPositions, const PatternLayerMap& patternDependencies) { for (auto& polygon : classifyRings(geometry)) { @@ -158,9 +159,9 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, for (auto& pair : paintPropertyBinders) { const auto it = patternDependencies.find(pair.first); if (it != patternDependencies.end()){ - pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions, it->second); + pair.second.populateVertexVectors(feature, featureIndex, vertices.vertexSize(), patternPositions, it->second); } else { - pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions, {}); + pair.second.populateVertexVectors(feature, featureIndex, vertices.vertexSize(), patternPositions, {}); } } } diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp index 362a9f4c9..d363d9fb5 100644 --- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp +++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp @@ -28,6 +28,7 @@ public: void addFeature(const GeometryTileFeature&, const GeometryCollection&, + size_t, const mbgl::ImagePositions&, const PatternLayerMap&) override; diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.cpp b/src/mbgl/renderer/buckets/heatmap_bucket.cpp index 46d5f3159..d08dcf9e0 100644 --- a/src/mbgl/renderer/buckets/heatmap_bucket.cpp +++ b/src/mbgl/renderer/buckets/heatmap_bucket.cpp @@ -40,6 +40,7 @@ bool HeatmapBucket::hasData() const { void HeatmapBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, + size_t featureIndex, const ImagePositions&, const PatternLayerMap&) { constexpr const uint16_t vertexLength = 4; @@ -89,7 +90,7 @@ void HeatmapBucket::addFeature(const GeometryTileFeature& feature, } for (auto& pair : paintPropertyBinders) { - pair.second.populateVertexVectors(feature, vertices.vertexSize(), {}, {}); + pair.second.populateVertexVectors(feature, featureIndex, vertices.vertexSize(), {}, {}); } } diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.hpp b/src/mbgl/renderer/buckets/heatmap_bucket.hpp index b2d866d2a..c84540d45 100644 --- a/src/mbgl/renderer/buckets/heatmap_bucket.hpp +++ b/src/mbgl/renderer/buckets/heatmap_bucket.hpp @@ -19,6 +19,7 @@ public: void addFeature(const GeometryTileFeature&, const GeometryCollection&, + size_t, const ImagePositions&, const PatternLayerMap&) override; bool hasData() const override; diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp index 2efb60c9a..dfd5d9c17 100644 --- a/src/mbgl/renderer/buckets/line_bucket.cpp +++ b/src/mbgl/renderer/buckets/line_bucket.cpp @@ -32,6 +32,7 @@ LineBucket::LineBucket(const style::LineLayoutProperties::PossiblyEvaluated layo void LineBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometryCollection, + size_t featureIndex, const ImagePositions& patternPositions, const PatternLayerMap& patternDependencies) { for (auto& line : geometryCollection) { @@ -41,9 +42,9 @@ void LineBucket::addFeature(const GeometryTileFeature& feature, for (auto& pair : paintPropertyBinders) { const auto it = patternDependencies.find(pair.first); if (it != patternDependencies.end()){ - pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions, it->second); + pair.second.populateVertexVectors(feature, featureIndex, vertices.vertexSize(), patternPositions, it->second); } else { - pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions, {}); + pair.second.populateVertexVectors(feature, featureIndex, vertices.vertexSize(), patternPositions, {}); } } } diff --git a/src/mbgl/renderer/buckets/line_bucket.hpp b/src/mbgl/renderer/buckets/line_bucket.hpp index 6bd37076d..d66bcd299 100644 --- a/src/mbgl/renderer/buckets/line_bucket.hpp +++ b/src/mbgl/renderer/buckets/line_bucket.hpp @@ -30,6 +30,7 @@ public: void addFeature(const GeometryTileFeature&, const GeometryCollection&, + size_t, const mbgl::ImagePositions& patternPositions, const PatternLayerMap&) override; diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp index 46fc5302c..89ab065a7 100644 --- a/src/mbgl/renderer/paint_property_binder.hpp +++ b/src/mbgl/renderer/paint_property_binder.hpp @@ -85,6 +85,7 @@ public: virtual ~PaintPropertyBinder() = default; virtual void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&) = 0; + virtual void updateVertexVector(size_t start, size_t end, const GeometryTileFeature& feature, const PropertyMap& featureState) = 0; virtual void upload(gl::Context& context) = 0; virtual void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters&) = 0; virtual std::tuple<ExpandToType<As, optional<gl::AttributeBinding>>...> attributeBinding(const PossiblyEvaluatedType& currentValue) const = 0; @@ -104,6 +105,8 @@ public: } void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional<PatternDependency>&) override {} + void updateVertexVector(size_t, size_t, const GeometryTileFeature&, const PropertyMap&) override {} + void upload(gl::Context&) override {} void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters&) override {}; @@ -131,6 +134,8 @@ public: } void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional<PatternDependency>&) override {} + void updateVertexVector(size_t, size_t, const GeometryTileFeature&, const PropertyMap&) override {} + void upload(gl::Context&) override {} void setPatternParameters(const optional<ImagePosition>& posA, const optional<ImagePosition>& posB, CrossfadeParameters&) override { @@ -169,9 +174,11 @@ public: SourceFunctionPaintPropertyBinder(style::PropertyExpression<T> expression_, T defaultValue_) : expression(std::move(expression_)), - defaultValue(std::move(defaultValue_)) { + defaultValue(std::move(defaultValue_)), + isUpdateable(!expression.isFeatureStateConstant()) { } void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters&) override {}; + void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&) override { auto evaluated = expression.evaluate(feature, {}, defaultValue); this->statistics.add(evaluated); @@ -181,8 +188,21 @@ public: } } + void updateVertexVector(size_t start, size_t end, const GeometryTileFeature& feature, const PropertyMap& featureState) override { + if (!isUpdateable) { return; } + assert(start < end && end < vertexVector.vertexSize()); + auto evaluated = expression.evaluate(feature, featureState, defaultValue); + this->statistics.add(evaluated); + auto value = attributeValue(evaluated); + + for (std::size_t i = start; i < end; ++i) { + vertexVector.emplace(i, BaseVertex { value }); + } + }; + void upload(gl::Context& context) override { - vertexBuffer = context.createVertexBuffer(std::move(vertexVector)); + vertexBuffer = context.createVertexBuffer(std::move(vertexVector), + isUpdateable ? gl::BufferUsage::StaticDraw : gl::BufferUsage::DynamicDraw); } std::tuple<optional<gl::AttributeBinding>> attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override { @@ -211,6 +231,7 @@ private: T defaultValue; gl::VertexVector<BaseVertex> vertexVector; optional<gl::VertexBuffer<BaseVertex>> vertexBuffer; + bool isUpdateable; }; template <class T, class A> @@ -224,9 +245,11 @@ public: CompositeFunctionPaintPropertyBinder(style::PropertyExpression<T> expression_, float zoom, T defaultValue_) : expression(std::move(expression_)), defaultValue(std::move(defaultValue_)), - zoomRange({zoom, zoom + 1}) { + zoomRange({zoom, zoom + 1}), + isUpdateable(!expression.isFeatureStateConstant()) { } void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters&) override {}; + void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&) override { Range<T> range = expression.evaluate(zoomRange, feature, {}, defaultValue); this->statistics.add(range.min); @@ -239,8 +262,23 @@ public: } } + void updateVertexVector(size_t start, size_t end, const GeometryTileFeature& feature, const PropertyMap& featureState) override { + if (!isUpdateable) { return; } + assert(start < end && end < vertexVector.vertexSize()); + Range<T> range = expression.evaluate(zoomRange, feature, featureState, defaultValue); + this->statistics.add(range.min); + this->statistics.add(range.max); + AttributeValue value = zoomInterpolatedAttributeValue( + attributeValue(range.min), + attributeValue(range.max)); + for (std::size_t i = start; i < end; ++i) { + vertexVector.emplace(i, Vertex { value }); + } + }; + void upload(gl::Context& context) override { - vertexBuffer = context.createVertexBuffer(std::move(vertexVector)); + vertexBuffer = context.createVertexBuffer(std::move(vertexVector), + isUpdateable ? gl::BufferUsage::StaticDraw : gl::BufferUsage::DynamicDraw); } std::tuple<optional<gl::AttributeBinding>> attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override { @@ -274,6 +312,7 @@ private: Range<float> zoomRange; gl::VertexVector<Vertex> vertexVector; optional<gl::VertexBuffer<Vertex>> vertexBuffer; + bool isUpdateable; }; template <class T, class A1, class A2> @@ -294,7 +333,8 @@ public: CompositeCrossFadedPaintPropertyBinder(style::PropertyExpression<T> expression_, float zoom, T defaultValue_) : expression(std::move(expression_)), defaultValue(std::move(defaultValue_)), - zoomRange({zoom, zoom + 1}) { + zoomRange({zoom, zoom + 1}), + isUpdateable(!expression.isFeatureStateConstant()) { } void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, CrossfadeParameters& crossfade_) override { @@ -332,12 +372,19 @@ public: } } + void upload(gl::Context& context) override { patternToVertexBuffer = context.createVertexBuffer(std::move(patternToVertexVector)); zoomInVertexBuffer = context.createVertexBuffer(std::move(zoomInVertexVector)); zoomOutVertexBuffer = context.createVertexBuffer(std::move(zoomOutVertexVector)); } + void updateVertexVector(size_t, size_t, const GeometryTileFeature&, const PropertyMap&) override { + if (!isUpdateable) return; + //TODO: AHM: How to evaluate expression with feature-state to determine + // patterns and pattern positions synchronously + }; + std::tuple<optional<gl::AttributeBinding>, optional<gl::AttributeBinding>> attributeBinding(const PossiblyEvaluatedPropertyValue<Faded<T>>& currentValue) const override { if (currentValue.isConstant()) { return {}; @@ -370,6 +417,7 @@ private: optional<gl::VertexBuffer<Vertex2>> zoomInVertexBuffer; optional<gl::VertexBuffer<Vertex2>> zoomOutVertexBuffer; CrossfadeParameters crossfade; + bool isUpdateable; }; template <class T, class PossiblyEvaluatedType> @@ -457,15 +505,22 @@ public: PaintPropertyBinders(const EvaluatedProperties& properties, float 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 + binderBufferOffset = 0; } PaintPropertyBinders(PaintPropertyBinders&&) = default; PaintPropertyBinders(const PaintPropertyBinders&) = delete; - void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies) { + void populateVertexVectors(const GeometryTileFeature& feature, size_t index, std::size_t length, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies) { util::ignore({ (binders.template get<Ps>()->populateVertexVector(feature, length, patternPositions, patternDependencies), 0)... }); + auto featureId = feature.getID(); + if (featureId) { + auto posArray = idMap[*featureId]; + posArray.emplace_back(index, binderBufferOffset, length); + } + binderBufferOffset = length; } void setPatternParameters(const optional<ImagePosition>& posA, const optional<ImagePosition>& posB, CrossfadeParameters& crossfade) const { @@ -474,6 +529,23 @@ public: }); } + bool updateVertexVectors(const std::vector<std::pair<FeatureIdentifier, PropertyMap>>& featureStates, + const GeometryTileLayer& layer) { + bool dirty = false; + for (const auto& pair : featureStates) { + const auto& posArray = idMap[pair.first]; + for (const auto& info : posArray) { + std::unique_ptr<GeometryTileFeature> feature = layer.getFeature(std::get<0>(info)); + const size_t startVertex = std::get<1>(info); + const size_t endVertex = std::get<2>(info); + util::ignore({ (binders.template get<Ps>()->updateVertexVector(startVertex, + endVertex, *feature, pair.second), 0)... }); + dirty = true; + } + } + return dirty; + } + void upload(gl::Context& context) { util::ignore({ (binders.template get<Ps>()->upload(context), 0)... @@ -550,8 +622,13 @@ public: return result; } + // Map Feature Id to a list of feature index, vertex start position, and length. + using IdMap = std::unordered_map<FeatureIdentifier, std::vector<std::tuple<size_t, size_t, size_t>>>; + private: Binders binders; + IdMap idMap; + uint32_t binderBufferOffset; }; } // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 9d3a1faf3..74d2028c5 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -388,7 +388,7 @@ void GeometryTileWorker::parse() { continue; GeometryCollection geometries = feature->getGeometries(); - bucket->addFeature(*feature, geometries, {}, PatternLayerMap ()); + bucket->addFeature(*feature, geometries, i, {}, PatternLayerMap ()); featureIndex->insert(geometries, i, sourceLayerID, leader.getID()); } |