Metal debug lines (#1888)
This commit is contained in:
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -19,6 +19,12 @@
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
#include <mbgl/tile/geojson_tile_data.hpp>
|
||||
#include <mbgl/gfx/polyline_generator.hpp>
|
||||
#include <mbgl/style/types.hpp>
|
||||
#include <mbgl/shaders/line_layer_ubo.hpp>
|
||||
#include <mbgl/gfx/drawable_tweaker.hpp>
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
|
||||
#include <unordered_set>
|
||||
#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<gfx::DrawableBuilder> 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<gfx::DrawableBuilder> debugBuilder = [&]() -> std::unique_ptr<gfx::DrawableBuilder> {
|
||||
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<StringIdentity> 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<gfx::DrawableBuilder> polylineBuilder;
|
||||
const auto createPolylineBuilder = [&](gfx::ShaderPtr shader) -> std::unique_ptr<gfx::DrawableBuilder> {
|
||||
std::unique_ptr<gfx::DrawableBuilder> builder = context.createDrawableBuilder("debug-polyline-builder");
|
||||
builder->setShader(std::static_pointer_cast<gfx::ShaderProgramBase>(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<OverscaledTileID> 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<float>(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<PolylineDrawableTweaker>(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<TileLayerGroup*>(
|
||||
@@ -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<float>(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<float>(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<float>(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<float>(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<float>(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<float>(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 {
|
||||
|
||||
Reference in New Issue
Block a user