[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.
This commit is contained in:
Mikhail Pozdnyakov
2019-10-03 18:32:07 +03:00
parent ac18688824
commit 064c60cdca
2 changed files with 39 additions and 26 deletions

View File

@@ -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,

View File

@@ -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