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

Cross tile index performance #16127

Merged
merged 11 commits into from
Jan 22, 2020
Merged
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@

### 🏁 Performance improvements

- [core] Cross tile index performance ([#16127](https://github.com/mapbox/mapbox-gl-native/pull/16127))

For overscaled tiles, index only the symbols inside the viewport.

Find matches only among the buckets that have the same leader Id.

- [core] Calculate GeoJSON tile geometries in a background thread ([#15953](https://github.com/mapbox/mapbox-gl-native/pull/15953))

Call `mapbox::geojsonvt::GeoJSONVT::getTile()` in a background thread, so that the rendering thread is not blocked.
Expand Down
2 changes: 1 addition & 1 deletion include/mbgl/renderer/renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Renderer {

void setObserver(RendererObserver*);

void render(const UpdateParameters&);
void render(const std::shared_ptr<UpdateParameters>&);

// Feature queries
std::vector<Feature> queryRenderedFeatures(const ScreenLineString&, const RenderedQueryOptions& options = {}) const;
Expand Down
2 changes: 1 addition & 1 deletion platform/android/src/map_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ void MapRenderer::render(JNIEnv&) {
framebufferSizeChanged = false;
}

renderer->render(*params);
renderer->render(params);

// Deliver the snapshot if requested
if (snapshotCallback) {
Expand Down
2 changes: 1 addition & 1 deletion platform/darwin/src/MGLRendererFrontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class MGLRenderFrontend : public mbgl::RendererFrontend
// Copy the shared pointer here so that the parameters aren't destroyed while `render(...)` is
// still using them.
auto updateParameters_ = updateParameters;
renderer->render(*updateParameters_);
renderer->render(updateParameters_);
}

mbgl::Renderer* getRenderer() {
Expand Down
2 changes: 1 addition & 1 deletion platform/default/src/mbgl/gfx/headless_frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ HeadlessFrontend::HeadlessFrontend(Size size_,
// Copy the shared pointer here so that the parameters aren't destroyed while `render(...)` is
// still using them.
auto updateParameters_ = updateParameters;
renderer->render(*updateParameters_);
renderer->render(updateParameters_);

auto endTime = mbgl::util::MonotonicTimer::now();
frameTime = (endTime - startTime).count();
Expand Down
2 changes: 1 addition & 1 deletion platform/glfw/glfw_renderer_frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void GLFWRendererFrontend::render() {
// Copy the shared pointer here so that the parameters aren't destroyed while `render(...)` is
// still using them.
auto updateParameters_ = updateParameters;
renderer->render(*updateParameters_);
renderer->render(updateParameters_);
}

mbgl::Renderer* GLFWRendererFrontend::getRenderer() {
Expand Down
2 changes: 1 addition & 1 deletion platform/qt/src/qmapboxgl_map_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void QMapboxGLMapRenderer::render()
// The OpenGL implementation automatically enables the OpenGL context for us.
mbgl::gfx::BackendScope scope(m_backend, mbgl::gfx::BackendScope::ScopeType::Implicit);

m_renderer->render(*params);
m_renderer->render(params);

if (m_forceScheduler) {
getScheduler()->processEvents();
Expand Down
2 changes: 2 additions & 0 deletions src/mbgl/layout/symbol_instance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ class SymbolInstance {
std::array<float, 2> variableTextOffset;
bool singleLine;
uint32_t crossTileID = 0;

static constexpr uint32_t invalidCrossTileID() { return std::numeric_limits<uint32_t>::max(); }
};

} // namespace mbgl
3 changes: 2 additions & 1 deletion src/mbgl/map/transform_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ class TransformState {
void setLatLngZoom(const LatLng& latLng, double zoom);

void constrain(double& scale, double& x, double& y) const;
const mat4& getProjectionMatrix() const;

private:
bool rotatedNorth() const;
Expand All @@ -236,7 +237,7 @@ class TransformState {

void updateMatricesIfNeeded() const;
bool needsMatricesUpdate() const { return requestMatricesUpdate; }
const mat4& getProjectionMatrix() const;

const mat4& getCoordMatrix() const;
const mat4& getInvertedMatrix() const;

Expand Down
2 changes: 1 addition & 1 deletion src/mbgl/renderer/bucket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Bucket {
// Returns a pair, the first element of which is a bucket cross-tile id
// on success call; `0` otherwise. The second element is `true` if
// the bucket was originally registered; `false` otherwise.
virtual std::pair<uint32_t, bool> registerAtCrossTileIndex(CrossTileSymbolLayerIndex&, const OverscaledTileID&, uint32_t&) {
virtual std::pair<uint32_t, bool> registerAtCrossTileIndex(CrossTileSymbolLayerIndex&, const RenderTile&) {
return std::make_pair(0u, false);
}
// Places this bucket to the given placement.
Expand Down
9 changes: 6 additions & 3 deletions src/mbgl/renderer/buckets/symbol_bucket.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <mbgl/renderer/bucket_parameters.hpp>
#include <mbgl/renderer/buckets/symbol_bucket.hpp>
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
#include <mbgl/renderer/bucket_parameters.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/text/cross_tile_symbol_index.hpp>
#include <mbgl/text/glyph_atlas.hpp>
Expand Down Expand Up @@ -37,6 +38,7 @@ SymbolBucket::SymbolBucket(Immutable<style::SymbolLayoutProperties::PossiblyEval
iconsInText(iconsInText_),
justReloaded(false),
hasVariablePlacement(false),
hasUninitializedSymbols(false),
symbolInstances(symbolInstances_),
textSizeBinder(SymbolSizeBinder::create(zoom, textSize, TextSize::defaultValue())),
iconSizeBinder(SymbolSizeBinder::create(zoom, iconSize, IconSize::defaultValue())),
Expand Down Expand Up @@ -295,8 +297,9 @@ bool SymbolBucket::hasFormatSectionOverrides() const {
return *hasFormatSectionOverrides_;
}

std::pair<uint32_t, bool> SymbolBucket::registerAtCrossTileIndex(CrossTileSymbolLayerIndex& index, const OverscaledTileID& tileID, uint32_t& maxCrossTileID) {
bool firstTimeAdded = index.addBucket(tileID, *this, maxCrossTileID);
std::pair<uint32_t, bool> SymbolBucket::registerAtCrossTileIndex(CrossTileSymbolLayerIndex& index,
const RenderTile& renderTile) {
bool firstTimeAdded = index.addBucket(renderTile.getOverscaledTileID(), renderTile.matrix, *this);
return std::make_pair(bucketInstanceId, firstTimeAdded);
}

Expand Down
3 changes: 2 additions & 1 deletion src/mbgl/renderer/buckets/symbol_bucket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class SymbolBucket final : public Bucket {

void upload(gfx::UploadPass&) override;
bool hasData() const override;
std::pair<uint32_t, bool> registerAtCrossTileIndex(CrossTileSymbolLayerIndex&, const OverscaledTileID&, uint32_t& maxCrossTileID) override;
std::pair<uint32_t, bool> registerAtCrossTileIndex(CrossTileSymbolLayerIndex&, const RenderTile&) override;
void place(Placement&, const BucketPlacementParameters&, std::set<uint32_t>&) override;
void updateVertices(
const Placement&, bool updateOpacities, const TransformState&, const RenderTile&, std::set<uint32_t>&) override;
Expand Down Expand Up @@ -114,6 +114,7 @@ class SymbolBucket final : public Bucket {
// Set and used by placement.
mutable bool justReloaded : 1;
bool hasVariablePlacement : 1;
bool hasUninitializedSymbols : 1;

std::vector<SymbolInstance> symbolInstances;

Expand Down
124 changes: 57 additions & 67 deletions src/mbgl/renderer/render_orchestrator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,61 +135,58 @@ void RenderOrchestrator::setObserver(RendererObserver* observer_) {
observer = observer_ ? observer_ : &nullObserver();
}

std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdateParameters& updateParameters) {
const bool isMapModeContinuous = updateParameters.mode == MapMode::Continuous;
std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(
const std::shared_ptr<UpdateParameters>& updateParameters) {
const bool isMapModeContinuous = updateParameters->mode == MapMode::Continuous;
if (!isMapModeContinuous) {
// Reset zoom history state.
zoomHistory.first = true;
}

if (LayerManager::annotationsEnabled) {
updateParameters.annotationManager.updateData();
updateParameters->annotationManager.updateData();
}

const bool zoomChanged = zoomHistory.update(updateParameters.transformState.getZoom(), updateParameters.timePoint);
const bool zoomChanged =
zoomHistory.update(updateParameters->transformState.getZoom(), updateParameters->timePoint);

const TransitionOptions transitionOptions = isMapModeContinuous ? updateParameters.transitionOptions : TransitionOptions();
const TransitionOptions transitionOptions =
isMapModeContinuous ? updateParameters->transitionOptions : TransitionOptions();

const TransitionParameters transitionParameters {
updateParameters.timePoint,
transitionOptions
};
const TransitionParameters transitionParameters{updateParameters->timePoint, transitionOptions};

const PropertyEvaluationParameters evaluationParameters {
const PropertyEvaluationParameters evaluationParameters{
zoomHistory,
updateParameters.timePoint,
transitionOptions.duration.value_or(isMapModeContinuous ? util::DEFAULT_TRANSITION_DURATION : Duration::zero())
};

const TileParameters tileParameters {
updateParameters.pixelRatio,
updateParameters.debugOptions,
updateParameters.transformState,
updateParameters.fileSource,
updateParameters.mode,
updateParameters.annotationManager,
*imageManager,
*glyphManager,
updateParameters.prefetchZoomDelta
};

glyphManager->setURL(updateParameters.glyphURL);
updateParameters->timePoint,
transitionOptions.duration.value_or(isMapModeContinuous ? util::DEFAULT_TRANSITION_DURATION
: Duration::zero())};

const TileParameters tileParameters{updateParameters->pixelRatio,
updateParameters->debugOptions,
updateParameters->transformState,
updateParameters->fileSource,
updateParameters->mode,
updateParameters->annotationManager,
*imageManager,
*glyphManager,
updateParameters->prefetchZoomDelta};

glyphManager->setURL(updateParameters->glyphURL);

// Update light.
const bool lightChanged = renderLight.impl != updateParameters.light;
const bool lightChanged = renderLight.impl != updateParameters->light;

if (lightChanged) {
renderLight.impl = updateParameters.light;
renderLight.impl = updateParameters->light;
renderLight.transition(transitionParameters);
}

if (lightChanged || zoomChanged || renderLight.hasTransition()) {
renderLight.evaluate(evaluationParameters);
}


const ImageDifference imageDiff = diffImages(imageImpls, updateParameters.images);
imageImpls = updateParameters.images;
const ImageDifference imageDiff = diffImages(imageImpls, updateParameters->images);
imageImpls = updateParameters->images;

// Only trigger tile reparse for changed images. Changed images only need a relayout when they have a different size.
bool hasImageDiff = !imageDiff.removed.empty();
Expand All @@ -214,10 +211,10 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
}

imageManager->notifyIfMissingImageAdded();
imageManager->setLoaded(updateParameters.spriteLoaded);
imageManager->setLoaded(updateParameters->spriteLoaded);

const LayerDifference layerDiff = diffLayers(layerImpls, updateParameters.layers);
layerImpls = updateParameters.layers;
const LayerDifference layerDiff = diffLayers(layerImpls, updateParameters->layers);
layerImpls = updateParameters->layers;
const bool layersAddedOrRemoved = !layerDiff.added.empty() || !layerDiff.removed.empty();

// Remove render layers for removed layers.
Expand Down Expand Up @@ -266,8 +263,8 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
}
}

const SourceDifference sourceDiff = diffSources(sourceImpls, updateParameters.sources);
sourceImpls = updateParameters.sources;
const SourceDifference sourceDiff = diffSources(sourceImpls, updateParameters->sources);
sourceImpls = updateParameters->sources;

// Remove render layers for removed sources.
for (const auto& entry : sourceDiff.removed) {
Expand All @@ -280,15 +277,14 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
renderSource->setObserver(this);
renderSources.emplace(entry.first, std::move(renderSource));
}
transformState = updateParameters.transformState;
transformState = updateParameters->transformState;

// Create parameters for the render tree.
auto renderTreeParameters = std::make_unique<RenderTreeParameters>(
updateParameters.transformState,
updateParameters.mode,
updateParameters.debugOptions,
updateParameters.timePoint,
renderLight.getEvaluated());
auto renderTreeParameters = std::make_unique<RenderTreeParameters>(updateParameters->transformState,
updateParameters->mode,
updateParameters->debugOptions,
updateParameters->timePoint,
renderLight.getEvaluated());

std::set<LayerRenderItem> layerRenderItems;
layersNeedPlacement.clear();
Expand Down Expand Up @@ -349,22 +345,24 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
filteredLayersForSource.clear();
}

renderTreeParameters->loaded = updateParameters.styleLoaded && isLoaded();
renderTreeParameters->loaded = updateParameters->styleLoaded && isLoaded();
if (!isMapModeContinuous && !renderTreeParameters->loaded) {
return nullptr;
}

// Prepare. Update all matrices and generate data that we should upload to the GPU.
for (const auto& entry : renderSources) {
if (entry.second->isEnabled()) {
entry.second->prepare({renderTreeParameters->transformParams, updateParameters.debugOptions, *imageManager});
entry.second->prepare(
{renderTreeParameters->transformParams, updateParameters->debugOptions, *imageManager});
}
}

auto opaquePassCutOffEstimation = layerRenderItems.size();
for (auto& renderItem : layerRenderItems) {
RenderLayer& renderLayer = renderItem.layer;
renderLayer.prepare({renderItem.source, *imageManager, *patternAtlas, *lineAtlas, updateParameters.transformState});
renderLayer.prepare(
{renderItem.source, *imageManager, *patternAtlas, *lineAtlas, updateParameters->transformState});
if (renderLayer.needsPlacement()) {
layersNeedPlacement.emplace_back(renderLayer);
}
Expand All @@ -377,10 +375,11 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
}
// Symbol placement.
bool symbolBucketsChanged = false;
auto longitude = updateParameters->transformState.getLatLng().longitude();
if (isMapModeContinuous) {
bool symbolBucketsAdded = false;
for (auto it = layersNeedPlacement.crbegin(); it != layersNeedPlacement.crend(); ++it) {
auto result = crossTileSymbolIndex.addLayer(*it, updateParameters.transformState.getLatLng().longitude());
auto result = crossTileSymbolIndex.addLayer(*it, longitude);
symbolBucketsAdded = symbolBucketsAdded || (result & CrossTileSymbolIndex::AddLayerResult::BucketsAdded);
symbolBucketsChanged = symbolBucketsChanged || (result != CrossTileSymbolIndex::AddLayerResult::NoChanges);
}
Expand All @@ -391,24 +390,20 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
optional<Duration> maximumPlacementUpdatePeriod;
if (symbolBucketsAdded) maximumPlacementUpdatePeriod = optional<Duration>(Milliseconds(30));
renderTreeParameters->placementChanged = !placementController.placementIsRecent(
updateParameters.timePoint, updateParameters.transformState.getZoom(), maximumPlacementUpdatePeriod);
updateParameters->timePoint, updateParameters->transformState.getZoom(), maximumPlacementUpdatePeriod);
symbolBucketsChanged |= renderTreeParameters->placementChanged;

std::set<std::string> usedSymbolLayers;
if (renderTreeParameters->placementChanged) {
Mutable<Placement> placement = makeMutable<Placement>(updateParameters.transformState,
updateParameters.mode,
updateParameters.transitionOptions,
updateParameters.crossSourceCollisions,
placementController.getPlacement());
Mutable<Placement> placement = makeMutable<Placement>(updateParameters, placementController.getPlacement());

for (auto it = layersNeedPlacement.crbegin(); it != layersNeedPlacement.crend(); ++it) {
const RenderLayer& layer = *it;
usedSymbolLayers.insert(layer.getID());
placement->placeLayer(layer, renderTreeParameters->transformParams.projMatrix, updateParameters.debugOptions & MapDebugOptions::Collision);
placement->placeLayer(layer);
}

placement->commit(updateParameters.timePoint, updateParameters.transformState.getZoom());
placement->commit();
crossTileSymbolIndex.pruneUnusedLayers(usedSymbolLayers);
for (const auto& entry : renderSources) {
entry.second->updateFadingTiles();
Expand All @@ -418,24 +413,19 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
placementController.setPlacementStale();
}
renderTreeParameters->symbolFadeChange =
placementController.getPlacement()->symbolFadeChange(updateParameters.timePoint);
renderTreeParameters->needsRepaint = hasTransitions(updateParameters.timePoint);
placementController.getPlacement()->symbolFadeChange(updateParameters->timePoint);
renderTreeParameters->needsRepaint = hasTransitions(updateParameters->timePoint);
} else {
crossTileSymbolIndex.reset();
renderTreeParameters->placementChanged = symbolBucketsChanged = !layersNeedPlacement.empty();
if (renderTreeParameters->placementChanged) {
Mutable<Placement> placement = makeMutable<Placement>(updateParameters.transformState,
updateParameters.mode,
updateParameters.transitionOptions,
updateParameters.crossSourceCollisions);
Mutable<Placement> placement = makeMutable<Placement>(updateParameters);
for (auto it = layersNeedPlacement.crbegin(); it != layersNeedPlacement.crend(); ++it) {
const RenderLayer& layer = *it;
crossTileSymbolIndex.addLayer(layer, updateParameters.transformState.getLatLng().longitude());
placement->placeLayer(layer,
renderTreeParameters->transformParams.projMatrix,
updateParameters.debugOptions & MapDebugOptions::Collision);
crossTileSymbolIndex.addLayer(layer, longitude);
placement->placeLayer(layer);
}
placement->commit(updateParameters.timePoint, updateParameters.transformState.getZoom());
placement->commit();
placementController.setPlacement(std::move(placement));
}
renderTreeParameters->symbolFadeChange = 1.0f;
Expand Down
Loading