diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 1c339f335..e54245f88 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -159,6 +159,8 @@ void Renderer::Impl::render(const RenderTree& renderTree, // Tweakers are run in the upload pass so they can set up uniforms. orchestrator.visitLayerGroups( [&](LayerGroupBase& layerGroup) { layerGroup.runTweakers(renderTree, parameters); }); + orchestrator.visitDebugLayerGroups( + [&](LayerGroupBase& layerGroup) { layerGroup.runTweakers(renderTree, parameters); }); // Update the debug layer groups orchestrator.updateDebugLayerGroups(renderTree, parameters); @@ -324,7 +326,12 @@ void Renderer::Impl::render(const RenderTree& renderTree, { const auto debugGroup(parameters.renderPass->createDebugGroup("debug")); orchestrator.visitDebugLayerGroups([&](LayerGroupBase& layerGroup) { - visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { drawable.draw(parameters); }); + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { + for (const auto& tweaker : drawable.getTweakers()) { + tweaker->execute(drawable, parameters); + } + drawable.draw(parameters); + }); }); } }; diff --git a/src/mbgl/renderer/sources/render_tile_source.cpp b/src/mbgl/renderer/sources/render_tile_source.cpp index 55b19622b..a412f2536 100644 --- a/src/mbgl/renderer/sources/render_tile_source.cpp +++ b/src/mbgl/renderer/sources/render_tile_source.cpp @@ -19,6 +19,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #endif @@ -49,26 +55,59 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr return; } - // initialize auto& context = parameters.context; const auto renderPass = RenderPass::None; auto& shaders = *parameters.staticData.shaders; + + // initialize debug builder constexpr auto DebugShaderName = "DebugShader"; gfx::ShaderProgramBasePtr debugShader = context.getGenericShader(shaders, std::string(DebugShaderName)); if (!debugShader) { return; } - - // create a builder static const StringIdentity idVertexAttribName = stringIndexer().get("a_pos"); static const StringIdentity idDebugUBOName = stringIndexer().get("DebugUBO"); - std::unique_ptr builder = context.createDrawableBuilder("debug-builder"); - builder->setShader(debugShader); - builder->setRenderPass(renderPass); - builder->setEnableDepth(false); - builder->setColorMode(gfx::ColorMode::unblended()); - builder->setCullFaceMode(gfx::CullFaceMode::disabled()); - builder->setVertexAttrNameId(idVertexAttribName); + std::unique_ptr debugBuilder = [&]() -> std::unique_ptr { + auto builder = context.createDrawableBuilder("debug-builder"); + builder->setShader(debugShader); + builder->setRenderPass(renderPass); + builder->setEnableDepth(false); + builder->setColorMode(gfx::ColorMode::unblended()); + builder->setCullFaceMode(gfx::CullFaceMode::disabled()); + builder->setVertexAttrNameId(idVertexAttribName); + + return builder; + }(); + +#if MLN_RENDER_BACKEND_METAL + // initialize polyline builder + gfx::ShaderPtr polylineShader; + const auto createPolylineShader = [&]() -> gfx::ShaderPtr { + gfx::ShaderGroupPtr shaderGroup = shaders.getShaderGroup("LineShader"); + const mbgl::unordered_set propertiesAsUniforms{ + stringIndexer().get("a_color"), + stringIndexer().get("a_blur"), + stringIndexer().get("a_opacity"), + stringIndexer().get("a_gapwidth"), + stringIndexer().get("a_offset"), + stringIndexer().get("a_width"), + }; + return shaderGroup->getOrCreateShader(context, propertiesAsUniforms); + }; + + std::unique_ptr polylineBuilder; + const auto createPolylineBuilder = [&](gfx::ShaderPtr shader) -> std::unique_ptr { + std::unique_ptr builder = context.createDrawableBuilder("debug-polyline-builder"); + builder->setShader(std::static_pointer_cast(shader)); + builder->setRenderPass(renderPass); + builder->setEnableDepth(false); + builder->setColorMode(gfx::ColorMode::alphaBlended()); + builder->setCullFaceMode(gfx::CullFaceMode::disabled()); + builder->setVertexAttrNameId(idVertexAttribName); + + return builder; + }; +#endif // add or get the layer group for a debug type const auto addOrGetLayerGroupForType = [&debugLayerGroups, &context]( @@ -87,9 +126,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr // build a set of tiles to cover std::unordered_set newTiles; for (auto& tile : *renderTiles) { - if (tile.getNeedsRendering()) { - newTiles.insert(tile.getOverscaledTileID()); - } + newTiles.insert(tile.getOverscaledTileID()); } // create texture. to be reused for all the tiles of the debug layers @@ -118,7 +155,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr return updatedCount; }; - // function to add drawable + // function to add lines drawable const auto addDrawable = [&](TileLayerGroup* tileLayerGroup, const OverscaledTileID& tileID, const DebugUBO& debugUBO, @@ -132,14 +169,14 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr return v.a1; }); - builder->addVertices(verts, 0, verts.size()); - builder->setSegments(mode, indexes, segments.data(), segments.size()); + debugBuilder->addVertices(verts, 0, verts.size()); + debugBuilder->setSegments(mode, indexes, segments.data(), segments.size()); // texture - builder->setTexture(texture, samplerLocation.value()); + debugBuilder->setTexture(texture, samplerLocation.value()); // finish - builder->flush(); - for (auto& drawable : builder->clearDrawables()) { + debugBuilder->flush(); + for (auto& drawable : debugBuilder->clearDrawables()) { drawable->setTileID(tileID); auto& uniforms = drawable->mutableUniformBuffers(); uniforms.createOrUpdate(idDebugUBOName, &debugUBO, context); @@ -148,6 +185,112 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr } }; +#if MLN_RENDER_BACKEND_METAL + // function to add polylines drawable + const auto addPolylineDrawable = [&](TileLayerGroup* tileLayerGroup, const RenderTile& tile) { + class PolylineDrawableTweaker : public gfx::DrawableTweaker { + public: + PolylineDrawableTweaker(const shaders::LinePropertiesUBO& properties) + : linePropertiesUBO(properties) {} + ~PolylineDrawableTweaker() override = default; + + void init(gfx::Drawable&) override{}; + + void execute(gfx::Drawable& drawable, const PaintParameters& parameters) override { + if (!drawable.getTileID().has_value()) { + return; + } + + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + const auto zoom = parameters.state.getZoom(); + mat4 tileMatrix; + parameters.state.matrixFor(/*out*/ tileMatrix, tileID); + + const auto matrix = LayerTweaker::getTileMatrix( + tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, false); + + static const StringIdentity idLineUBOName = stringIndexer().get("LineUBO"); + const shaders::LineUBO lineUBO{ + /*matrix = */ util::cast(matrix), + /*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]}, + /*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, zoom), + /*device_pixel_ratio = */ parameters.pixelRatio}; + + static const StringIdentity idLinePropertiesUBOName = stringIndexer().get("LinePropertiesUBO"); + + static const StringIdentity idLineInterpolationUBOName = stringIndexer().get("LineInterpolationUBO"); + const shaders::LineInterpolationUBO lineInterpolationUBO{/*color_t =*/0.f, + /*blur_t =*/0.f, + /*opacity_t =*/0.f, + /*gapwidth_t =*/0.f, + /*offset_t =*/0.f, + /*width_t =*/0.f, + 0, + 0}; + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.createOrUpdate(idLineUBOName, &lineUBO, parameters.context); + uniforms.createOrUpdate(idLinePropertiesUBOName, &linePropertiesUBO, parameters.context); + uniforms.createOrUpdate(idLineInterpolationUBOName, &lineInterpolationUBO, parameters.context); + + static const StringIdentity idExpressionInputsUBOName = stringIndexer().get("ExpressionInputsUBO"); + const auto expressionUBO = LayerTweaker::buildExpressionUBO(zoom, parameters.frameCount); + uniforms.createOrUpdate(idExpressionInputsUBOName, &expressionUBO, parameters.context); + + static const StringIdentity idLinePermutationUBOName = stringIndexer().get("LinePermutationUBO"); + const shaders::LinePermutationUBO permutationUBO = { + /* .color = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .blur = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .opacity = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .gapwidth = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .offset = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .width = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .floorwidth = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .pattern_from = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .pattern_to = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .overdrawInspector = */ false, + /* .pad = */ 0, + 0, + 0, + 0}; + uniforms.createOrUpdate(idLinePermutationUBOName, &permutationUBO, parameters.context); + }; + + private: + shaders::LinePropertiesUBO linePropertiesUBO; + }; + + GeometryCoordinates coords{{0, 0}, {util::EXTENT, 0}, {util::EXTENT, util::EXTENT}, {0, util::EXTENT}, {0, 0}}; + gfx::PolylineGeneratorOptions options; + options.type = FeatureType::Polygon; + + if (!polylineShader) polylineShader = createPolylineShader(); + if (!polylineBuilder) { + polylineBuilder = createPolylineBuilder(polylineShader); + } + polylineBuilder->addPolyline(coords, options); + + // create line tweaker + const shaders::LinePropertiesUBO linePropertiesUBO{/*color*/ Color::red(), + /*blur*/ 0.f, + /*opacity*/ 1.f, + /*gapwidth*/ 0.f, + /*offset*/ 0.f, + /*width*/ 4.f, + 0, + 0, + 0}; + auto tweaker = std::make_shared(linePropertiesUBO); + + // finish + polylineBuilder->flush(); + for (auto& drawable : polylineBuilder->clearDrawables()) { + drawable->setTileID(tile.getOverscaledTileID()); + drawable->addTweaker(tweaker); + tileLayerGroup->addDrawable(renderPass, tile.getOverscaledTileID(), std::move(drawable)); + } + }; +#endif + // Timestamps or Parse Status if (parameters.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) { TileLayerGroup* outlineLayerGroup = static_cast( @@ -164,42 +307,40 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr // add new drawables and update existing ones for (auto& tile : *renderTiles) { - if (tile.getNeedsRendering()) { - const auto tileID = tile.getOverscaledTileID(); - const auto& debugBucket = tile.debugBucket; - if (!debugBucket) continue; + const auto tileID = tile.getOverscaledTileID(); + const auto& debugBucket = tile.debugBucket; + if (!debugBucket) continue; - const DebugUBO outlineUBO{/*matrix = */ util::cast(tile.matrix), - /*color = */ Color::white(), - /*overlay_scale = */ 1.0f, - 0, - 0, - 0}; - if (0 == updateDrawables(outlineLayerGroup, tileID, outlineUBO)) { - addDrawable(outlineLayerGroup, - tileID, - outlineUBO, - gfx::Lines(4.0f * parameters.pixelRatio), - debugBucket->vertices.vector(), - debugBucket->indices.vector(), - debugBucket->segments); - } + const DebugUBO outlineUBO{/*matrix = */ util::cast(tile.matrix), + /*color = */ Color::white(), + /*overlay_scale = */ 1.0f, + 0, + 0, + 0}; + if (0 == updateDrawables(outlineLayerGroup, tileID, outlineUBO)) { + addDrawable(outlineLayerGroup, + tileID, + outlineUBO, + gfx::Lines(4.0f * parameters.pixelRatio), + debugBucket->vertices.vector(), + debugBucket->indices.vector(), + debugBucket->segments); + } - const DebugUBO textUBO{/*matrix = */ util::cast(tile.matrix), - /*color = */ Color::black(), - /*overlay_scale = */ 1.0f, - 0, - 0, - 0}; - if (0 == updateDrawables(textLayerGroup, tileID, textUBO)) { - addDrawable(textLayerGroup, - tileID, - textUBO, - gfx::Lines(2.0f * parameters.pixelRatio), - debugBucket->vertices.vector(), - debugBucket->indices.vector(), - debugBucket->segments); - } + const DebugUBO textUBO{/*matrix = */ util::cast(tile.matrix), + /*color = */ Color::black(), + /*overlay_scale = */ 1.0f, + 0, + 0, + 0}; + if (0 == updateDrawables(textLayerGroup, tileID, textUBO) && tile.getNeedsRendering()) { + addDrawable(textLayerGroup, + tileID, + textUBO, + gfx::Lines(2.0f * parameters.pixelRatio), + debugBucket->vertices.vector(), + debugBucket->indices.vector(), + debugBucket->segments); } } } else { @@ -223,26 +364,28 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr auto indexes = RenderStaticData::tileLineStripIndices().vector(); auto segments = RenderStaticData::tileBorderSegments(); for (auto& tile : *renderTiles) { - if (tile.getNeedsRendering()) { - const auto tileID = tile.getOverscaledTileID(); - const auto& debugBucket = tile.debugBucket; - if (!debugBucket) continue; + const auto tileID = tile.getOverscaledTileID(); + const auto& debugBucket = tile.debugBucket; + if (!debugBucket) continue; - const DebugUBO debugUBO{/*matrix = */ util::cast(tile.matrix), - /*color = */ Color::red(), - /*overlay_scale = */ 1.0f, - 0, - 0, - 0}; - if (0 == updateDrawables(tileLayerGroup, tileID, debugUBO)) { - addDrawable(tileLayerGroup, - tileID, - debugUBO, - gfx::LineStrip(4.0f * parameters.pixelRatio), - vertices, - indexes, - segments); - } + const DebugUBO debugUBO{/*matrix = */ util::cast(tile.matrix), + /*color = */ Color::red(), + /*overlay_scale = */ 1.0f, + 0, + 0, + 0}; + if (0 == updateDrawables(tileLayerGroup, tileID, debugUBO) && tile.getNeedsRendering()) { +#if MLN_RENDER_BACKEND_METAL + addPolylineDrawable(tileLayerGroup, tile); +#else + addDrawable(tileLayerGroup, + tileID, + debugUBO, + gfx::LineStrip(4.0f * parameters.pixelRatio), + vertices, + indexes, + segments); +#endif } } } else {