Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[cp][core] sort symbols using symbol-sort-key before placement #16208

Merged
merged 1 commit into from
Feb 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/mbgl/layout/symbol_instance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,11 @@ class SymbolInstance {
uint32_t crossTileID = 0;
};

class SortKeyRange {
public:
float sortKey;
size_t symbolInstanceStart;
size_t symbolInstanceEnd;
};

} // namespace mbgl
23 changes: 20 additions & 3 deletions src/mbgl/layout/symbol_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,

const bool hasSymbolSortKey = !leader.layout.get<SymbolSortKey>().isUndefined();
const auto symbolZOrder = layout->get<SymbolZOrder>();
const bool sortFeaturesByKey = symbolZOrder != SymbolZOrderType::ViewportY && hasSymbolSortKey;
sortFeaturesByKey = symbolZOrder != SymbolZOrderType::ViewportY && hasSymbolSortKey;
const bool zOrderByViewportY = symbolZOrder == SymbolZOrderType::ViewportY || (symbolZOrder == SymbolZOrderType::Auto && !sortFeaturesByKey);
sortFeaturesByY = zOrderByViewportY && (layout->get<TextAllowOverlap>() || layout->get<IconAllowOverlap>() ||
layout->get<TextIgnorePlacement>() || layout->get<IconIgnorePlacement>());
Expand Down Expand Up @@ -560,6 +560,14 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
layoutFeatureIndex, feature.index,
feature.formattedText ? feature.formattedText->rawText() : std::u16string(),
overscaling, iconRotation, textRotation, variableTextOffset, allowVerticalPlacement, iconType);

if (sortFeaturesByKey) {
if (sortKeyRanges.size() && sortKeyRanges.back().sortKey == feature.sortKey) {
sortKeyRanges.back().symbolInstanceEnd = symbolInstances.size();
} else {
sortKeyRanges.push_back({feature.sortKey, symbolInstances.size() - 1, symbolInstances.size()});
}
}
}
};

Expand Down Expand Up @@ -679,8 +687,17 @@ std::vector<float> CalculateTileDistances(const GeometryCoordinates& line, const
}

