From fb72de77afbb14fa4362ed448a5b499957c62aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Fri, 16 Aug 2019 12:03:53 +0200 Subject: [PATCH 1/3] [core] Store SegmentVectors in ephemeral render objects We used some shared SegmentVectors, e.g. for drawing raster or background tiles. In longer running maps, this lead to resource accumulation. By storing the SegmentVectors and the contained gfx::DrawScope objects, we ensure that resources get released when the associated render objects vanish. --- CMakeLists.txt | 2 - src/mbgl/renderer/buckets/debug_bucket.cpp | 5 +- src/mbgl/renderer/buckets/debug_bucket.hpp | 2 +- src/mbgl/renderer/buckets/raster_bucket.cpp | 14 ++-- src/mbgl/renderer/buckets/raster_bucket.hpp | 1 - .../layers/render_background_layer.cpp | 76 +++++++++--------- .../layers/render_background_layer.hpp | 2 + .../renderer/layers/render_circle_layer.cpp | 7 +- .../layers/render_fill_extrusion_layer.cpp | 7 +- .../renderer/layers/render_fill_layer.cpp | 7 +- .../renderer/layers/render_heatmap_layer.cpp | 22 ++--- .../renderer/layers/render_heatmap_layer.hpp | 9 ++- .../layers/render_hillshade_layer.cpp | 80 ++++++++++--------- .../renderer/layers/render_line_layer.cpp | 9 +-- .../renderer/layers/render_raster_layer.cpp | 43 +++++----- .../renderer/layers/render_symbol_layer.cpp | 14 ++-- src/mbgl/renderer/paint_parameters.cpp | 57 ++++++------- src/mbgl/renderer/render_static_data.cpp | 34 ++++++-- src/mbgl/renderer/render_static_data.hpp | 10 ++- src/mbgl/renderer/render_tile.cpp | 67 ++++++---------- .../renderer/sources/render_image_source.cpp | 46 +++++------ src/mbgl/util/id.cpp | 14 ---- src/mbgl/util/id.hpp | 11 --- 23 files changed, 250 insertions(+), 289 deletions(-) delete mode 100644 src/mbgl/util/id.cpp delete mode 100644 src/mbgl/util/id.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4509f08e733..485ced04aad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -772,8 +772,6 @@ add_library( ${PROJECT_SOURCE_DIR}/src/mbgl/util/http_timeout.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/i18n.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/i18n.hpp - ${PROJECT_SOURCE_DIR}/src/mbgl/util/id.cpp - ${PROJECT_SOURCE_DIR}/src/mbgl/util/id.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/interpolate.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/intersection_tests.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/intersection_tests.hpp diff --git a/src/mbgl/renderer/buckets/debug_bucket.cpp b/src/mbgl/renderer/buckets/debug_bucket.cpp index 13380c09058..fcdc727f4b8 100644 --- a/src/mbgl/renderer/buckets/debug_bucket.cpp +++ b/src/mbgl/renderer/buckets/debug_bucket.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include @@ -20,9 +19,7 @@ DebugBucket::DebugBucket(const OverscaledTileID& id, complete(complete_), modified(std::move(modified_)), expires(std::move(expires_)), - debugMode(debugMode_), - drawScopeID("__debug/" + util::toHex(util::nextID())) { - + debugMode(debugMode_) { auto addText = [&] (const std::string& text, double left, double baseline, double scale) { for (uint8_t c : text) { if (c < 32 || c >= 127) diff --git a/src/mbgl/renderer/buckets/debug_bucket.hpp b/src/mbgl/renderer/buckets/debug_bucket.hpp index 2b735b4987f..78b1cbb8ff5 100644 --- a/src/mbgl/renderer/buckets/debug_bucket.hpp +++ b/src/mbgl/renderer/buckets/debug_bucket.hpp @@ -40,9 +40,9 @@ class DebugBucket : private util::noncopyable { gfx::IndexVector indices; SegmentVector segments; + SegmentVector tileBorderSegments; optional> vertexBuffer; optional indexBuffer; - const std::string drawScopeID; }; } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/raster_bucket.cpp b/src/mbgl/renderer/buckets/raster_bucket.cpp index a26b9a50650..859ee8d2a24 100644 --- a/src/mbgl/renderer/buckets/raster_bucket.cpp +++ b/src/mbgl/renderer/buckets/raster_bucket.cpp @@ -2,21 +2,15 @@ #include #include #include -#include namespace mbgl { using namespace style; RasterBucket::RasterBucket(PremultipliedImage&& image_) - : image(std::make_shared(std::move(image_))), - drawScopeID(util::toHex(util::nextID())) { -} + : image(std::make_shared(std::move(image_))) {} -RasterBucket::RasterBucket(std::shared_ptr image_) - : image(std::move(image_)), - drawScopeID(util::toHex(util::nextID())) { -} +RasterBucket::RasterBucket(std::shared_ptr image_) : image(std::move(image_)) {} RasterBucket::~RasterBucket() = default; @@ -27,8 +21,10 @@ void RasterBucket::upload(gfx::UploadPass& uploadPass) { if (!texture) { texture = uploadPass.createTexture(*image); } - if (!segments.empty()) { + if (!vertices.empty()) { vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); + } + if (!indices.empty()) { indexBuffer = uploadPass.createIndexBuffer(std::move(indices)); } uploaded = true; diff --git a/src/mbgl/renderer/buckets/raster_bucket.hpp b/src/mbgl/renderer/buckets/raster_bucket.hpp index f880903167c..0fa3c4299e4 100644 --- a/src/mbgl/renderer/buckets/raster_bucket.hpp +++ b/src/mbgl/renderer/buckets/raster_bucket.hpp @@ -37,7 +37,6 @@ class RasterBucket final : public Bucket { optional> vertexBuffer; optional indexBuffer; - const std::string drawScopeID; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index 694addcc97b..96a4c44f08c 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -18,7 +17,7 @@ using namespace style; namespace { -inline const BackgroundLayer::Impl& impl(const Immutable& impl) { +inline const BackgroundLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == BackgroundLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -27,13 +26,12 @@ inline const BackgroundLayer::Impl& impl(const Immutable& im RenderBackgroundLayer::RenderBackgroundLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} RenderBackgroundLayer::~RenderBackgroundLayer() = default; void RenderBackgroundLayer::transition(const TransitionParameters ¶meters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters ¶meters) { @@ -69,7 +67,7 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) { const Properties<>::PossiblyEvaluated properties; const BackgroundProgram::Binders paintAttributeData(properties, 0); - auto draw = [&](auto& program, auto&& uniformValues, const auto& textureBindings, const UnwrappedTileID& id) { + auto draw = [&](auto& program, auto&& uniformValues, const auto& textureBindings, const uint32_t id) { const auto allUniformValues = program.computeAllUniformValues( std::move(uniformValues), paintAttributeData, @@ -88,20 +86,24 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) { parameters.context, *parameters.renderPass, gfx::Triangles(), - parameters.depthModeForSublayer(0, parameters.pass == RenderPass::Opaque - ? gfx::DepthMaskType::ReadWrite - : gfx::DepthMaskType::ReadOnly), + parameters.depthModeForSublayer( + 0, + parameters.pass == RenderPass::Opaque ? gfx::DepthMaskType::ReadWrite : gfx::DepthMaskType::ReadOnly), gfx::StencilMode::disabled(), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), *parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.tileTriangleSegments, + segments, allUniformValues, allAttributeBindings, textureBindings, - getID() + "/" + util::toString(id) - ); + util::toString(id)); }; + + if (segments.empty()) { + segments = parameters.staticData.tileTriangleSegments(); + } + const auto& evaluated = static_cast(*evaluatedProperties).evaluated; const auto& crossfade = static_cast(*evaluatedProperties).crossfade; if (!evaluated.get().to.empty()) { @@ -113,24 +115,21 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) { if (!imagePosA || !imagePosB) return; + uint32_t i = 0; for (const auto& tileID : util::tileCover(parameters.state, parameters.state.getIntegerZoom())) { - draw( - parameters.programs.getBackgroundLayerPrograms().backgroundPattern, - BackgroundPatternProgram::layoutUniformValues( - parameters.matrixForTile(tileID), - evaluated.get(), - parameters.patternAtlas.getPixelSize(), - *imagePosA, - *imagePosB, - crossfade, - tileID, - parameters.state - ), - BackgroundPatternProgram::TextureBindings{ - textures::image::Value{ parameters.patternAtlas.textureBinding() }, - }, - tileID - ); + draw(parameters.programs.getBackgroundLayerPrograms().backgroundPattern, + BackgroundPatternProgram::layoutUniformValues(parameters.matrixForTile(tileID), + evaluated.get(), + parameters.patternAtlas.getPixelSize(), + *imagePosA, + *imagePosB, + crossfade, + tileID, + parameters.state), + BackgroundPatternProgram::TextureBindings{ + textures::image::Value{parameters.patternAtlas.textureBinding()}, + }, + i++); } } else { auto backgroundRenderPass = (evaluated.get().a >= 1.0f @@ -139,17 +138,16 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) { if (parameters.pass != backgroundRenderPass) { return; } + uint32_t i = 0; for (const auto& tileID : util::tileCover(parameters.state, parameters.state.getIntegerZoom())) { - draw( - parameters.programs.getBackgroundLayerPrograms().background, - BackgroundProgram::LayoutUniformValues { - uniforms::matrix::Value( parameters.matrixForTile(tileID) ), - uniforms::color::Value( evaluated.get() ), - uniforms::opacity::Value( evaluated.get() ), - }, - BackgroundProgram::TextureBindings{}, - tileID - ); + draw(parameters.programs.getBackgroundLayerPrograms().background, + BackgroundProgram::LayoutUniformValues{ + uniforms::matrix::Value(parameters.matrixForTile(tileID)), + uniforms::color::Value(evaluated.get()), + uniforms::opacity::Value(evaluated.get()), + }, + BackgroundProgram::TextureBindings{}, + i++); } } } diff --git a/src/mbgl/renderer/layers/render_background_layer.hpp b/src/mbgl/renderer/layers/render_background_layer.hpp index dfc2adf76ed..dab733172b8 100644 --- a/src/mbgl/renderer/layers/render_background_layer.hpp +++ b/src/mbgl/renderer/layers/render_background_layer.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -22,6 +23,7 @@ class RenderBackgroundLayer final : public RenderLayer { // Paint properties style::BackgroundPaintProperties::Unevaluated unevaluated; + SegmentVector segments; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index b88a026e118..e5d7e6230e4 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -17,7 +17,7 @@ using namespace style; namespace { -inline const style::CircleLayer::Impl& impl(const Immutable& impl) { +inline const style::CircleLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == CircleLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -26,11 +26,10 @@ inline const style::CircleLayer::Impl& impl(const Immutable& RenderCircleLayer::RenderCircleLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} void RenderCircleLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } void RenderCircleLayer::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index af0bc788d05..4eaec6e55f7 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -23,7 +23,7 @@ using namespace style; namespace { -inline const FillExtrusionLayer::Impl& impl(const Immutable& impl) { +inline const FillExtrusionLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == FillExtrusionLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -32,13 +32,12 @@ inline const FillExtrusionLayer::Impl& impl(const Immutable& RenderFillExtrusionLayer::RenderFillExtrusionLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} RenderFillExtrusionLayer::~RenderFillExtrusionLayer() = default; void RenderFillExtrusionLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index bbfcef7aba4..31b847b6a75 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -24,7 +24,7 @@ using namespace style; namespace { -inline const FillLayer::Impl& impl(const Immutable& impl) { +inline const FillLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == FillLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -33,13 +33,12 @@ inline const FillLayer::Impl& impl(const Immutable& impl) { RenderFillLayer::RenderFillLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} RenderFillLayer::~RenderFillLayer() = default; void RenderFillLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index 797aedd297c..5f3c36e4404 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -21,7 +20,7 @@ using namespace style; namespace { -inline const HeatmapLayer::Impl& impl(const Immutable& impl) { +inline const HeatmapLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == HeatmapLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -30,13 +29,13 @@ inline const HeatmapLayer::Impl& impl(const Immutable& impl) { RenderHeatmapLayer::RenderHeatmapLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()), colorRamp({256, 1}) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()), + colorRamp({256, 1}) {} RenderHeatmapLayer::~RenderHeatmapLayer() = default; void RenderHeatmapLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); updateColorRamp(); } @@ -177,6 +176,10 @@ void RenderHeatmapLayer::render(PaintParameters& parameters) { checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); + if (segments.empty()) { + // Copy over the segments so that we can create our own DrawScopes. + segments = parameters.staticData.heatmapTextureSegments(); + } programInstance.draw( parameters.context, *parameters.renderPass, @@ -186,15 +189,14 @@ void RenderHeatmapLayer::render(PaintParameters& parameters) { parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), *parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.heatmapTextureSegments, + segments, allUniformValues, allAttributeBindings, HeatmapTextureProgram::TextureBindings{ - textures::image::Value{ renderTexture->getTexture().getResource(), gfx::TextureFilterType::Linear }, - textures::color_ramp::Value{ colorRampTexture->getResource(), gfx::TextureFilterType::Linear }, + textures::image::Value{renderTexture->getTexture().getResource(), gfx::TextureFilterType::Linear}, + textures::color_ramp::Value{colorRampTexture->getResource(), gfx::TextureFilterType::Linear}, }, - getID() - ); + getID()); } } diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.hpp b/src/mbgl/renderer/layers/render_heatmap_layer.hpp index 1e9b1063aeb..b7a03a6ba59 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.hpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.hpp @@ -1,10 +1,11 @@ #pragma once +#include +#include +#include #include #include #include -#include -#include #include namespace mbgl { @@ -24,14 +25,14 @@ class RenderHeatmapLayer final : public RenderLayer { bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float, const TransformState&, const float, const mat4&, const FeatureState&) const override; + void updateColorRamp(); // Paint properties style::HeatmapPaintProperties::Unevaluated unevaluated; PremultipliedImage colorRamp; std::unique_ptr renderTexture; optional colorRampTexture; - - void updateColorRamp(); + SegmentVector segments; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp index b570d9c4c95..bf899221f8e 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp @@ -20,7 +20,7 @@ using namespace style; namespace { -inline const HillshadeLayer::Impl& impl(const Immutable& impl) { +inline const HillshadeLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == HillshadeLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -29,8 +29,7 @@ inline const HillshadeLayer::Impl& impl(const Immutable& imp RenderHillshadeLayer::RenderHillshadeLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} RenderHillshadeLayer::~RenderHillshadeLayer() = default; @@ -48,7 +47,7 @@ const std::array RenderHillshadeLayer::getLight(const PaintParameters& } void RenderHillshadeLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } void RenderHillshadeLayer::evaluate(const PropertyEvaluationParameters& parameters) { @@ -111,21 +110,19 @@ void RenderHillshadeLayer::render(PaintParameters& parameters) { checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); - programInstance.draw( - parameters.context, - *parameters.renderPass, - gfx::Triangles(), - parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), - gfx::StencilMode::disabled(), - parameters.colorModeForRenderPass(), - gfx::CullFaceMode::disabled(), - indexBuffer, - segments, - allUniformValues, - allAttributeBindings, - textureBindings, - getID() + "/" + util::toString(id) - ); + programInstance.draw(parameters.context, + *parameters.renderPass, + gfx::Triangles(), + parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), + gfx::StencilMode::disabled(), + parameters.colorModeForRenderPass(), + gfx::CullFaceMode::disabled(), + indexBuffer, + segments, + allUniformValues, + allAttributeBindings, + textureBindings, + getID()); }; mat4 mat; @@ -177,29 +174,30 @@ void RenderHillshadeLayer::render(PaintParameters& parameters) { checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); - programInstance.draw( - parameters.context, - *renderPass, - gfx::Triangles(), - parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), - gfx::StencilMode::disabled(), - parameters.colorModeForRenderPass(), - gfx::CullFaceMode::disabled(), - *parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.rasterSegments, - allUniformValues, - allAttributeBindings, - HillshadePrepareProgram::TextureBindings{ - textures::image::Value{ bucket.dem->getResource() }, - }, - getID() + "/p/" + util::toString(tile.id) - ); + // Copy over the segments so that we can create our own DrawScopes that get destroyed + // after this draw call. + auto segments = parameters.staticData.rasterSegments(); + programInstance.draw(parameters.context, + *renderPass, + gfx::Triangles(), + parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), + gfx::StencilMode::disabled(), + parameters.colorModeForRenderPass(), + gfx::CullFaceMode::disabled(), + *parameters.staticData.quadTriangleIndexBuffer, + segments, + allUniformValues, + allAttributeBindings, + HillshadePrepareProgram::TextureBindings{ + textures::image::Value{bucket.dem->getResource()}, + }, + "prepare"); bucket.texture = std::move(view->getTexture()); bucket.setPrepared(true); } else if (parameters.pass == RenderPass::Translucent) { assert(bucket.texture); - if (bucket.vertexBuffer && bucket.indexBuffer && !bucket.segments.empty()) { + if (bucket.vertexBuffer && bucket.indexBuffer) { // Draw only the parts of the tile that aren't drawn by another tile in the layer. draw(parameters.matrixForTile(tile.id, true), *bucket.vertexBuffer, @@ -211,13 +209,17 @@ void RenderHillshadeLayer::render(PaintParameters& parameters) { }); } else { // Draw the full tile. + if (bucket.segments.empty()) { + // Copy over the segments so that we can create our own DrawScopes. + bucket.segments = parameters.staticData.rasterSegments(); + } draw(parameters.matrixForTile(tile.id, true), *parameters.staticData.rasterVertexBuffer, *parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.rasterSegments, + bucket.segments, tile.id, HillshadeProgram::TextureBindings{ - textures::image::Value{ bucket.texture->getResource(), gfx::TextureFilterType::Linear }, + textures::image::Value{bucket.texture->getResource(), gfx::TextureFilterType::Linear}, }); } } diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index 588cf6286cf..90bb38b9f96 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -23,7 +23,7 @@ using namespace style; namespace { -inline const LineLayer::Impl& impl(const Immutable& impl) { +inline const LineLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == LineLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -32,14 +32,13 @@ inline const LineLayer::Impl& impl(const Immutable& impl) { RenderLineLayer::RenderLineLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()), - colorRamp({256, 1}) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()), + colorRamp({256, 1}) {} RenderLineLayer::~RenderLineLayer() = default; void RenderLineLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); updateColorRamp(); } diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index 8a1a8a6c288..047333d5e5d 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -16,7 +16,7 @@ using namespace style; namespace { -inline const RasterLayer::Impl& impl(const Immutable& impl) { +inline const RasterLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == RasterLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -25,13 +25,12 @@ inline const RasterLayer::Impl& impl(const Immutable& impl) RenderRasterLayer::RenderRasterLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} RenderRasterLayer::~RenderRasterLayer() = default; void RenderRasterLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters) { @@ -153,14 +152,14 @@ void RenderRasterLayer::render(PaintParameters& parameters) { size_t i = 0; for (const auto& matrix_ : imageData->matrices) { draw(matrix_, - *bucket.vertexBuffer, - *bucket.indexBuffer, - bucket.segments, - RasterProgram::TextureBindings{ - textures::image0::Value{ bucket.texture->getResource(), filter }, - textures::image1::Value{ bucket.texture->getResource(), filter }, - }, - bucket.drawScopeID + std::to_string(i++)); + *bucket.vertexBuffer, + *bucket.indexBuffer, + bucket.segments, + RasterProgram::TextureBindings{ + textures::image0::Value{bucket.texture->getResource(), filter}, + textures::image1::Value{bucket.texture->getResource(), filter}, + }, + std::to_string(i++)); } } else if (renderTiles) { for (const RenderTile& tile : *renderTiles) { @@ -174,28 +173,32 @@ void RenderRasterLayer::render(PaintParameters& parameters) { continue; assert(bucket.texture); - if (bucket.vertexBuffer && bucket.indexBuffer && !bucket.segments.empty()) { + if (bucket.vertexBuffer && bucket.indexBuffer) { // Draw only the parts of the tile that aren't drawn by another tile in the layer. draw(parameters.matrixForTile(tile.id, true), *bucket.vertexBuffer, *bucket.indexBuffer, bucket.segments, RasterProgram::TextureBindings{ - textures::image0::Value{ bucket.texture->getResource(), filter }, - textures::image1::Value{ bucket.texture->getResource(), filter }, + textures::image0::Value{bucket.texture->getResource(), filter}, + textures::image1::Value{bucket.texture->getResource(), filter}, }, - bucket.drawScopeID); + "image"); } else { // Draw the full tile. + if (bucket.segments.empty()) { + // Copy over the segments so that we can create our own DrawScopes. + bucket.segments = parameters.staticData.rasterSegments(); + } draw(parameters.matrixForTile(tile.id, true), *parameters.staticData.rasterVertexBuffer, *parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.rasterSegments, + bucket.segments, RasterProgram::TextureBindings{ - textures::image0::Value{ bucket.texture->getResource(), filter }, - textures::image1::Value{ bucket.texture->getResource(), filter }, + textures::image0::Value{bucket.texture->getResource(), filter}, + textures::image1::Value{bucket.texture->getResource(), filter}, }, - bucket.drawScopeID); + "image"); } } } diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 955ad2ce515..2a94c452c78 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -290,7 +290,7 @@ void drawText(const DrawFn& draw, } } -inline const SymbolLayer::Impl& impl(const Immutable& impl) { +inline const SymbolLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == SymbolLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -299,14 +299,14 @@ inline const SymbolLayer::Impl& impl(const Immutable& impl) RenderSymbolLayer::RenderSymbolLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} RenderSymbolLayer::~RenderSymbolLayer() = default; void RenderSymbolLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); - hasFormatSectionOverrides = SymbolLayerPaintPropertyOverrides::hasOverrides(impl(baseImpl).layout.get()); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + hasFormatSectionOverrides = + SymbolLayerPaintPropertyOverrides::hasOverrides(impl_cast(baseImpl).layout.get()); } void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) { @@ -314,7 +314,7 @@ void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) staticImmutableCast(baseImpl), unevaluated.evaluate(parameters)); auto& evaluated = properties->evaluated; - auto& layout = impl(baseImpl).layout; + auto& layout = impl_cast(baseImpl).layout; if (hasFormatSectionOverrides) { SymbolLayerPaintPropertyOverrides::setOverrides(layout, evaluated); @@ -346,7 +346,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { return; } - const bool sortFeaturesByKey = !impl(baseImpl).layout.get().isUndefined(); + const bool sortFeaturesByKey = !impl_cast(baseImpl).layout.get().isUndefined(); std::multiset renderableSegments; const auto draw = [¶meters, this] (auto& programInstance, diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index 6c6abc008b9..b2f958b14ef 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -129,39 +129,30 @@ void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) { const int32_t stencilID = nextStencilID++; tileClippingMaskIDs.emplace(renderTile.id, stencilID); - program.draw( - context, - *renderPass, - gfx::Triangles(), - gfx::DepthMode::disabled(), - gfx::StencilMode { - gfx::StencilMode::Always{}, - stencilID, - 0b11111111, - gfx::StencilOpType::Keep, - gfx::StencilOpType::Keep, - gfx::StencilOpType::Replace - }, - gfx::ColorMode::disabled(), - gfx::CullFaceMode::disabled(), - *staticData.quadTriangleIndexBuffer, - staticData.tileTriangleSegments, - program.computeAllUniformValues( - ClippingMaskProgram::LayoutUniformValues { - uniforms::matrix::Value( matrixForTile(renderTile.id) ), - }, - paintAttributeData, - properties, - state.getZoom() - ), - program.computeAllAttributeBindings( - *staticData.tileVertexBuffer, - paintAttributeData, - properties - ), - ClippingMaskProgram::TextureBindings{}, - "clipping/" + util::toString(stencilID) - ); + program.draw(context, + *renderPass, + gfx::Triangles(), + gfx::DepthMode::disabled(), + gfx::StencilMode{gfx::StencilMode::Always{}, + stencilID, + 0b11111111, + gfx::StencilOpType::Keep, + gfx::StencilOpType::Keep, + gfx::StencilOpType::Replace}, + gfx::ColorMode::disabled(), + gfx::CullFaceMode::disabled(), + *staticData.quadTriangleIndexBuffer, + staticData.clippingMaskSegments, + program.computeAllUniformValues( + ClippingMaskProgram::LayoutUniformValues{ + uniforms::matrix::Value(matrixForTile(renderTile.id)), + }, + paintAttributeData, + properties, + state.getZoom()), + program.computeAllAttributeBindings(*staticData.tileVertexBuffer, paintAttributeData, properties), + ClippingMaskProgram::TextureBindings{}, + "clipping/" + util::toString(stencilID)); } } diff --git a/src/mbgl/renderer/render_static_data.cpp b/src/mbgl/renderer/render_static_data.cpp index 6378ad99897..f7d9c18a785 100644 --- a/src/mbgl/renderer/render_static_data.cpp +++ b/src/mbgl/renderer/render_static_data.cpp @@ -50,15 +50,37 @@ static gfx::VertexVector heatmapTextureVertices() { } RenderStaticData::RenderStaticData(gfx::Context& context, float pixelRatio) - : programs(context, ProgramParameters { pixelRatio, false }) + : programs(context, ProgramParameters{pixelRatio, false}), + clippingMaskSegments(tileTriangleSegments()) #ifndef NDEBUG - , overdrawPrograms(context, ProgramParameters { pixelRatio, true }) + , + overdrawPrograms(context, ProgramParameters{pixelRatio, true}) #endif { - tileTriangleSegments.emplace_back(0, 0, 4, 6); - tileBorderSegments.emplace_back(0, 0, 4, 5); - rasterSegments.emplace_back(0, 0, 4, 6); - heatmapTextureSegments.emplace_back(0, 0, 4, 6); +} + +SegmentVector RenderStaticData::tileTriangleSegments() { + SegmentVector segments; + segments.emplace_back(0, 0, 4, 6); + return segments; +} + +SegmentVector RenderStaticData::tileBorderSegments() { + SegmentVector segments; + segments.emplace_back(0, 0, 4, 5); + return segments; +} + +SegmentVector RenderStaticData::rasterSegments() { + SegmentVector segments; + segments.emplace_back(0, 0, 4, 6); + return segments; +} + +SegmentVector RenderStaticData::heatmapTextureSegments() { + SegmentVector segments; + segments.emplace_back(0, 0, 4, 6); + return segments; } void RenderStaticData::upload(gfx::UploadPass& uploadPass) { diff --git a/src/mbgl/renderer/render_static_data.hpp b/src/mbgl/renderer/render_static_data.hpp index 6bf2c846f43..22b29387dbb 100644 --- a/src/mbgl/renderer/render_static_data.hpp +++ b/src/mbgl/renderer/render_static_data.hpp @@ -30,10 +30,10 @@ class RenderStaticData { optional quadTriangleIndexBuffer; optional tileBorderIndexBuffer; - SegmentVector tileTriangleSegments; - SegmentVector tileBorderSegments; - SegmentVector rasterSegments; - SegmentVector heatmapTextureSegments; + static SegmentVector tileTriangleSegments(); + static SegmentVector tileBorderSegments(); + static SegmentVector rasterSegments(); + static SegmentVector heatmapTextureSegments(); optional> depthRenderbuffer; bool has3D = false; @@ -42,6 +42,8 @@ class RenderStaticData { Programs programs; + const SegmentVector clippingMaskSegments; + #ifndef NDEBUG Programs overdrawPrograms; #endif diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp index 70db10fa087..ce5fef05b8e 100644 --- a/src/mbgl/renderer/render_tile.cpp +++ b/src/mbgl/renderer/render_tile.cpp @@ -147,81 +147,66 @@ void RenderTile::finishRender(PaintParameters& parameters) const { program.draw( parameters.context, *parameters.renderPass, - gfx::Lines { 4.0f * parameters.pixelRatio }, + gfx::Lines{4.0f * parameters.pixelRatio}, gfx::DepthMode::disabled(), gfx::StencilMode::disabled(), gfx::ColorMode::unblended(), gfx::CullFaceMode::disabled(), *debugBucket->indexBuffer, debugBucket->segments, - program.computeAllUniformValues( - DebugProgram::LayoutUniformValues { - uniforms::matrix::Value( matrix ), - uniforms::color::Value( Color::white() ) - }, - paintAttributeData, - properties, - parameters.state.getZoom() - ), + program.computeAllUniformValues(DebugProgram::LayoutUniformValues{uniforms::matrix::Value(matrix), + uniforms::color::Value(Color::white())}, + paintAttributeData, + properties, + parameters.state.getZoom()), allAttributeBindings, DebugProgram::TextureBindings{}, - "__debug/" + debugBucket->drawScopeID + "/text-outline" - ); + "text-outline"); program.draw( parameters.context, *parameters.renderPass, - gfx::Lines { 2.0f * parameters.pixelRatio }, + gfx::Lines{2.0f * parameters.pixelRatio}, gfx::DepthMode::disabled(), gfx::StencilMode::disabled(), gfx::ColorMode::unblended(), gfx::CullFaceMode::disabled(), *debugBucket->indexBuffer, debugBucket->segments, - program.computeAllUniformValues( - DebugProgram::LayoutUniformValues { - uniforms::matrix::Value( matrix ), - uniforms::color::Value( Color::black() ) - }, - paintAttributeData, - properties, - parameters.state.getZoom() - ), + program.computeAllUniformValues(DebugProgram::LayoutUniformValues{uniforms::matrix::Value(matrix), + uniforms::color::Value(Color::black())}, + paintAttributeData, + properties, + parameters.state.getZoom()), allAttributeBindings, DebugProgram::TextureBindings{}, - "__debug/" + debugBucket->drawScopeID + "/text" - ); + "text"); } if (parameters.debugOptions & MapDebugOptions::TileBorders) { assert(debugBucket); + if (debugBucket->tileBorderSegments.empty()) { + debugBucket->tileBorderSegments = parameters.staticData.tileBorderSegments(); + } parameters.programs.debug.draw( parameters.context, *parameters.renderPass, - gfx::LineStrip { 4.0f * parameters.pixelRatio }, + gfx::LineStrip{4.0f * parameters.pixelRatio}, gfx::DepthMode::disabled(), gfx::StencilMode::disabled(), gfx::ColorMode::unblended(), gfx::CullFaceMode::disabled(), *parameters.staticData.tileBorderIndexBuffer, - parameters.staticData.tileBorderSegments, - program.computeAllUniformValues( - DebugProgram::LayoutUniformValues { - uniforms::matrix::Value( matrix ), - uniforms::color::Value( Color::red() ) - }, - paintAttributeData, - properties, - parameters.state.getZoom() - ), + debugBucket->tileBorderSegments, + program.computeAllUniformValues(DebugProgram::LayoutUniformValues{uniforms::matrix::Value(matrix), + uniforms::color::Value(Color::red())}, + paintAttributeData, + properties, + parameters.state.getZoom()), program.computeAllAttributeBindings( - *parameters.staticData.tileVertexBuffer, - paintAttributeData, - properties - ), + *parameters.staticData.tileVertexBuffer, paintAttributeData, properties), DebugProgram::TextureBindings{}, - "__debug/" + debugBucket->drawScopeID - ); + "border"); } } diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp index 6d197df9dbe..30f1bbcee65 100644 --- a/src/mbgl/renderer/sources/render_image_source.cpp +++ b/src/mbgl/renderer/sources/render_image_source.cpp @@ -36,33 +36,25 @@ void ImageSourceRenderData::render(PaintParameters& parameters) const { auto& programInstance = parameters.programs.debug; for (auto matrix : matrices) { - programInstance.draw( - parameters.context, - *parameters.renderPass, - gfx::LineStrip { 4.0f * parameters.pixelRatio }, - gfx::DepthMode::disabled(), - gfx::StencilMode::disabled(), - gfx::ColorMode::unblended(), - gfx::CullFaceMode::disabled(), - *parameters.staticData.tileBorderIndexBuffer, - parameters.staticData.tileBorderSegments, - programInstance.computeAllUniformValues( - DebugProgram::LayoutUniformValues { - uniforms::matrix::Value( matrix ), - uniforms::color::Value( Color::red() ) - }, - paintAttributeData, - properties, - parameters.state.getZoom() - ), - programInstance.computeAllAttributeBindings( - *parameters.staticData.tileVertexBuffer, - paintAttributeData, - properties - ), - DebugProgram::TextureBindings{}, - "image" - ); + programInstance.draw(parameters.context, + *parameters.renderPass, + gfx::LineStrip{4.0f * parameters.pixelRatio}, + gfx::DepthMode::disabled(), + gfx::StencilMode::disabled(), + gfx::ColorMode::unblended(), + gfx::CullFaceMode::disabled(), + *parameters.staticData.tileBorderIndexBuffer, + parameters.staticData.tileBorderSegments(), + programInstance.computeAllUniformValues( + DebugProgram::LayoutUniformValues{uniforms::matrix::Value(matrix), + uniforms::color::Value(Color::red())}, + paintAttributeData, + properties, + parameters.state.getZoom()), + programInstance.computeAllAttributeBindings( + *parameters.staticData.tileVertexBuffer, paintAttributeData, properties), + DebugProgram::TextureBindings{}, + "image"); } } diff --git a/src/mbgl/util/id.cpp b/src/mbgl/util/id.cpp deleted file mode 100644 index 4486194de44..00000000000 --- a/src/mbgl/util/id.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include - -#include - -namespace mbgl { -namespace util { - -uint64_t nextID() { - static std::atomic GUID { 0 }; - return GUID++; -} - -} // namespace util -} // namespace mbgl diff --git a/src/mbgl/util/id.hpp b/src/mbgl/util/id.hpp deleted file mode 100644 index 12e23dfc2d9..00000000000 --- a/src/mbgl/util/id.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -namespace mbgl { -namespace util { - -uint64_t nextID(); - -} // namespace util -} // namespace mbgl From 480c7e56b10beda9ac372b27a4fcb3eaf0ff78fb Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Thu, 13 Feb 2020 19:05:25 +0200 Subject: [PATCH 2/3] [core] Update baselines --- metrics/binary-size/linux-clang8/metrics.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/binary-size/linux-clang8/metrics.json b/metrics/binary-size/linux-clang8/metrics.json index 4350e4ae361..067acd33062 100644 --- a/metrics/binary-size/linux-clang8/metrics.json +++ b/metrics/binary-size/linux-clang8/metrics.json @@ -16,4 +16,4 @@ 6470600 ] ] -} \ No newline at end of file +} From ce9e0e0934b294d0e9fa0702cc76d929f6006ac0 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Thu, 13 Feb 2020 21:53:16 +0200 Subject: [PATCH 3/3] [core] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c51124537f6..fb643dd222a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,10 @@ - [core] Fix potential visual artifact for line-dasharray ([#16202](https://github.com/mapbox/mapbox-gl-native/pull/16202)) +- Store gfx::DrawScope objects with associated render objects. ([#15395](https://github.com/mapbox/mapbox-gl-native/pull/15395)) + + We used some shared SegmentVectors, e.g. for drawing raster or background tiles. In longer running maps, this lead to resource accumulation. By storing the SegmentVectors and the contained gfx::DrawScope objects, we ensure that resources get released when the associated render objects vanish. + ### 🏁 Performance improvements - [core] Loading images to style optimization ([#16187](https://github.com/mapbox/mapbox-gl-native/pull/16187))