diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index f67f55101..d913d7fce 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -108,6 +108,10 @@ public: bool getEnabled() const { return enabled; } void setEnabled(bool value) { enabled = value; } + /// Whether to do stenciling (based on the Tile ID) + bool getNeedsStencil() const { return needsStencil; } + void setNeedsStencil(bool value) { needsStencil = value; } + /// not used for anything yet DrawPriority getDrawPriority() const { return drawPriority; } void setDrawPriority(DrawPriority value) { drawPriority = value; } @@ -155,6 +159,7 @@ public: protected: bool enabled = true; + bool needsStencil = false; std::string name; util::SimpleIdentity uniqueID; gfx::ShaderProgramBasePtr shader; diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index 0f28cb52c..77ce6bc9b 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -84,6 +84,10 @@ public: float getLineWidth() const { return lineWidth; } void setLineWidth(float value) { lineWidth = value; } + /// Whether to do stenciling (based on the Tile ID) + bool getNeedsStencil() const { return needsStencil; } + void setNeedsStencil(bool value) { needsStencil = value; } + DepthMaskType getDepthType() const { return depthType; } void setDepthType(DepthMaskType value) { depthType = value; } @@ -156,6 +160,7 @@ protected: std::string vertexAttrName; std::string colorAttrName; mbgl::RenderPass renderPass; + bool needsStencil = false; float lineWidth = 1.0f; DrawPriority drawPriority = 0; int32_t subLayerIndex = 0; diff --git a/include/mbgl/gl/layer_group_gl.hpp b/include/mbgl/gl/layer_group_gl.hpp index fd7a54259..b44ba9f84 100644 --- a/include/mbgl/gl/layer_group_gl.hpp +++ b/include/mbgl/gl/layer_group_gl.hpp @@ -10,7 +10,7 @@ namespace gl { */ class TileLayerGroupGL : public TileLayerGroup { public: - TileLayerGroupGL(int32_t layerIndex, std::size_t initialCapacity); + TileLayerGroupGL(int32_t layerIndex, std::size_t initialCapacity, std::string name); ~TileLayerGroupGL() override {} void upload(gfx::UploadPass&) override; diff --git a/include/mbgl/renderer/layer_group.hpp b/include/mbgl/renderer/layer_group.hpp index eb3cbb400..7cddc03f3 100644 --- a/include/mbgl/renderer/layer_group.hpp +++ b/include/mbgl/renderer/layer_group.hpp @@ -6,6 +6,7 @@ #include #include +#include #include namespace mbgl { @@ -33,7 +34,7 @@ using LayerTweakerPtr = std::shared_ptr; */ class LayerGroup : public util::SimpleIdentifiable { protected: - LayerGroup(int32_t layerIndex); + LayerGroup(int32_t layerIndex, std::string name = std::string()); public: LayerGroup(const LayerGroup&) = delete; @@ -43,8 +44,14 @@ public: bool getEnabled() const { return enabled; } void setEnabled(bool value) { enabled = value; } + const std::string& getName() const { return name; } + void setName(std::string value) { name = std::move(value); } + int32_t getLayerIndex() const { return layerIndex; } + virtual std::size_t getDrawableCount() const = 0; + bool empty() const { return getDrawableCount() == 0; } + /// Called before starting each frame virtual void preRender(RenderOrchestrator&, PaintParameters&) {} /// Called during the upload pass @@ -71,6 +78,7 @@ protected: bool enabled = true; int32_t layerIndex; LayerTweakerPtr layerTweaker; + std::string name; }; /** @@ -78,12 +86,12 @@ protected: */ class TileLayerGroup : public LayerGroup { public: - TileLayerGroup(int32_t layerIndex, std::size_t initialCapacity); + TileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name); ~TileLayerGroup() override; void updateLayerIndex(int32_t newLayerIndex); - std::size_t getDrawableCount() const; + std::size_t getDrawableCount() const override; std::size_t getDrawableCount(mbgl::RenderPass, const OverscaledTileID&) const; std::vector removeDrawables(mbgl::RenderPass, const OverscaledTileID&); diff --git a/src/mbgl/gfx/context.hpp b/src/mbgl/gfx/context.hpp index 982ed9f2f..63f6bea0c 100644 --- a/src/mbgl/gfx/context.hpp +++ b/src/mbgl/gfx/context.hpp @@ -116,7 +116,9 @@ public: virtual gfx::ShaderProgramBasePtr getGenericShader(gfx::ShaderRegistry&, const std::string& name) = 0; /// Create a layer group implementation - virtual TileLayerGroupPtr createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity) = 0; + virtual TileLayerGroupPtr createTileLayerGroup(int32_t layerIndex, + std::size_t initialCapacity, + std::string name) = 0; /// Create a texture virtual Texture2DPtr createTexture2D() = 0; diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index 12cbb232f..b32bf4f52 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -42,6 +42,7 @@ void DrawableBuilder::flush() { if (!impl->vertices.empty()) { const auto& draw = getCurrentDrawable(/*createIfNone=*/true); draw->setLineWidth(static_cast(lineWidth)); + draw->setNeedsStencil(needsStencil); draw->setRenderPass(renderPass); draw->setDrawPriority(drawPriority); draw->setSubLayerIndex(subLayerIndex); diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 4c982936f..d4e4fdfb8 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -471,8 +471,8 @@ gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders return shaders.get(name); } -TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity) { - return std::make_shared(layerIndex, initialCapacity); +TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) { + return std::make_shared(layerIndex, initialCapacity, std::move(name)); } gfx::Texture2DPtr Context::createTexture2D() { diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 87d75a89e..ae3d4c4fa 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -109,7 +109,7 @@ public: gfx::ShaderProgramBasePtr getGenericShader(gfx::ShaderRegistry&, const std::string& name) override; - TileLayerGroupPtr createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity) override; + TileLayerGroupPtr createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) override; gfx::Texture2DPtr createTexture2D() override; diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index 4a80138c7..662185c37 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -41,10 +41,8 @@ void DrawableGL::draw(const PaintParameters& parameters) const { // force disable depth test for debugging // setDepthMode({gfx::DepthFunctionType::Always, gfx::DepthMaskType::ReadOnly, {0,1}}); - if (tileID) { - // Doesn't work until the clipping masks are generated - // parameters.stencilModeForClipping(tileID->toUnwrapped()); - context.setStencilMode(gfx::StencilMode::disabled()); + if (needsStencil && tileID) { + context.setStencilMode(parameters.stencilModeForClipping(tileID->toUnwrapped())); } else { context.setStencilMode(gfx::StencilMode::disabled()); } diff --git a/src/mbgl/gl/layer_group_gl.cpp b/src/mbgl/gl/layer_group_gl.cpp index a3b8bd75e..e48e5247f 100644 --- a/src/mbgl/gl/layer_group_gl.cpp +++ b/src/mbgl/gl/layer_group_gl.cpp @@ -12,8 +12,8 @@ namespace mbgl { namespace gl { -TileLayerGroupGL::TileLayerGroupGL(int32_t layerIndex_, std::size_t initialCapacity) - : TileLayerGroup(layerIndex_, initialCapacity) {} +TileLayerGroupGL::TileLayerGroupGL(int32_t layerIndex_, std::size_t initialCapacity, std::string name_) + : TileLayerGroup(layerIndex_, initialCapacity, std::move(name_)) {} void TileLayerGroupGL::upload(gfx::UploadPass& uploadPass) { if (!enabled) { @@ -45,6 +45,23 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) return; } + if (getDrawableCount()) { +#if !defined(NDEBUG) + const auto label = getName() + (getName().empty() ? "" : "-") + "tile-clip-masks"; + const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); +#endif + + // Collect the tile IDs relevant to stenciling and update the stencil buffer, if necessary. + std::set tileIDs; + observeDrawables([&](const gfx::Drawable& drawable) { + if (drawable.getEnabled() && drawable.getNeedsStencil() && drawable.getTileID() && + drawable.hasRenderPass(parameters.pass)) { + tileIDs.emplace(drawable.getTileID()->toUnwrapped()); + } + }); + parameters.renderTileClippingMasks(tileIDs); + } + observeDrawables([&](gfx::Drawable& drawable) { if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) { return; diff --git a/src/mbgl/renderer/layer_group.cpp b/src/mbgl/renderer/layer_group.cpp index fea92122d..a3cd5f290 100644 --- a/src/mbgl/renderer/layer_group.cpp +++ b/src/mbgl/renderer/layer_group.cpp @@ -29,11 +29,12 @@ struct TileLayerGroup::Impl { TileMap tileDrawables; }; -LayerGroup::LayerGroup(int32_t layerIndex_) - : layerIndex(layerIndex_) {} +LayerGroup::LayerGroup(int32_t layerIndex_, std::string name_) + : layerIndex(layerIndex_), + name(std::move(name_)) {} -TileLayerGroup::TileLayerGroup(int32_t layerIndex_, std::size_t initialCapacity) - : LayerGroup(layerIndex_), +TileLayerGroup::TileLayerGroup(int32_t layerIndex_, std::size_t initialCapacity, std::string name_) + : LayerGroup(layerIndex_, std::move(name_)), impl(std::make_unique(initialCapacity)) {} TileLayerGroup::~TileLayerGroup() {} diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.cpp b/src/mbgl/renderer/layers/background_layer_tweaker.cpp index 0465c4365..d69b1f103 100644 --- a/src/mbgl/renderer/layers/background_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/background_layer_tweaker.cpp @@ -54,6 +54,16 @@ static constexpr std::string_view BackgroundLayerUBOName = "BackgroundLayerUBO"; void BackgroundLayerTweaker::execute(LayerGroup& layerGroup, const RenderTree&, const PaintParameters& parameters) { const auto& state = parameters.state; auto& context = parameters.context; + + if (layerGroup.empty()) { + return; + } + +#if defined(DEBUG) + const auto label = layerGroup.getName() + "-update-uniforms"; + const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); +#endif + const auto& evaluated = static_cast(*evaluatedProperties).evaluated; const auto& crossfade = static_cast(*evaluatedProperties).crossfade; const bool hasPattern = !evaluated.get().to.empty(); diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp index 477638e3a..201d744da 100644 --- a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp @@ -57,6 +57,15 @@ void CircleLayerTweaker::execute(LayerGroup& layerGroup, const PaintParameters& parameters) { const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + if (layerGroup.empty()) { + return; + } + +#if !defined(NDEBUG) + const auto label = layerGroup.getName() + "-update-uniforms"; + const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); +#endif + CirclePaintParamsUBO paintParamsUBO; paintParamsUBO.camera_to_center_distance = parameters.state.getCameraToCenterDistance(); paintParamsUBO.device_pixel_ratio = parameters.pixelRatio; diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp index 9d7cce80d..25718df08 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp @@ -60,6 +60,15 @@ void FillLayerTweaker::execute(LayerGroup& layerGroup, const auto& evaluated = props.evaluated; const auto& crossfade = props.crossfade; + if (layerGroup.empty()) { + return; + } + +#if !defined(NDEBUG) + const auto label = layerGroup.getName() + "-update-uniforms"; + const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); +#endif + layerGroup.observeDrawables([&](gfx::Drawable& drawable) { if (!drawable.getTileID()) { return; diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index 6deeb6046..3f08a1404 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -250,7 +250,7 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders, } if (!tileLayerGroup) { - tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64); + tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID()); if (!tileLayerGroup) { return; } diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index eaf51d900..c617aa023 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -272,7 +272,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, // Set up a layer group if (!tileLayerGroup) { - tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64); + tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID()); if (!tileLayerGroup) { return; } diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index f5479a852..46bb828aa 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -293,7 +293,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, // Set up a layer group if (!tileLayerGroup) { - tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64); + tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID()); if (!tileLayerGroup) { return; } @@ -339,6 +339,12 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } }; + const auto commonInit = [](gfx::DrawableBuilder& builder) { + builder.setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None); + builder.setCullFaceMode(gfx::CullFaceMode::disabled()); + builder.setNeedsStencil(true); + }; + for (const auto renderPass : {RenderPass::Opaque, RenderPass::Translucent}) { if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) { continue; @@ -355,6 +361,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, }); constexpr auto samplerLocation = 0; + const auto layerPrefix = getID() + "/"; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -454,34 +461,30 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } if (doFill && !fillBuilder && fillShader) { - fillBuilder = context.createDrawableBuilder("fill"); - fillBuilder->setShader(fillShader); - fillBuilder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None); - fillBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite + if (auto builder = context.createDrawableBuilder(layerPrefix + "fill")) { + commonInit(*builder); + builder->setShader(fillShader); + builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite : gfx::DepthMaskType::ReadOnly); - fillBuilder->setCullFaceMode(gfx::CullFaceMode::disabled()); + builder->setSubLayerIndex(0); + fillBuilder = std::move(builder); + } } if (doOutline && !outlineBuilder && outlineShader) { - outlineBuilder = context.createDrawableBuilder("fill-outline"); - outlineBuilder->setShader(outlineShader); - outlineBuilder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None); - outlineBuilder->setLineWidth(2.0f); - outlineBuilder->setDepthType(gfx::DepthMaskType::ReadOnly); - outlineBuilder->setCullFaceMode(gfx::CullFaceMode::disabled()); - outlineBuilder->setSubLayerIndex(unevaluated.get().isUndefined() ? 2 : 0); - } - - if (fillBuilder) { - fillBuilder->setRenderPass(renderPass); - fillBuilder->setVertexAttributes(fillVertexAttrs); - } - if (outlineBuilder) { - outlineBuilder->setRenderPass(renderPass); - outlineBuilder->setVertexAttributes(outlineVertexAttrs); + if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-outline")) { + commonInit(*builder); + builder->setShader(outlineShader); + builder->setLineWidth(2.0f); + builder->setDepthType(gfx::DepthMaskType::ReadOnly); + builder->setSubLayerIndex(unevaluated.get().isUndefined() ? 2 : 0); + outlineBuilder = std::move(builder); + } } if (fillBuilder) { buildVertices(); + fillBuilder->setRenderPass(renderPass); + fillBuilder->setVertexAttributes(fillVertexAttrs); fillBuilder->addVertices(rawVerts, 0, rawVerts.size()); fillBuilder->setSegments( gfx::Triangles(), @@ -491,6 +494,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } if (outlineBuilder) { buildVertices(); + outlineBuilder->setRenderPass(renderPass); + outlineBuilder->setVertexAttributes(outlineVertexAttrs); outlineBuilder->addVertices(rawVerts, 0, rawVerts.size()); outlineBuilder->setSegments( gfx::Lines(2), @@ -547,40 +552,35 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, // } if (!patternBuilder && patternShader) { - patternBuilder = context.createDrawableBuilder("fill-pattern"); - patternBuilder->setShader(fillShader); - patternBuilder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None); - patternBuilder->setDepthType(gfx::DepthMaskType::ReadWrite); - patternBuilder->setCullFaceMode(gfx::CullFaceMode::disabled()); - patternBuilder->setSubLayerIndex(1); - if (auto& tex = tile.getIconAtlasTexture()) { - patternBuilder->setTexture(tex, samplerLocation); + if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-pattern")) { + commonInit(*builder); + builder->setShader(fillShader); + builder->setDepthType(gfx::DepthMaskType::ReadWrite); + builder->setSubLayerIndex(1); + if (auto& tex = tile.getIconAtlasTexture()) { + builder->setTexture(tex, samplerLocation); + } + patternBuilder = std::move(builder); } } if (doOutline && !outlinePatternBuilder && outlinePatternShader) { - outlinePatternBuilder = context.createDrawableBuilder("fill-outline-pattern"); - outlinePatternBuilder->setShader(outlineShader); - outlinePatternBuilder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None); - outlinePatternBuilder->setLineWidth(2.0f); - outlinePatternBuilder->setDepthType(gfx::DepthMaskType::ReadOnly); - outlinePatternBuilder->setCullFaceMode(gfx::CullFaceMode::disabled()); - outlinePatternBuilder->setSubLayerIndex(2); - if (auto& tex = tile.getIconAtlasTexture()) { - patternBuilder->setTexture(tex, samplerLocation); + if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-outline-pattern")) { + commonInit(*builder); + builder->setShader(outlineShader); + builder->setLineWidth(2.0f); + builder->setDepthType(gfx::DepthMaskType::ReadOnly); + builder->setSubLayerIndex(2); + if (auto& tex = tile.getIconAtlasTexture()) { + builder->setTexture(tex, samplerLocation); + } + outlinePatternBuilder = std::move(builder); } } - if (patternBuilder) { - patternBuilder->setRenderPass(renderPass); - patternBuilder->setVertexAttributes(fillVertexAttrs); - } - if (outlinePatternBuilder) { - outlinePatternBuilder->setRenderPass(renderPass); - outlinePatternBuilder->setVertexAttributes(outlineVertexAttrs); - } - if (patternBuilder) { buildVertices(); + patternBuilder->setRenderPass(renderPass); + patternBuilder->setVertexAttributes(fillVertexAttrs); patternBuilder->addVertices(rawVerts, 0, rawVerts.size()); patternBuilder->setSegments( gfx::Triangles(), @@ -590,6 +590,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } if (outlinePatternBuilder) { buildVertices(); + outlinePatternBuilder->setRenderPass(renderPass); + outlinePatternBuilder->setVertexAttributes(outlineVertexAttrs); outlinePatternBuilder->addVertices(rawVerts, 0, rawVerts.size()); outlinePatternBuilder->setSegments( gfx::Lines(2), @@ -597,8 +599,6 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, reinterpret_cast>&>(bucket.lineSegments)); finish(*outlinePatternBuilder, renderPass, tileID); } - - // checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); } } } diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index ddc43b4bc..8ebe8eea8 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -92,29 +92,44 @@ void PaintParameters::clearStencil() { namespace { // Detects a difference in keys of renderTiles and tileClippingMaskIDs -bool tileIDsIdentical(const RenderTiles& renderTiles, const std::map& tileClippingMaskIDs) { - assert(renderTiles); - assert(std::is_sorted(renderTiles->begin(), renderTiles->end(), [](const RenderTile& a, const RenderTile& b) { - return a.id < b.id; - })); - if (renderTiles->size() != tileClippingMaskIDs.size()) { +template +bool tileIDsIdentical(TIter beg, + TIter end, + std::function f, + const std::map& idMap) { + if (static_cast(std::distance(beg, end)) != idMap.size()) { return false; } - return std::equal( - renderTiles->begin(), renderTiles->end(), tileClippingMaskIDs.begin(), [](const RenderTile& a, const auto& b) { - return a.id == b.first; - }); + assert(std::is_sorted(beg, end, [&f](const auto& a, const auto& b) { return f(a) < f(b); })); + return std::equal(beg, end, idMap.cbegin(), [&f](const auto& ii, const auto& pair) { return f(ii) == pair.first; }); } } // namespace +void PaintParameters::renderTileClippingMasks(const std::set& tileIDs) { + renderTileClippingMasks( + tileIDs.cbegin(), tileIDs.cend(), [](const UnwrappedTileID& ii) -> const UnwrappedTileID& { return ii; }); +} + void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) { - if (!renderTiles || renderTiles->empty() || tileIDsIdentical(renderTiles, tileClippingMaskIDs)) { + renderTileClippingMasks((*renderTiles).cbegin(), + (*renderTiles).cend(), + [](const std::reference_wrapper& ii) -> const UnwrappedTileID& { + const RenderTile& tile = ii.get(); + return tile.id; + }); +} + +template +void PaintParameters::renderTileClippingMasks( + TIter beg, TIter end, std::function::value_type&)> f) { + if (tileIDsIdentical(beg, end, f, tileClippingMaskIDs)) { // The current stencil mask is for this source already; no need to draw another one. return; } - if (nextStencilID + renderTiles->size() > 256) { + const auto count = std::distance(beg, end); + if (nextStencilID + count > maxStencilValue) { // we'll run out of fresh IDs so we need to clear and start from scratch clearStencil(); } @@ -129,9 +144,11 @@ void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) { const style::Properties<>::PossiblyEvaluated properties{}; const ClippingMaskProgram::Binders paintAttributeData(properties, 0); - for (const RenderTile& renderTile : *renderTiles) { + for (auto i = beg; i != end; ++i) { + const auto& tileID = f(*i); + const int32_t stencilID = nextStencilID++; - tileClippingMaskIDs.emplace(renderTile.id, stencilID); + tileClippingMaskIDs.emplace(tileID, stencilID); program->draw(context, *renderPass, @@ -149,7 +166,7 @@ void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) { staticData.clippingMaskSegments, ClippingMaskProgram::computeAllUniformValues( ClippingMaskProgram::LayoutUniformValues{ - uniforms::matrix::Value(matrixForTile(renderTile.id)), + uniforms::matrix::Value(matrixForTile(tileID)), }, paintAttributeData, properties, @@ -174,7 +191,7 @@ gfx::StencilMode PaintParameters::stencilModeForClipping(const UnwrappedTileID& } gfx::StencilMode PaintParameters::stencilModeFor3D() { - if (nextStencilID + 1 > 256) { + if (nextStencilID + 1 > maxStencilValue) { clearStencil(); } @@ -193,7 +210,7 @@ gfx::StencilMode PaintParameters::stencilModeFor3D() { gfx::ColorMode PaintParameters::colorModeForRenderPass() const { if (debugOptions & MapDebugOptions::Overdraw) { - const float overdraw = 1.0f / 8.0f; + constexpr float overdraw = 1.0f / 8.0f; return gfx::ColorMode{ gfx::ColorMode::Add{gfx::ColorBlendFactorType::ConstantColor, gfx::ColorBlendFactorType::One}, Color{overdraw, overdraw, overdraw, 0.0f}, diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp index 802b53407..1cbdfcd61 100644 --- a/src/mbgl/renderer/paint_parameters.hpp +++ b/src/mbgl/renderer/paint_parameters.hpp @@ -11,7 +11,10 @@ #include #include +#include +#include #include +#include #include namespace mbgl { @@ -92,12 +95,18 @@ public: // Stencil handling public: void renderTileClippingMasks(const RenderTiles&); + void renderTileClippingMasks(const std::set&); + gfx::StencilMode stencilModeForClipping(const UnwrappedTileID&) const; gfx::StencilMode stencilModeFor3D(); private: void clearStencil(); + template + void renderTileClippingMasks( + TIter beg, TIter end, std::function::value_type&)>); + // This needs to be an ordered map so that we have the same order as the renderTiles. std::map tileClippingMaskIDs; int32_t nextStencilID = 1; @@ -106,7 +115,8 @@ public: int numSublayers = 3; uint32_t currentLayer; float depthRangeSize; - const float depthEpsilon = 1.0f / (1 << 16); + static constexpr float depthEpsilon = 1.0f / (1 << 16); + static constexpr int maxStencilValue = 255; uint32_t opaquePassCutoff = 0; float symbolFadeChange; };