void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIndex>&, std::unordered_map<std::string, LayerRenderData>& renderData, const bool firstLoad, const bool showCollisionBoxes) {
auto bucket = std::make_shared<SymbolBucket>(layout, layerPaintProperties, textSize, iconSize, zoom, iconsNeedLinear,
sortFeaturesByY, bucketLeaderID, std::move(symbolInstances), tilePixelRatio,
auto bucket = std::make_shared<SymbolBucket>(layout,
layerPaintProperties,
textSize,
iconSize,
zoom,
iconsNeedLinear,
sortFeaturesByY,
bucketLeaderID,
std::move(symbolInstances),
std::move(sortKeyRanges),
tilePixelRatio,
allowVerticalPlacement,
std::move(placementModes));

Expand Down
2 changes: 2 additions & 0 deletions src/mbgl/layout/symbol_layout.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class SymbolLayout final : public Layout {

const std::string bucketLeaderID;
std::vector<SymbolInstance> symbolInstances;
std::vector<SortKeyRange> sortKeyRanges;

static constexpr float INVALID_OFFSET_VALUE = std::numeric_limits<float>::max();
/**
Expand Down Expand Up @@ -105,6 +106,7 @@ class SymbolLayout final : public Layout {

bool iconsNeedLinear = false;
bool sortFeaturesByY = false;
bool sortFeaturesByKey = false;
bool allowVerticalPlacement = false;
std::vector<style::TextWritingModeType> placementModes;

Expand Down
2 changes: 2 additions & 0 deletions src/mbgl/renderer/buckets/symbol_bucket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ SymbolBucket::SymbolBucket(Immutable<style::SymbolLayoutProperties::PossiblyEval
bool sortFeaturesByY_,
const std::string bucketName_,
const std::vector<SymbolInstance>&& symbolInstances_,
const std::vector<SortKeyRange>&& sortKeyRanges_,
float tilePixelRatio_,
bool allowVerticalPlacement_,
std::vector<style::TextWritingModeType> placementModes_)
Expand All @@ -36,6 +37,7 @@ SymbolBucket::SymbolBucket(Immutable<style::SymbolLayoutProperties::PossiblyEval
justReloaded(false),
hasVariablePlacement(false),
symbolInstances(symbolInstances_),
sortKeyRanges(sortKeyRanges_),
textSizeBinder(SymbolSizeBinder::create(zoom, textSize, TextSize::defaultValue())),
iconSizeBinder(SymbolSizeBinder::create(zoom, iconSize, IconSize::defaultValue())),
tilePixelRatio(tilePixelRatio_),
Expand Down
2 changes: 2 additions & 0 deletions src/mbgl/renderer/buckets/symbol_bucket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class SymbolBucket final : public Bucket {
bool sortFeaturesByY,
const std::string bucketLeaderID,
const std::vector<SymbolInstance>&&,
const std::vector<SortKeyRange>&&,
const float tilePixelRatio,
bool allowVerticalPlacement,
std::vector<style::TextWritingModeType> placementModes);
Expand Down Expand Up @@ -100,6 +101,7 @@ class SymbolBucket final : public Bucket {
bool hasVariablePlacement : 1;

std::vector<SymbolInstance> symbolInstances;
std::vector<SortKeyRange> sortKeyRanges;

struct PaintProperties {
SymbolIconProgram::Binders iconBinders;
Expand Down
25 changes: 24 additions & 1 deletion src/mbgl/renderer/layers/render_symbol_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ void RenderSymbolLayer::render(PaintParameters& parameters) {
assert(bucket.paintProperties.find(getID()) != bucket.paintProperties.end());
const auto& bucketPaintProperties = bucket.paintProperties.at(getID());

bucket.justReloaded = false;

auto addRenderables = [&renderableSegments, &tile, renderData, &bucketPaintProperties, it = renderableSegments.begin()] (auto& segments, const SymbolType type) mutable {
for (auto& segment : segments) {
it = renderableSegments.emplace_hint(it, SegmentWrapper{std::ref(segment)}, tile, *renderData, bucketPaintProperties, segment.sortKey, type);
Expand Down Expand Up @@ -518,7 +520,28 @@ void RenderSymbolLayer::prepare(const LayerPrepareParameters& params) {
const Tile* tile = params.source->getRenderedTile(renderTile.id);
assert(tile);
assert(tile->kind == Tile::Kind::Geometry);
placementData.push_back({*bucket, renderTile, static_cast<const GeometryTile*>(tile)->getFeatureIndex()});

bool firstInBucket = true;
auto featureIndex = static_cast<const GeometryTile*>(tile)->getFeatureIndex();

if (bucket->sortKeyRanges.empty()) {
placementData.push_back(
{*bucket, renderTile, featureIndex, firstInBucket, 0.0f, 0, bucket->symbolInstances.size()});
} else {
for (const SortKeyRange& sortKeyRange : bucket->sortKeyRanges) {
LayerPlacementData layerData{*bucket,
renderTile,
featureIndex,
firstInBucket,
sortKeyRange.sortKey,
sortKeyRange.symbolInstanceStart,
sortKeyRange.symbolInstanceEnd};
auto sortPosition = std::upper_bound(placementData.cbegin(), placementData.cend(), layerData);
placementData.insert(sortPosition, std::move(layerData));

firstInBucket = false;
}
}
}
}
}
Expand Down
16 changes: 11 additions & 5 deletions src/mbgl/renderer/render_layer.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#pragma once
#include <list>
#include <mbgl/layout/layout.hpp>
#include <mbgl/renderer/render_pass.hpp>
#include <mbgl/renderer/render_source.hpp>
#include <mbgl/style/layer_properties.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/util/mat4.hpp>

#include <memory>
#include <string>

Expand All @@ -20,6 +20,7 @@ class RenderTile;
class TransformState;
class PatternAtlas;
class LineAtlas;
class SymbolBucket;

class LayerRenderData {
public:
Expand All @@ -29,9 +30,16 @@ class LayerRenderData {

class LayerPlacementData {
public:
friend bool operator<(const LayerPlacementData& lhs, const LayerPlacementData& rhs) {
return lhs.sortKey < rhs.sortKey;
}
std::reference_wrapper<Bucket> bucket;
std::reference_wrapper<const RenderTile> tile;
std::shared_ptr<FeatureIndex> featureIndex;
bool firstInBucket;
float sortKey;
size_t symbolInstanceStart;
size_t symbolInstanceEnd;
};

class LayerPrepareParameters {
Expand Down Expand Up @@ -95,9 +103,7 @@ class RenderLayer {

virtual void prepare(const LayerPrepareParameters&);

const std::vector<LayerPlacementData>& getPlacementData() const {
return placementData;
}
const std::list<LayerPlacementData>& getPlacementData() const { return placementData; }

// Latest evaluated properties.
Immutable<style::LayerProperties> evaluatedProperties;
Expand Down Expand Up @@ -126,7 +132,7 @@ class RenderLayer {
// evaluated StyleProperties object and is updated accordingly.
RenderPass passes = RenderPass::None;

std::vector<LayerPlacementData> placementData;
std::list<LayerPlacementData> placementData;

private:
// Some layers may not render correctly on some hardware when the vertex attribute limit of
Expand Down
29 changes: 18 additions & 11 deletions src/mbgl/text/placement.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <list>
#include <mbgl/text/placement.hpp>

#include <mbgl/layout/symbol_layout.hpp>
Expand Down Expand Up @@ -110,12 +111,14 @@ void Placement::placeLayer(const RenderLayer& layer, const mat4& projMatrix, boo
std::set<uint32_t> seenCrossTileIDs;
for (const auto& item : layer.getPlacementData()) {
Bucket& bucket = item.bucket;
BucketPlacementParameters params{
item.tile,
projMatrix,
layer.baseImpl->source,
item.featureIndex,
showCollisionBoxes};
BucketPlacementParameters params{item.tile,
projMatrix,
layer.baseImpl->source,
item.featureIndex,
item.sortKey,
item.symbolInstanceStart,
item.symbolInstanceEnd,
showCollisionBoxes};
bucket.place(*this, params, seenCrossTileIDs);
}
}
Expand Down Expand Up @@ -518,13 +521,15 @@ void Placement::placeBucket(
placeSymbol(*it);
}
} else {
for (const SymbolInstance& symbol : bucket.symbolInstances) {
placeSymbol(symbol);
auto beginIt = bucket.symbolInstances.begin() + params.symbolInstanceStart;
auto endIt = bucket.symbolInstances.begin() + params.symbolInstanceEnd;
assert(params.symbolInstanceStart < params.symbolInstanceEnd);
assert(params.symbolInstanceEnd <= bucket.symbolInstances.size());
for (auto it = beginIt; it != endIt; ++it) {
placeSymbol(*it);
}
}

bucket.justReloaded = false;

// As long as this placement lives, we have to hold onto this bucket's
// matching FeatureIndex/data for querying purposes
retainedQueryData.emplace(std::piecewise_construct,
Expand Down Expand Up @@ -590,7 +595,9 @@ void Placement::commit(TimePoint now, const double zoom) {
void Placement::updateLayerBuckets(const RenderLayer& layer, const TransformState& state, bool updateOpacities) const {
std::set<uint32_t> seenCrossTileIDs;
for (const auto& item : layer.getPlacementData()) {
item.bucket.get().updateVertices(*this, updateOpacities, state, item.tile, seenCrossTileIDs);
if (item.firstInBucket) {
item.bucket.get().updateVertices(*this, updateOpacities, state, item.tile, seenCrossTileIDs);
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/mbgl/text/placement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ class BucketPlacementParameters {
const mat4& projMatrix;
std::string sourceId;
std::shared_ptr<FeatureIndex> featureIndex;
float sortKey;
size_t symbolInstanceStart;
size_t symbolInstanceEnd;
bool showCollisionBoxes;
};

Expand Down
15 changes: 14 additions & 1 deletion test/gl/bucket.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,22 @@ TEST(Buckets, SymbolBucket) {
bool sortFeaturesByY = false;
std::string bucketLeaderID = "test";
std::vector<SymbolInstance> symbolInstances;
std::vector<SortKeyRange> symbolRanges;

gl::Context context{ backend };
SymbolBucket bucket { std::move(layout), {}, 16.0f, 1.0f, 0, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(symbolInstances), 1.0f, false, {}};
SymbolBucket bucket{std::move(layout),
{},
16.0f,
1.0f,
0,
iconsNeedLinear,
sortFeaturesByY,
bucketLeaderID,
std::move(symbolInstances),
std::move(symbolRanges),
1.0f,
false,
{}};
ASSERT_FALSE(bucket.hasIconData());
ASSERT_FALSE(bucket.hasSdfIconData());
ASSERT_FALSE(bucket.hasTextData());
Expand Down
Loading