Skip to content

Commit

Permalink
rework to deal with ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
TimSylvester committed Aug 16, 2024
1 parent 60951e0 commit 5b1b35b
Show file tree
Hide file tree
Showing 8 changed files with 234 additions and 173 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,7 @@ list(APPEND SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile_cache.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile_cache.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile_diff.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile_diff.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile_id_hash.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile_id_io.cpp
Expand Down Expand Up @@ -1562,4 +1563,4 @@ endif()

add_subdirectory(${PROJECT_SOURCE_DIR}/test)
add_subdirectory(${PROJECT_SOURCE_DIR}/benchmark)
add_subdirectory(${PROJECT_SOURCE_DIR}/render-test)
add_subdirectory(${PROJECT_SOURCE_DIR}/render-test)
1 change: 1 addition & 0 deletions bazel/core.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ MLN_CORE_SOURCE = [
"src/mbgl/tile/tile.hpp",
"src/mbgl/tile/tile_cache.cpp",
"src/mbgl/tile/tile_cache.hpp",
"src/mbgl/tile/tile_diff.cpp",
"src/mbgl/tile/tile_diff.hpp",
"src/mbgl/tile/tile_id_hash.cpp",
"src/mbgl/tile/tile_id_io.cpp",
Expand Down
151 changes: 66 additions & 85 deletions src/mbgl/renderer/layers/render_fill_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
#include <mbgl/shaders/shader_program_base.hpp>
#endif

#define _LIBCPP_ENABLE_EXPERIMENTAL
#include <ranges>

namespace mbgl {

using namespace style;
Expand Down Expand Up @@ -296,6 +299,18 @@ bool RenderFillLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeo

#if MLN_DRAWABLE_RENDERER

namespace {

// Setup that's the same for all drawables
void commonInit(gfx::DrawableBuilder& builder) {
builder.setRenderPass(RenderPass::Translucent);
builder.setColorMode(gfx::ColorMode::alphaBlended());
builder.setCullFaceMode(gfx::CullFaceMode::disabled());
builder.setEnableStencil(true);
}

} // namespace

void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
gfx::Context& context,
const TransformState&,
Expand Down Expand Up @@ -353,11 +368,6 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
const auto layerPrefix = getID() + "/";
constexpr auto renderPass = RenderPass::Translucent;

const auto commonInit = [&](gfx::DrawableBuilder& builder) {
builder.setCullFaceMode(gfx::CullFaceMode::disabled());
builder.setEnableStencil(true);
};

// Remove drawables for removed tiles
for (const auto& tileID : renderTileDiff->removed) {
removeTile(renderPass, tileID);
Expand All @@ -367,23 +377,41 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,

StringIDSetsPair propertiesAsUniforms;

// Update tiles that weren't added or removed
std::vector<OverscaledTileID> resetTileIDs;
for (const auto& tileID : renderTileDiff->remainder) {
const auto tileRef = getRenderTile(tileID);
if (!tileRef) {
assert(false);
continue;
const auto buildVertexAttrs = [&](FillBucket& bucket,
const FillProgram::Binders& binders,
const FillPaintProperties::PossiblyEvaluated& evaluated) {
propertiesAsUniforms.first.clear();
propertiesAsUniforms.second.clear();

// `Fill*Program` all use `style::FillPaintProperties`
// TODO: Only rebuild the vertex attributes when something has changed.
// TODO: Can we update them in-place instead of replacing?
auto vertexAttrs = context.createVertexAttributeArray();
vertexAttrs->readDataDrivenPaintProperties<FillColor, FillOpacity, FillOutlineColor, FillPattern>(
binders, evaluated, propertiesAsUniforms, idFillColorVertexAttribute);

if (const auto& attr = vertexAttrs->set(idFillPosVertexAttribute)) {
attr->setSharedRawData(bucket.sharedVertices,
offsetof(FillLayoutVertex, a1),
/*vertexOffset=*/0,
sizeof(FillLayoutVertex),
gfx::AttributeDataType::Short2);
}
const RenderTile& tile = tileRef->get();
return vertexAttrs;
};

// Update tiles that weren't added or removed
using RenderTileRefVec = std::vector<RenderTiles::element_type::value_type>;
RenderTileRefVec resetTileIDs;
for (const RenderTile& tile : renderTileDiff->remainder) {
const auto& tileID = tile.getOverscaledTileID();
const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass);
if (!renderData || !renderData->bucket || !renderData->bucket->hasData()) {
removeTile(renderPass, tileID);

if (renderData && !renderData->bucket) {
// We'll need to treat this tile as an add
resetTileIDs.push_back(tileID);
resetTileIDs.push_back(tile);
}
continue;
}
Expand All @@ -396,53 +424,43 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
removeTile(renderPass, tileID);

// We'll need to treat this tile as an add
resetTileIDs.push_back(tileID);
resetTileIDs.push_back(tile);
continue;
}
setRenderTileBucketID(tileID, bucket.getID());
}

// Create drawables for new tiles
const auto newTile = [&](const OverscaledTileID& tileID) {
const auto tileRef = getRenderTile(tileID);
if (!tileRef) {
assert(false);
return;
}
const RenderTile& tile = tileRef->get();

const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass);
if (!renderData || !renderData->bucket || !renderData->bucket->hasData()) {
return;
auto updateExisting = [&](gfx::Drawable& drawable) {
if (drawable.getLayerTweaker() != layerTweaker) {
// This drawable was produced on a previous style/bucket, and should not be updated.
return false;
}
auto& binders = bucket.paintPropertyBinders.at(getID());
const auto& evaluated = getEvaluated<FillLayerProperties>(renderData->layerProperties);
drawable.setVertexAttributes(buildVertexAttrs(bucket, binders, evaluated));
return true;
};
if (updateTile(renderPass, tileID, std::move(updateExisting))) {
// Existing drawable was updated
} else {
// Existing drawable is obsolete, build a new one
resetTileIDs.push_back(tile);
}
}

auto& bucket = static_cast<FillBucket&>(*renderData->bucket);
setRenderTileBucketID(tileID, bucket.getID());
};
// With C++20 we can chain iterator ranges and use `for(:)`
std::for_each(renderTileDiff->added.begin(), renderTileDiff->added.end(), newTile);
std::for_each(resetTileIDs.begin(), resetTileIDs.end(), newTile);

for (const RenderTile& tile : *renderTiles) {
// Create drawables for tiles that are new or need to be re-created
for (const RenderTile& tile : std::ranges::join_view(std::array<std::ranges::ref_view<RenderTileRefVec>, 2>{
std::views::all(renderTileDiff->added), std::views::all(resetTileIDs)})) {
const auto& tileID = tile.getOverscaledTileID();

const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass);
if (!renderData || !renderData->bucket || !renderData->bucket->hasData()) {
removeTile(renderPass, tileID);
continue;
return;
}

const auto& evaluated = getEvaluated<FillLayerProperties>(renderData->layerProperties);
auto& bucket = static_cast<FillBucket&>(*renderData->bucket);
auto& binders = bucket.paintPropertyBinders.at(getID());

const auto prevBucketID = getRenderTileBucketID(tileID);
if (prevBucketID != util::SimpleIdentity::Empty && prevBucketID != bucket.getID()) {
// This tile was previously set up from a different bucket, drop and re-create any drawables for it.
removeTile(renderPass, tileID);
}
setRenderTileBucketID(tileID, bucket.getID());

const auto& evaluated = getEvaluated<FillLayerProperties>(renderData->layerProperties);

gfx::DrawableTweakerPtr atlasTweaker;
auto getAtlasTweaker = [&]() {
if (!atlasTweaker) {
Expand All @@ -461,37 +479,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
return atlasTweaker;
};

propertiesAsUniforms.first.clear();
propertiesAsUniforms.second.clear();

// `Fill*Program` all use `style::FillPaintProperties`
// TODO: Only rebuild the vertex attributes when something has changed.
// TODO: Can we update them in-place instead of replacing?
auto vertexAttrs = context.createVertexAttributeArray();
vertexAttrs->readDataDrivenPaintProperties<FillColor, FillOpacity, FillOutlineColor, FillPattern>(
binders, evaluated, propertiesAsUniforms, idFillColorVertexAttribute);

const auto vertexCount = bucket.vertices.elements();
if (const auto& attr = vertexAttrs->set(idFillPosVertexAttribute)) {
attr->setSharedRawData(bucket.sharedVertices,
offsetof(FillLayoutVertex, a1),
/*vertexOffset=*/0,
sizeof(FillLayoutVertex),
gfx::AttributeDataType::Short2);
}

// If we already have drawables for this tile, update them.
auto updateExisting = [&](gfx::Drawable& drawable) {
if (drawable.getLayerTweaker() != layerTweaker) {
// This drawable was produced on a previous style/bucket, and should not be updated.
return false;
}
drawable.setVertexAttributes(vertexAttrs);
return true;
};
if (updateTile(renderPass, tileID, std::move(updateExisting))) {
continue;
}
auto vertexAttrs = buildVertexAttrs(bucket, binders, evaluated);

const auto addDrawable = [&](std::unique_ptr<gfx::Drawable> drawable, FillVariant type) {
drawable->setTileID(tileID);
Expand Down Expand Up @@ -577,9 +566,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,

commonInit(*builder);
builder->setDepthType(opaque ? gfx::DepthMaskType::ReadWrite : gfx::DepthMaskType::ReadOnly);
builder->setColorMode(gfx::ColorMode::alphaBlended());
builder->setSubLayerIndex(1);
builder->setRenderPass(renderPass);
fillBuilder = std::move(builder);
}
}
Expand All @@ -589,8 +576,6 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
builder->setDepthType(gfx::DepthMaskType::ReadOnly);
builder->setLineWidth(2.0f);
builder->setSubLayerIndex(unevaluated.get<FillOutlineColor>().isUndefined() ? 2 : 0);
builder->setColorMode(gfx::ColorMode::alphaBlended());
builder->setRenderPass(RenderPass::Translucent);
outlineBuilder = std::move(builder);
}
}
Expand Down Expand Up @@ -678,9 +663,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
commonInit(*builder);
builder->setShader(fillShader);
builder->setDepthType(gfx::DepthMaskType::ReadWrite);
builder->setColorMode(gfx::ColorMode::alphaBlended());
builder->setSubLayerIndex(1);
builder->setRenderPass(RenderPass::Translucent);
patternBuilder = std::move(builder);
}
}
Expand All @@ -690,9 +673,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
builder->setShader(outlineShader);
builder->setLineWidth(2.0f);
builder->setDepthType(gfx::DepthMaskType::ReadOnly);
builder->setColorMode(gfx::ColorMode::alphaBlended());
builder->setSubLayerIndex(2);
builder->setRenderPass(RenderPass::Translucent);
outlinePatternBuilder = std::move(builder);
}
}
Expand Down
16 changes: 7 additions & 9 deletions src/mbgl/renderer/sources/render_tile_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ RenderTileSource::RenderTileSource(Immutable<style::Source::Impl> impl_, const T
: RenderSource(std::move(impl_)),
tilePyramid(threadPool_),
renderTiles(makeMutable<std::vector<RenderTile>>()),
previousRenderTiles(makeMutable<std::vector<RenderTile>>()) {
previousRenderTiles(std::make_shared<RenderTiles::element_type>()) {
tilePyramid.setObserver(this);
}

Expand All @@ -407,18 +407,18 @@ void RenderTileSource::prepare(const SourcePrepareParameters& parameters) {
MLN_TRACE_FUNC()
MLN_ZONE_STR(baseImpl->id)
bearing = static_cast<float>(parameters.transform.state.getBearing());
filteredRenderTiles = nullptr;
renderTilesSortedByY = nullptr;

auto tiles = makeMutable<std::vector<RenderTile>>();
tiles->reserve(tilePyramid.getRenderedTiles().size());
for (auto& entry : tilePyramid.getRenderedTiles()) {
tiles->emplace_back(entry.first, entry.second);
for (auto& [tileID, tileRef] : tilePyramid.getRenderedTiles()) {
tiles->emplace_back(tileID, tileRef);
tiles->back().prepare(parameters);
}
featureState.coalesceChanges(*tiles);

renderTileDiff.reset();
previousRenderTiles = std::move(renderTiles);
renderTilesSortedByY.reset();
previousRenderTiles = getRenderTiles();
renderTiles = std::move(tiles);
}

Expand Down Expand Up @@ -446,9 +446,7 @@ RenderTiles RenderTileSource::getRenderTiles() const {

std::shared_ptr<TileDifference> RenderTileSource::getRenderTileDiff() const {
if (!renderTileDiff) {
const auto tiles = getRenderTiles();
renderTileDiff = std::make_shared<TileDifference>(
diffTiles(previousRenderTiles->begin(), previousRenderTiles->end(), tiles->begin(), tiles->end()));
renderTileDiff = std::make_shared<TileDifference>(diffTiles(previousRenderTiles, getRenderTiles()));
}
return renderTileDiff;
}
Expand Down
2 changes: 1 addition & 1 deletion src/mbgl/renderer/sources/render_tile_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class RenderTileSource : public RenderSource {
RenderTileSource(Immutable<style::Source::Impl>, const TaggedScheduler&);
TilePyramid tilePyramid;
Immutable<std::vector<RenderTile>> renderTiles;
Immutable<std::vector<RenderTile>> previousRenderTiles;
RenderTiles previousRenderTiles;
mutable std::shared_ptr<TileDifference> renderTileDiff;
mutable RenderTiles filteredRenderTiles;
mutable RenderTiles renderTilesSortedByY;
Expand Down
Loading

0 comments on commit 5b1b35b

Please sign in to comment.