From 08163713e239ab7756dc9bbe9b6e2c4986f168d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Tue, 16 Apr 2019 17:44:34 +0200 Subject: [core] change approach to stencil clipping to (almost) match JS --- src/mbgl/renderer/layers/render_circle_layer.cpp | 4 +- src/mbgl/renderer/layers/render_fill_layer.cpp | 8 +- src/mbgl/renderer/layers/render_heatmap_layer.cpp | 6 +- src/mbgl/renderer/layers/render_line_layer.cpp | 5 +- src/mbgl/renderer/paint_parameters.cpp | 100 +++++++++++++++++++-- src/mbgl/renderer/paint_parameters.hpp | 21 ++++- src/mbgl/renderer/render_layer.cpp | 1 + src/mbgl/renderer/render_tile.cpp | 6 +- src/mbgl/renderer/render_tile.hpp | 2 - src/mbgl/renderer/renderer_impl.cpp | 62 ++----------- .../sources/render_custom_geometry_source.cpp | 4 - .../renderer/sources/render_geojson_source.cpp | 4 - src/mbgl/renderer/sources/render_vector_source.cpp | 4 - 13 files changed, 130 insertions(+), 97 deletions(-) (limited to 'src/mbgl/renderer') diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index a0531afaed..e96dee0cf5 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -103,9 +103,7 @@ void RenderCircleLayer::render(PaintParameters& parameters, RenderSource*) { *parameters.renderPass, gfx::Triangles(), parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), - parameters.mapMode != MapMode::Continuous - ? parameters.stencilModeForClipping(tile.clip) - : gfx::StencilMode::disabled(), + gfx::StencilMode::disabled(), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), *bucket.indexBuffer, diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 85ae12b9d9..ec446136dc 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,7 @@ bool RenderFillLayer::hasCrossfade() const { void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) { if (unevaluated.get().isUndefined()) { + parameters.renderTileClippingMasks(renderTiles); for (const RenderTile& tile : renderTiles) { const LayerRenderData* renderData = tile.tile.getLayerRenderData(*baseImpl); if (!renderData) { @@ -115,7 +117,7 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) { *parameters.renderPass, drawMode, depthMode, - parameters.stencilModeForClipping(tile.clip), + parameters.stencilModeForClipping(tile.id), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), indexBuffer, @@ -157,6 +159,8 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) { return; } + parameters.renderTileClippingMasks(renderTiles); + for (const RenderTile& tile : renderTiles) { const LayerRenderData* renderData = tile.tile.getLayerRenderData(*baseImpl); if (!renderData) { @@ -209,7 +213,7 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) { *parameters.renderPass, drawMode, depthMode, - parameters.stencilModeForClipping(tile.clip), + parameters.stencilModeForClipping(tile.id), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), indexBuffer, diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index 1f3c179acc..48249002ea 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -98,10 +98,6 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) { const auto extrudeScale = tile.id.pixelsToTileUnits(1, parameters.state.getZoom()); - const auto stencilMode = parameters.mapMode != MapMode::Continuous - ? parameters.stencilModeForClipping(tile.clip) - : gfx::StencilMode::disabled(); - const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID()); auto& programInstance = parameters.programs.getHeatmapLayerPrograms().heatmap; @@ -129,7 +125,7 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) { *renderPass, gfx::Triangles(), parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), - stencilMode, + gfx::StencilMode::disabled(), gfx::ColorMode::additive(), gfx::CullFaceMode::disabled(), *bucket.indexBuffer, diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index 8fbe799f17..596a121249 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,8 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) { return; } + parameters.renderTileClippingMasks(renderTiles); + for (const RenderTile& tile : renderTiles) { const LayerRenderData* renderData = tile.tile.getLayerRenderData(*baseImpl); if (!renderData) { @@ -98,7 +101,7 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) { *parameters.renderPass, gfx::Triangles(), parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), - parameters.stencilModeForClipping(tile.clip), + parameters.stencilModeForClipping(tile.id), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), *bucket.indexBuffer, diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index 624deeec0a..e9f42d2579 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -1,8 +1,11 @@ #include #include #include +#include +#include #include #include +#include #include namespace mbgl { @@ -73,15 +76,94 @@ gfx::DepthMode PaintParameters::depthModeFor3D(gfx::DepthMaskType mask) const { return gfx::DepthMode { gfx::DepthFunctionType::LessEqual, mask, { 0.0, 1.0 } }; } -gfx::StencilMode PaintParameters::stencilModeForClipping(const ClipID& id) const { - return gfx::StencilMode { - gfx::StencilMode::Equal { static_cast(id.mask.to_ulong()) }, - static_cast(id.reference.to_ulong()), - 0, - gfx::StencilOpType::Keep, - gfx::StencilOpType::Keep, - gfx::StencilOpType::Replace - }; +void PaintParameters::clearStencil() { + nextStencilID = 1; + context.clearStencilBuffer(0b00000000); +} + +namespace { + +// Detects a difference in keys of renderTiles and tileClippingMaskIDs +bool tileIDsIdentical(const std::vector>& renderTiles, + const std::map& tileClippingMaskIDs) { + assert(std::is_sorted(renderTiles.begin(), renderTiles.end(), + [](const RenderTile& a, const RenderTile& b) { return a.id < b.id; })); + if (renderTiles.size() != tileClippingMaskIDs.size()) { + return false; + } + return std::equal(renderTiles.begin(), renderTiles.end(), tileClippingMaskIDs.begin(), + [](const RenderTile& a, const auto& b) { return a.id == b.first; }); +} + +} // namespace + +void PaintParameters::renderTileClippingMasks(const std::vector>& renderTiles) { + if (renderTiles.empty() || tileIDsIdentical(renderTiles, tileClippingMaskIDs)) { + // The current stencil mask is for this source already; no need to draw another one. + return; + } + + if (nextStencilID + renderTiles.size() > 256) { + // we'll run out of fresh IDs so we need to clear and start from scratch + clearStencil(); + } + + tileClippingMaskIDs.clear(); + + auto& program = staticData.programs.clippingMask; + const style::Properties<>::PossiblyEvaluated properties {}; + const ClippingMaskProgram::Binders paintAttributeData(properties, 0); + + for (const RenderTile& renderTile : 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" + ); + } +} + +gfx::StencilMode PaintParameters::stencilModeForClipping(const UnwrappedTileID& tileID) const { + auto it = tileClippingMaskIDs.find(tileID); + assert(it != tileClippingMaskIDs.end()); + const int32_t id = it != tileClippingMaskIDs.end() ? it->second : 0b00000000; + return gfx::StencilMode{ gfx::StencilMode::Equal{ 0b11111111 }, + id, + 0b00000000, + gfx::StencilOpType::Keep, + gfx::StencilOpType::Keep, + gfx::StencilOpType::Replace }; } gfx::ColorMode PaintParameters::colorModeForRenderPass() const { diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp index 523975c78c..1a576b6c9c 100644 --- a/src/mbgl/renderer/paint_parameters.hpp +++ b/src/mbgl/renderer/paint_parameters.hpp @@ -7,10 +7,11 @@ #include #include #include -#include #include #include +#include +#include namespace mbgl { @@ -21,6 +22,8 @@ class TransformState; class ImageManager; class LineAtlas; class UnwrappedTileID; +class RenderSource; +class RenderTile; namespace gfx { class Context; @@ -62,13 +65,11 @@ public: float pixelRatio; Placement::VariableOffsets variableOffsets; std::array pixelsToGLUnits; - algorithm::ClipIDGenerator clipIDGenerator; Programs& programs; gfx::DepthMode depthModeForSublayer(uint8_t n, gfx::DepthMaskType) const; gfx::DepthMode depthModeFor3D(gfx::DepthMaskType) const; - gfx::StencilMode stencilModeForClipping(const ClipID&) const; gfx::ColorMode colorModeForRenderPass() const; mat4 matrixForTile(const UnwrappedTileID&, bool aligned = false) const; @@ -77,10 +78,24 @@ public: mat4 alignedProjMatrix; mat4 nearClippedProjMatrix; + // Stencil handling +public: + void renderTileClippingMasks(const std::vector>&); + gfx::StencilMode stencilModeForClipping(const UnwrappedTileID&) const; + +private: + void clearStencil(); + + // This needs to be an ordered map so that we have the same order as the renderTiles. + std::map tileClippingMaskIDs; + int32_t nextStencilID = 1; + +public: int numSublayers = 3; uint32_t currentLayer; float depthRangeSize; const float depthEpsilon = 1.0f / (1 << 16); + float symbolFadeChange; }; diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp index 5868c38fbc..b7639f83fe 100644 --- a/src/mbgl/renderer/render_layer.cpp +++ b/src/mbgl/renderer/render_layer.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp index 5429536c3f..e175b761fe 100644 --- a/src/mbgl/renderer/render_tile.cpp +++ b/src/mbgl/renderer/render_tile.cpp @@ -101,7 +101,7 @@ void RenderTile::finishRender(PaintParameters& parameters) { *parameters.renderPass, gfx::Lines { 4.0f * parameters.pixelRatio }, gfx::DepthMode::disabled(), - parameters.stencilModeForClipping(clip), + gfx::StencilMode::disabled(), gfx::ColorMode::unblended(), gfx::CullFaceMode::disabled(), *tile.debugBucket->indexBuffer, @@ -125,7 +125,7 @@ void RenderTile::finishRender(PaintParameters& parameters) { *parameters.renderPass, gfx::Lines { 2.0f * parameters.pixelRatio }, gfx::DepthMode::disabled(), - parameters.stencilModeForClipping(clip), + gfx::StencilMode::disabled(), gfx::ColorMode::unblended(), gfx::CullFaceMode::disabled(), *tile.debugBucket->indexBuffer, @@ -152,7 +152,7 @@ void RenderTile::finishRender(PaintParameters& parameters) { *parameters.renderPass, gfx::LineStrip { 4.0f * parameters.pixelRatio }, gfx::DepthMode::disabled(), - parameters.stencilModeForClipping(clip), + gfx::StencilMode::disabled(), gfx::ColorMode::unblended(), gfx::CullFaceMode::disabled(), parameters.staticData.tileBorderIndexBuffer, diff --git a/src/mbgl/renderer/render_tile.hpp b/src/mbgl/renderer/render_tile.hpp index bfa695586c..ddfcaa8d4d 100644 --- a/src/mbgl/renderer/render_tile.hpp +++ b/src/mbgl/renderer/render_tile.hpp @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -24,7 +23,6 @@ public: UnwrappedTileID id; Tile& tile; - ClipID clip; mat4 matrix; mat4 nearClippedMatrix; bool used = false; diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 1b17324ccf..ecb26fa330 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -420,61 +420,6 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { parameters.renderPass = parameters.encoder->createRenderPass("main buffer", { parameters.backend.getDefaultRenderable(), color, 1, 0 }); } - // - CLIPPING MASKS ---------------------------------------------------------------------------- - // Draws the clipping masks to the stencil buffer. - { - const auto debugGroup(parameters.renderPass->createDebugGroup("clipping masks")); - - static const Properties<>::PossiblyEvaluated properties {}; - static const ClippingMaskProgram::Binders paintAttributeData(properties, 0); - - for (const auto& clipID : parameters.clipIDGenerator.getClipIDs()) { - auto& program = parameters.staticData.programs.clippingMask; - - program.draw( - parameters.context, - *parameters.renderPass, - gfx::Triangles(), - gfx::DepthMode::disabled(), - gfx::StencilMode { - gfx::StencilMode::Always(), - static_cast(clipID.second.reference.to_ulong()), - 0b11111111, - gfx::StencilOpType::Keep, - gfx::StencilOpType::Keep, - gfx::StencilOpType::Replace - }, - gfx::ColorMode::disabled(), - gfx::CullFaceMode::disabled(), - parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.tileTriangleSegments, - program.computeAllUniformValues( - ClippingMaskProgram::LayoutUniformValues { - uniforms::matrix::Value( parameters.matrixForTile(clipID.first) ), - }, - paintAttributeData, - properties, - parameters.state.getZoom() - ), - program.computeAllAttributeBindings( - parameters.staticData.tileVertexBuffer, - paintAttributeData, - properties - ), - ClippingMaskProgram::TextureBindings{}, - "clipping" - ); - } - } - -#if not defined(NDEBUG) - // Render tile clip boundaries, using stencil buffer to calculate fill color. - if (parameters.debugOptions & MapDebugOptions::StencilClip) { - parameters.context.visualizeStencilBuffer(); - return; - } -#endif - // Actually render the layers parameters.depthRangeSize = 1 - (renderItems.size() + 2) * parameters.numSublayers * parameters.depthEpsilon; @@ -530,8 +475,11 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { } #if not defined(NDEBUG) - // Render the depth buffer. - if (parameters.debugOptions & MapDebugOptions::DepthBuffer) { + if (parameters.debugOptions & MapDebugOptions::StencilClip) { + // Render tile clip boundaries, using stencil buffer to calculate fill color. + parameters.context.visualizeStencilBuffer(); + } else if (parameters.debugOptions & MapDebugOptions::DepthBuffer) { + // Render the depth buffer. parameters.context.visualizeDepthBuffer(parameters.depthRangeSize); } #endif diff --git a/src/mbgl/renderer/sources/render_custom_geometry_source.cpp b/src/mbgl/renderer/sources/render_custom_geometry_source.cpp index 30b6e65f24..8de79d8016 100644 --- a/src/mbgl/renderer/sources/render_custom_geometry_source.cpp +++ b/src/mbgl/renderer/sources/render_custom_geometry_source.cpp @@ -3,9 +3,6 @@ #include #include -#include -#include - namespace mbgl { using namespace style; @@ -51,7 +48,6 @@ void RenderCustomGeometrySource::update(Immutable baseImpl_ } void RenderCustomGeometrySource::startRender(PaintParameters& parameters) { - parameters.clipIDGenerator.update(tilePyramid.getRenderTiles()); tilePyramid.startRender(parameters); } diff --git a/src/mbgl/renderer/sources/render_geojson_source.cpp b/src/mbgl/renderer/sources/render_geojson_source.cpp index 332ea4d170..0234b97eca 100644 --- a/src/mbgl/renderer/sources/render_geojson_source.cpp +++ b/src/mbgl/renderer/sources/render_geojson_source.cpp @@ -4,9 +4,6 @@ #include #include -#include -#include - #include namespace mbgl { @@ -127,7 +124,6 @@ void RenderGeoJSONSource::update(Immutable baseImpl_, } void RenderGeoJSONSource::startRender(PaintParameters& parameters) { - parameters.clipIDGenerator.update(tilePyramid.getRenderTiles()); tilePyramid.startRender(parameters); } diff --git a/src/mbgl/renderer/sources/render_vector_source.cpp b/src/mbgl/renderer/sources/render_vector_source.cpp index efcd11094c..518692fc77 100644 --- a/src/mbgl/renderer/sources/render_vector_source.cpp +++ b/src/mbgl/renderer/sources/render_vector_source.cpp @@ -3,9 +3,6 @@ #include #include -#include -#include - namespace mbgl { using namespace style; @@ -61,7 +58,6 @@ void RenderVectorSource::update(Immutable baseImpl_, } void RenderVectorSource::startRender(PaintParameters& parameters) { - parameters.clipIDGenerator.update(tilePyramid.getRenderTiles()); tilePyramid.startRender(parameters); } -- cgit v1.2.1