summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2019-10-03 18:32:07 +0300
committerMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2019-10-04 13:16:54 +0300
commit064c60cdcab331bc19fe399492179dcb5b29121a (patch)
tree7f1de3beaa1ebf9c6295605120a6bfa156aa3638
parentac1868882470cb3b2549c65f13cd35efb8105b74 (diff)
downloadqtlocation-mapboxgl-064c60cdcab331bc19fe399492179dcb5b29121a.tar.gz
[core] Orchestration performance for styles with multiple sources
RenderOrchestrator holds a vector of ordered rendered layers, in order to minimize calling of `getRenderLayer()`, which could be quite expensive as it calculates hash of the layer Id. This change improves orchestration performance in particular for the styles that have multiple sources. The `API_renderStill_multiple_sources` benchmark runs approximately 70% faster with the changes applied.
-rw-r--r--src/mbgl/renderer/render_orchestrator.cpp61
-rw-r--r--src/mbgl/renderer/render_orchestrator.hpp4
2 files changed, 39 insertions, 26 deletions
diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp
index 28f6ab3199..50077784b5 100644
--- a/src/mbgl/renderer/render_orchestrator.cpp
+++ b/src/mbgl/renderer/render_orchestrator.cpp
@@ -220,6 +220,7 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
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.
for (const auto& entry : layerDiff.removed) {
@@ -238,20 +239,31 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
renderLayers.at(entry.first)->transition(transitionParameters, entry.second.after);
}
- if (!layerDiff.removed.empty() || !layerDiff.added.empty() || !layerDiff.changed.empty()) {
- glyphManager->evict(fontStacks(*updateParameters.layers));
+ if (layersAddedOrRemoved) {
+ orderedLayers.clear();
+ orderedLayers.reserve(layerImpls->size());
+ for (const auto& layerImpl : *layerImpls) {
+ RenderLayer* layer = renderLayers.at(layerImpl->id).get();
+ assert(layer);
+ orderedLayers.emplace_back(*layer);
+ }
+ }
+ assert(orderedLayers.size() == renderLayers.size());
+
+ if (layersAddedOrRemoved || !layerDiff.changed.empty()) {
+ glyphManager->evict(fontStacks(*layerImpls));
}
// Update layers for class and zoom changes.
std::unordered_set<std::string> constantsMaskChanged;
- for (const auto& entry : renderLayers) {
- RenderLayer& layer = *entry.second;
- const bool layerAddedOrChanged = layerDiff.added.count(entry.first) || layerDiff.changed.count(entry.first);
+ for (RenderLayer& layer : orderedLayers) {
+ const std::string& id = layer.getID();
+ const bool layerAddedOrChanged = layerDiff.added.count(id) || layerDiff.changed.count(id);
if (layerAddedOrChanged || zoomChanged || layer.hasTransition() || layer.hasCrossfade()) {
auto previousMask = layer.evaluatedProperties->constantsMask();
layer.evaluate(evaluationParameters);
if (previousMask != layer.evaluatedProperties->constantsMask()) {
- constantsMaskChanged.insert(layer.getID());
+ constantsMaskChanged.insert(id);
}
}
}
@@ -281,7 +293,7 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
renderLight.getEvaluated());
std::set<LayerRenderItem> layerRenderItems;
- std::vector<std::reference_wrapper<RenderLayer>> layersNeedPlacement;
+ layersNeedPlacement.clear();
auto renderItemsEmplaceHint = layerRenderItems.begin();
// Reserve size for filteredLayersForSource if there are sources.
@@ -293,27 +305,26 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
for (const auto& sourceImpl : *sourceImpls) {
RenderSource* source = renderSources.at(sourceImpl->id).get();
bool sourceNeedsRendering = false;
- bool sourceNeedsRelayout = false;
-
- uint32_t index = 0u;
- const auto begin = layerImpls->begin();
- const auto end = layerImpls->end();
- for (auto it = begin; it != end; ++it, ++index) {
- const Immutable<Layer::Impl>& layerImpl = *it;
- RenderLayer* layer = getRenderLayer(layerImpl->id);
- const auto* layerInfo = layerImpl->getTypeInfo();
- const bool layerIsVisible = layer->baseImpl->visibility != style::VisibilityType::None;
- const bool zoomFitsLayer = layer->supportsZoom(zoomHistory.lastZoom);
+ bool sourceNeedsRelayout = false;
+
+ for (uint32_t index = 0u; index < orderedLayers.size(); ++index) {
+ RenderLayer& layer = orderedLayers[index];
+ const auto* layerInfo = layer.baseImpl->getTypeInfo();
+ const bool layerIsVisible = layer.baseImpl->visibility != style::VisibilityType::None;
+ const bool zoomFitsLayer = layer.supportsZoom(zoomHistory.lastZoom);
renderTreeParameters->has3D |= (layerInfo->pass3d == LayerTypeInfo::Pass3D::Required);
if (layerInfo->source != LayerTypeInfo::Source::NotRequired) {
- if (layerImpl->source == sourceImpl->id) {
- sourceNeedsRelayout = (sourceNeedsRelayout || hasImageDiff || constantsMaskChanged.count(layerImpl->id) || hasLayoutDifference(layerDiff, layerImpl->id));
+ if (layer.baseImpl->source == sourceImpl->id) {
+ const std::string& layerId = layer.getID();
+ sourceNeedsRelayout = (sourceNeedsRelayout || hasImageDiff || constantsMaskChanged.count(layerId) ||
+ hasLayoutDifference(layerDiff, layerId));
if (layerIsVisible) {
- filteredLayersForSource.push_back(layer->evaluatedProperties);
+ filteredLayersForSource.push_back(layer.evaluatedProperties);
if (zoomFitsLayer) {
sourceNeedsRendering = true;
- renderItemsEmplaceHint = layerRenderItems.emplace_hint(renderItemsEmplaceHint, *layer, source, index);
+ renderItemsEmplaceHint =
+ layerRenderItems.emplace_hint(renderItemsEmplaceHint, layer, source, index);
}
}
}
@@ -322,14 +333,14 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
// Handle layers without source.
if (layerIsVisible && zoomFitsLayer && sourceImpl.get() == sourceImpls->at(0).get()) {
- if (backgroundLayerAsColor && layerImpl.get() == layerImpls->at(0).get()) {
- const auto& solidBackground = layer->getSolidBackground();
+ if (backgroundLayerAsColor && layer.baseImpl == layerImpls->front()) {
+ const auto& solidBackground = layer.getSolidBackground();
if (solidBackground) {
renderTreeParameters->backgroundColor = *solidBackground;
continue; // This layer is shown with background color, and it shall not be added to render items.
}
}
- renderItemsEmplaceHint = layerRenderItems.emplace_hint(renderItemsEmplaceHint, *layer, nullptr, index);
+ renderItemsEmplaceHint = layerRenderItems.emplace_hint(renderItemsEmplaceHint, layer, nullptr, index);
}
}
source->update(sourceImpl,
diff --git a/src/mbgl/renderer/render_orchestrator.hpp b/src/mbgl/renderer/render_orchestrator.hpp
index 9b63498a2a..c2b44c2792 100644
--- a/src/mbgl/renderer/render_orchestrator.hpp
+++ b/src/mbgl/renderer/render_orchestrator.hpp
@@ -127,9 +127,11 @@ private:
const bool backgroundLayerAsColor;
bool contextLost = false;
- // Vector with reserved capacity of layerImpls->size() to avoid reallocation
+ // Vectors with reserved capacity of layerImpls->size() to avoid reallocation
// on each frame.
std::vector<Immutable<style::LayerProperties>> filteredLayersForSource;
+ std::vector<std::reference_wrapper<RenderLayer>> orderedLayers;
+ std::vector<std::reference_wrapper<RenderLayer>> layersNeedPlacement;
};
} // namespace mbgl