Bug/fill attributes (#1359)

This commit is contained in:
Tim Sylvester
2023-07-13 12:32:59 -07:00
committed by Bart Louwers
parent bc988c024b
commit 4a4389ab9b
19 changed files with 233 additions and 145 deletions

View File

@@ -48,7 +48,7 @@ public:
struct DrawSegment;
using UniqueDrawSegment = std::unique_ptr<DrawSegment>;
const util::SimpleIdentity& getId() const { return uniqueID; }
const util::SimpleIdentity& getID() const { return uniqueID; }
/// Draw the drawable
virtual void draw(PaintParameters&) const = 0;
@@ -208,7 +208,7 @@ struct DrawableLessByPriority {
if (a.getDrawPriority() != b.getDrawPriority()) {
return a.getDrawPriority() < b.getDrawPriority();
}
return a.getId() < b.getId();
return a.getID() < b.getID();
}
bool operator()(const Drawable* left, const Drawable* right) const { return operator()(*left, *right); }
bool operator()(const UniqueDrawable& left, const UniqueDrawable& right) const { return operator()(*left, *right); }

View File

@@ -73,7 +73,7 @@ void DrawableBuilder::flush() {
}
util::SimpleIdentity DrawableBuilder::getDrawableId() {
return currentDrawable ? currentDrawable->getId() : util::SimpleIdentity::Empty;
return currentDrawable ? currentDrawable->getID() : util::SimpleIdentity::Empty;
}
DrawPriority DrawableBuilder::getDrawPriority() const {

View File

@@ -35,7 +35,7 @@ void DrawableGL::draw(PaintParameters& parameters) const {
}
}
if (!shader || context.program.getCurrentValue() == 0) {
mbgl::Log::Warning(Event::General, "Missing shader for drawable " + util::toString(getId()) + "/" + getName());
mbgl::Log::Warning(Event::General, "Missing shader for drawable " + util::toString(getID()) + "/" + getName());
assert(false);
return;
}

View File

@@ -114,7 +114,7 @@ void Texture2D::create() noexcept {
}
platform::GLuint Texture2D::getTextureID() const noexcept {
return static_cast<gl::TextureResource&>(*textureResource).texture;
return textureResource ? static_cast<gl::TextureResource&>(*textureResource).texture : 0;
}
void Texture2D::updateSamplerConfiguration() noexcept {

View File

@@ -13,12 +13,8 @@ const style::LayerTypeInfo* FillLayerFactory::getTypeInfo() const noexcept {
std::unique_ptr<style::Layer> FillLayerFactory::createLayer(const std::string& id,
const style::conversion::Convertible& value) noexcept {
std::optional<std::string> source = getSource(value);
if (!source) {
return nullptr;
}
return std::unique_ptr<style::Layer>(new style::FillLayer(id, *source));
const auto source = getSource(value);
return std::unique_ptr<style::Layer>(source ? new (std::nothrow) style::FillLayer(id, *source) : nullptr);
}
std::unique_ptr<Layout> FillLayerFactory::createLayout(

View File

@@ -4,6 +4,8 @@
#include <mbgl/style/image_impl.hpp>
#include <mbgl/renderer/image_atlas.hpp>
#include <mbgl/style/layer_impl.hpp>
#include <mbgl/util/identity.hpp>
#include <atomic>
namespace mbgl {
@@ -65,9 +67,13 @@ public:
virtual void updateVertices(
const Placement&, bool /*updateOpacities*/, const TransformState&, const RenderTile&, std::set<uint32_t>&) {}
const util::SimpleIdentity& getID() const { return bucketID; }
protected:
Bucket() = default;
std::atomic<bool> uploaded{false};
util::SimpleIdentity bucketID;
};
} // namespace mbgl

View File

@@ -283,7 +283,7 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders,
tileLayerGroup->observeDrawables([&](gfx::Drawable& drawable) -> bool {
// Has this tile dropped out of the cover set?
return (!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end());
return (!drawable.getTileID() || hasRenderTile(*drawable.getTileID()));
});
// For each tile in the cover set, add a tile drawable if one doesn't already exist.

View File

@@ -319,9 +319,8 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
return;
}
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
return (!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end());
});
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove(
[&](gfx::Drawable& drawable) { return (!drawable.getTileID() || hasRenderTile(*drawable.getTileID())); });
const auto& evaluated = static_cast<const CircleLayerProperties&>(*evaluatedProperties).evaluated;
@@ -329,7 +328,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
const auto& tileID = tile.getOverscaledTileID();
const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass);
if (!renderData) {
if (!renderData || !renderData->bucket || !renderData->bucket->hasData()) {
removeTile(renderPass, tileID);
continue;
}
@@ -338,6 +337,13 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
const auto vertexCount = bucket.vertices.elements();
const auto& paintPropertyBinders = 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 float zoom = static_cast<float>(state.getZoom());
const CircleInterpolateUBO interpolateUBO = {
/* .color_t = */ std::get<0>(paintPropertyBinders.get<CircleColor>()->interpolationFactor(zoom)),

View File

@@ -311,7 +311,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
// If the render pass has changed or the tile has dropped out of the cover set, remove it.
return (drawable.getRenderPass() == drawPass &&
(!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end()));
(!drawable.getTileID() || hasRenderTile(*drawable.getTileID())));
});
const auto zoom = static_cast<float>(state.getZoom());
@@ -332,7 +332,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
const auto& tileID = tile.getOverscaledTileID();
const auto* optRenderData = getRenderDataForPass(tile, passes);
if (!optRenderData || !optRenderData->bucket) {
if (!optRenderData || !optRenderData->bucket || !optRenderData->bucket->hasData()) {
removeTile(drawPass, tileID);
continue;
}
@@ -340,7 +340,12 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
const auto& renderData = *optRenderData;
const auto& bucket = static_cast<const FillExtrusionBucket&>(*renderData.bucket);
gfx::VertexAttributeArray vertexAttrs;
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(passes, tileID);
}
setRenderTileBucketID(tileID, bucket.getID());
gfx::DrawableTweakerPtr tweaker;
if (depthBuilder) {
@@ -389,6 +394,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
continue;
}
gfx::VertexAttributeArray vertexAttrs;
const auto uniformProps = vertexAttrs.readDataDrivenPaintProperties<FillExtrusionBase,
FillExtrusionColor,
FillExtrusionHeight,

View File

@@ -363,16 +363,15 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
};
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
// If the render pass has changed or the tile has dropped out of the cover set, remove it.
return (drawable.getRenderPass() == renderPass &&
(!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end()));
// If the render pass has changed or the tile has dropped out of the cover set, remove it.
return drawable.getRenderPass() == renderPass && drawable.getTileID() && hasRenderTile(*drawable.getTileID());
});
for (const RenderTile& tile : *renderTiles) {
const auto& tileID = tile.getOverscaledTileID();
const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass);
if (!renderData) {
if (!renderData || !renderData->bucket || !renderData->bucket->hasData()) {
removeTile(renderPass, tileID);
continue;
}
@@ -380,6 +379,13 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
auto& bucket = static_cast<FillBucket&>(*renderData->bucket);
const 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);
const auto& crossfade = getCrossfade<FillLayerProperties>(renderData->layerProperties);
@@ -404,20 +410,6 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
/* pattern_to = */ patternPosB ? util::cast<float>(patternPosB->tlbr()) : std::array<float, 4>{0},
};
// If we already have drawables for this tile, update them.
auto updateExisting = [&](gfx::Drawable& drawable) {
auto& uniforms = drawable.mutableUniformBuffers();
uniforms.createOrUpdate(FillLayerTweaker::FillInterpolateUBOName, &interpolateUBO, context);
uniforms.createOrUpdate(FillLayerTweaker::FillTilePropsUBOName, &tileProps, context);
};
if (0 < tileLayerGroup->observeDrawables(renderPass, tileID, std::move(updateExisting))) {
continue;
}
// Share UBO buffers among any drawables created for this tile
const auto interpBuffer = context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO));
const auto tilePropsBuffer = context.createUniformBuffer(&tileProps, sizeof(tileProps));
// `Fill*Program` all use `style::FillPaintProperties`
gfx::VertexAttributeArray vertexAttrs;
const auto uniformProps =
@@ -433,6 +425,21 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
gfx::AttributeDataType::Short2);
}
// If we already have drawables for this tile, update them.
auto updateExisting = [&](gfx::Drawable& drawable) {
auto& uniforms = drawable.mutableUniformBuffers();
uniforms.createOrUpdate(FillLayerTweaker::FillInterpolateUBOName, &interpolateUBO, context);
uniforms.createOrUpdate(FillLayerTweaker::FillTilePropsUBOName, &tileProps, context);
drawable.setVertexAttributes(vertexAttrs);
};
if (0 < tileLayerGroup->observeDrawables(renderPass, tileID, std::move(updateExisting))) {
continue;
}
// Share UBO buffers among any drawables created for this tile
const auto interpBuffer = context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO));
const auto tilePropsBuffer = context.createUniformBuffer(&tileProps, sizeof(tileProps));
if (unevaluated.get<FillPattern>().isUndefined()) {
// Fill will occur in opaque or translucent pass based on `opaquePassCutoff`.
// Outline always occurs in translucent pass, defaults to fill color

View File

@@ -338,9 +338,8 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
return;
}
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
return (!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end());
});
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove(
[&](gfx::Drawable& drawable) { return (!drawable.getTileID() || hasRenderTile(*drawable.getTileID())); });
const auto& evaluated = static_cast<const HeatmapLayerProperties&>(*evaluatedProperties).evaluated;
@@ -357,6 +356,13 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
const auto vertexCount = bucket.vertices.elements();
const auto& paintPropertyBinders = 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 float zoom = static_cast<float>(state.getZoom());
const HeatmapInterpolateUBO interpolateUBO = {
/* .weight_t = */ std::get<0>(paintPropertyBinders.get<HeatmapWeight>()->interpolationFactor(zoom)),

View File

@@ -324,9 +324,8 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders,
return;
}
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
return (!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end());
});
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove(
[&](gfx::Drawable& drawable) { return (!drawable.getTileID() || hasRenderTile(*drawable.getTileID())); });
if (!staticDataSharedVertices) {
staticDataSharedVertices = std::make_shared<HillshadeVertexVector>(RenderStaticData::rasterVertices());
@@ -341,15 +340,19 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders,
const auto& tileID = tile.getOverscaledTileID();
auto* bucket_ = tile.getBucket(*baseImpl);
if (!bucket_) {
if (!bucket_ || !bucket_->hasData()) {
removeTile(renderPass, tileID);
continue;
}
auto& bucket = static_cast<HillshadeBucket&>(*bucket_);
if (!bucket.hasData()) {
continue;
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());
if (!bucket.renderTargetPrepared) {
// Set up tile render target

View File

@@ -458,7 +458,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
// If the render pass has changed or the tile has dropped out of the cover set, remove it.
return (drawable.getRenderPass() == renderPass &&
(!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end()));
(!drawable.getTileID() || hasRenderTile(*drawable.getTileID())));
});
auto createLineBuilder = [&](const std::string& name,
@@ -520,6 +520,13 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
const auto& evaluated = getEvaluated<LineLayerProperties>(renderData->layerProperties);
const auto& crossfade = getCrossfade<LineLayerProperties>(renderData->layerProperties);
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());
// interpolation UBOs
const float zoom = static_cast<float>(state.getZoom());
const LineInterpolationUBO lineInterpolationUBO{

View File

@@ -271,7 +271,8 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders,
return builder;
};
auto setTextures = [&context, &filter, this](std::unique_ptr<gfx::DrawableBuilder>& builder, RasterBucket& bucket) {
auto setTextures = [&context, &filter, this](std::unique_ptr<gfx::DrawableBuilder>& builder,
const RasterBucket& bucket) {
// textures
auto location0 = rasterShader->getSamplerLocation("u_image0");
if (location0.has_value()) {
@@ -289,7 +290,8 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders,
}
};
auto buildTileDrawables = [&setTextures](std::unique_ptr<gfx::DrawableBuilder>& builder, RasterBucket& bucket) {
auto buildTileDrawables = [&setTextures](std::unique_ptr<gfx::DrawableBuilder>& builder,
const RasterBucket& bucket) {
auto buildRenderData = [](const TileMask& mask,
std::vector<std::array<int16_t, 2>>& vertices,
std::vector<std::array<int16_t, 2>>& attributes,
@@ -422,7 +424,7 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders,
if (layerGroup) {
stats.drawablesRemoved += layerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
// Has this tile dropped out of the cover set?
return (!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end());
return (!drawable.getTileID() || hasRenderTile(*drawable.getTileID()));
});
} else {
// Set up a tile layer group
@@ -437,12 +439,21 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders,
auto builder = createBuilder();
for (const RenderTile& tile : *renderTiles) {
const auto& tileID = tile.getOverscaledTileID();
auto* bucket_ = tile.getBucket(*baseImpl);
if (!bucket_) {
const auto* bucket_ = tile.getBucket(*baseImpl);
if (!bucket_ || !bucket_->hasData()) {
removeTile(renderPass, tileID);
continue;
}
auto& bucket = static_cast<RasterBucket&>(*bucket_);
if (!bucket.hasData()) continue;
const auto& bucket = static_cast<const RasterBucket&>(*bucket_);
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());
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) continue;

View File

@@ -748,10 +748,65 @@ constexpr auto fadeOpacityAttribName = "a_fade_opacity";
constexpr auto texUniformName = "u_texture";
constexpr auto iconTexUniformName = "u_texture_icon";
std::vector<std::string> updateTileAttributes(gfx::Context& context,
const SymbolBucket::Buffer& buffer,
const bool isText,
const SymbolBucket::PaintProperties& paintProps,
const SymbolPaintProperties::PossiblyEvaluated& evaluated,
gfx::VertexAttributeArray& attribs) {
if (const auto& attr = attribs.getOrAdd(posOffsetAttribName)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(SymbolLayoutVertex, a1),
/*vertexOffset=*/0,
sizeof(SymbolLayoutVertex),
gfx::AttributeDataType::Short4);
}
if (const auto& attr = attribs.getOrAdd(dataAttibName)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(SymbolLayoutVertex, a2),
/*vertexOffset=*/0,
sizeof(SymbolLayoutVertex),
gfx::AttributeDataType::UShort4);
}
if (const auto& attr = attribs.getOrAdd(pixOffsetAttribName)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(SymbolLayoutVertex, a3),
/*vertexOffset=*/0,
sizeof(SymbolLayoutVertex),
gfx::AttributeDataType::Short4);
}
if (const auto& attr = attribs.getOrAdd(projPosAttribName)) {
using Vertex = gfx::Vertex<SymbolDynamicLayoutAttributes>;
attr->setSharedRawData(buffer.sharedDynamicVertices,
offsetof(Vertex, a1),
/*vertexOffset=*/0,
sizeof(Vertex),
gfx::AttributeDataType::Float3);
}
if (const auto& attr = attribs.getOrAdd(fadeOpacityAttribName)) {
using Vertex = gfx::Vertex<SymbolOpacityAttributes>;
attr->setSharedRawData(buffer.sharedOpacityVertices,
offsetof(Vertex, a1),
/*vertexOffset=*/0,
sizeof(Vertex),
gfx::AttributeDataType::Float);
}
return isText
? attribs
.readDataDrivenPaintProperties<TextOpacity, TextColor, TextHaloColor, TextHaloWidth, TextHaloBlur>(
paintProps.textBinders, evaluated)
: attribs
.readDataDrivenPaintProperties<IconOpacity, IconColor, IconHaloColor, IconHaloWidth, IconHaloBlur>(
paintProps.iconBinders, evaluated);
}
void updateTileDrawable(gfx::Drawable& drawable,
gfx::Context& context,
const SymbolBucket& bucket,
const SymbolBucket::PaintProperties& paintProps,
const SymbolPaintProperties::PossiblyEvaluated& evaluated,
const TransformState& state) {
if (!drawable.getData()) {
return;
@@ -759,6 +814,7 @@ void updateTileDrawable(gfx::Drawable& drawable,
auto& drawData = static_cast<gfx::SymbolDrawableData&>(*drawable.getData());
const auto isText = (drawData.symbolType == SymbolType::Text);
const auto sdfIcons = (drawData.symbolType == SymbolType::IconSDF);
const auto currentZoom = static_cast<float>(state.getZoom());
// This property can be set after the initial appearance of the tile, as part of the layout process.
@@ -771,22 +827,17 @@ void updateTileDrawable(gfx::Drawable& drawable,
uniforms.createOrUpdate(SymbolLayerTweaker::SymbolDrawableTilePropsUBOName, &tileUBO, context);
uniforms.createOrUpdate(SymbolLayerTweaker::SymbolDrawableInterpolateUBOName, &interpolateUBO, context);
const auto& buffer = isText ? bucket.text : (sdfIcons ? bucket.sdfIcon : bucket.icon);
const auto vertexCount = buffer.vertices().elements();
drawable.setVertices({}, vertexCount, gfx::AttributeDataType::Short4);
// TODO: detect whether anything has actually changed
// See `Placement::updateBucketDynamicVertices`
const auto sdfIcons = (drawData.symbolType == SymbolType::IconSDF);
const auto& buffer = isText ? bucket.text : (sdfIcons ? bucket.sdfIcon : bucket.icon);
auto& attribs = drawable.mutableVertexAttributes();
if (const auto& attr = attribs.get(projPosAttribName)) {
using Vertex = gfx::Vertex<SymbolDynamicLayoutAttributes>;
attr->setSharedRawData(
buffer.sharedDynamicVertices, offsetof(Vertex, a1), 0, sizeof(Vertex), gfx::AttributeDataType::Float3);
}
if (const auto& attr = attribs.get(fadeOpacityAttribName)) {
using Vertex = gfx::Vertex<SymbolOpacityAttributes>;
attr->setSharedRawData(
buffer.sharedOpacityVertices, offsetof(Vertex, a1), 0, sizeof(Vertex), gfx::AttributeDataType::Float);
}
gfx::VertexAttributeArray attribs;
updateTileAttributes(context, buffer, isText, paintProps, evaluated, attribs);
drawable.setVertexAttributes(std::move(attribs));
}
} // namespace
@@ -826,8 +877,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
// If the render pass has changed or the tile has dropped out of the cover set, remove it.
const auto& tileID = drawable.getTileID();
if (drawable.getRenderPass() != passes || (tileID && renderTileIDs.find(*tileID) == renderTileIDs.end())) {
tileBucketInstances.erase(*tileID);
if (drawable.getRenderPass() != passes || (tileID && !hasRenderTile(*tileID))) {
return false;
}
return true;
@@ -844,7 +894,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
const auto& tileID = tile.getOverscaledTileID();
const auto* optRenderData = getRenderDataForPass(tile, passes);
if (!optRenderData || !optRenderData->bucket) {
if (!optRenderData || !optRenderData->bucket || !optRenderData->bucket->hasData()) {
removeTile(passes, tileID);
continue;
}
@@ -852,23 +902,24 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
const auto& renderData = *optRenderData;
const auto& bucket = static_cast<const SymbolBucket&>(*renderData.bucket);
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(passes, tileID);
}
setRenderTileBucketID(tileID, bucket.getID());
assert(bucket.paintProperties.find(getID()) != bucket.paintProperties.end());
const auto& bucketPaintProperties = bucket.paintProperties.at(getID());
// If we already have drawables for this tile, update them.
if (tileLayerGroup->getDrawableCount(passes, tileID) > 0) {
const auto hit = tileBucketInstances.insert(std::make_pair(tileID, bucket.bucketInstanceId));
if (!hit.second && hit.first->second != bucket.bucketInstanceId) {
// The bucket has changed, reset the drawables for this tile.
tileLayerGroup->removeDrawables(passes, tileID);
hit.first->second = bucket.bucketInstanceId;
} else {
// Just update the drawables we already created
tileLayerGroup->observeDrawables(passes, tileID, [&](gfx::Drawable& drawable) {
updateTileDrawable(drawable, context, bucket, bucketPaintProperties, state);
});
continue;
}
// Just update the drawables we already created
tileLayerGroup->observeDrawables(passes, tileID, [&](gfx::Drawable& drawable) {
const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderData.layerProperties);
updateTileDrawable(drawable, context, bucket, bucketPaintProperties, evaluated, state);
});
continue;
}
float serialKey = 1.0f;
@@ -919,52 +970,11 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
auto& tileInfo = tileCache[tile.id];
gfx::VertexAttributeArray attrs;
const auto vertexCount = buffer.vertices().elements();
if (const auto& attr = attrs.add(posOffsetAttribName)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(SymbolLayoutVertex, a1),
0,
sizeof(SymbolLayoutVertex),
gfx::AttributeDataType::Short4);
}
if (const auto& attr = attrs.add(dataAttibName)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(SymbolLayoutVertex, a2),
0,
sizeof(SymbolLayoutVertex),
gfx::AttributeDataType::UShort4);
}
if (const auto& attr = attrs.add(pixOffsetAttribName)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(SymbolLayoutVertex, a3),
0,
sizeof(SymbolLayoutVertex),
gfx::AttributeDataType::Short4);
}
if (const auto& attr = attrs.add(projPosAttribName)) {
using Vertex = gfx::Vertex<SymbolDynamicLayoutAttributes>;
attr->setSharedRawData(
buffer.sharedDynamicVertices, offsetof(Vertex, a1), 0, sizeof(Vertex), gfx::AttributeDataType::Float3);
}
if (const auto& attr = attrs.add(fadeOpacityAttribName)) {
using Vertex = gfx::Vertex<SymbolOpacityAttributes>;
attr->setSharedRawData(
buffer.sharedOpacityVertices, offsetof(Vertex, a1), 0, sizeof(Vertex), gfx::AttributeDataType::Float);
}
const auto uniformProps = isText ? attrs.readDataDrivenPaintProperties<TextOpacity,
TextColor,
TextHaloColor,
TextHaloWidth,
TextHaloBlur>(
bucketPaintProperties.textBinders, evaluated)
: attrs.readDataDrivenPaintProperties<IconOpacity,
IconColor,
IconHaloColor,
IconHaloWidth,
IconHaloBlur>(
bucketPaintProperties.iconBinders, evaluated);
gfx::VertexAttributeArray attribs;
const auto uniformProps = updateTileAttributes(
context, buffer, isText, bucketPaintProperties, evaluated, attribs);
const auto textHalo = evaluated.get<style::TextHaloColor>().constantOr(Color::black()).a > 0.0f &&
evaluated.get<style::TextHaloWidth>().constantOr(1);
@@ -1013,7 +1023,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
builder->addTweaker(isText ? tileInfo.textTweaker : tileInfo.iconTweaker);
builder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short4);
builder->setDrawableName(layerPrefix + std::string(suffix));
builder->setVertexAttributes(attrs);
builder->setVertexAttributes(attribs);
const auto shader = std::static_pointer_cast<gfx::ShaderProgramBase>(
shaderGroup->getOrCreateShader(context, uniformProps, posOffsetAttribName));

View File

@@ -125,8 +125,6 @@ private:
gfx::ShaderGroupPtr symbolSDFIconGroup;
gfx::ShaderGroupPtr symbolSDFTextGroup;
gfx::ShaderGroupPtr symbolTextAndIconGroup;
std::unordered_map<OverscaledTileID, uint32_t> tileBucketInstances;
#endif // MLN_DRAWABLE_RENDERER
};

View File

@@ -71,10 +71,9 @@ std::optional<Color> RenderLayer::getSolidBackground() const {
#if MLN_DRAWABLE_RENDERER
void RenderLayer::layerChanged(const TransitionParameters&,
const Immutable<style::Layer::Impl>&,
UniqueChangeRequestVec& changes) {
// Treat a layer change the same as a remove.
// It will be set up again when `update()` is called.
layerRemoved(changes);
UniqueChangeRequestVec&) {
// When a layer changes, the bucket won't be replaced until the new source(s) load.
// If we remove the drawables here, they will just be re-created based on the current data.
}
void RenderLayer::layerRemoved(UniqueChangeRequestVec& changes) {
@@ -150,17 +149,38 @@ void RenderLayer::removeAllDrawables() {
}
void RenderLayer::updateRenderTileIDs() {
renderTileIDs.clear();
const auto oldMap = std::move(renderTileIDs);
if (renderTiles) {
const auto inserter = std::inserter(renderTileIDs, renderTileIDs.end());
const auto getID = [](const auto& tile) {
return tile.get().getOverscaledTileID();
};
renderTileIDs.reserve(renderTiles->size());
std::transform(renderTiles->begin(), renderTiles->end(), inserter, getID);
for (const auto& tile : *renderTiles) {
// If the tile existed previously, retain the mapped value
const auto tileID = tile.get().getOverscaledTileID();
const auto hit = oldMap.find(tileID);
const auto bucketID = (hit != oldMap.end()) ? hit->second : util::SimpleIdentity::Empty;
[[maybe_unused]] const auto result = renderTileIDs.insert(std::make_pair(tileID, bucketID));
assert(result.second && "Unexpected duplicate TileID in renderTiles");
}
}
}
bool RenderLayer::hasRenderTile(const OverscaledTileID& tileID) const {
return renderTileIDs.find(tileID) != renderTileIDs.end();
}
util::SimpleIdentity RenderLayer::getRenderTileBucketID(const OverscaledTileID& tileID) const {
const auto hit = renderTileIDs.find(tileID);
return (hit != renderTileIDs.end()) ? hit->second : util::SimpleIdentity::Empty;
}
bool RenderLayer::setRenderTileBucketID(const OverscaledTileID& tileID, util::SimpleIdentity bucketID) {
const auto hit = renderTileIDs.find(tileID);
if (hit != renderTileIDs.end() && hit->second != bucketID) {
hit->second = bucketID;
return true;
}
return false;
}
void RenderLayer::layerIndexChanged(int32_t newLayerIndex, UniqueChangeRequestVec& changes) {
layerIndex = newLayerIndex;

View File

@@ -10,7 +10,7 @@
#include <mbgl/gfx/drawable.hpp>
#include <mbgl/renderer/change_request.hpp>
#include <unordered_set>
#include <unordered_map>
#endif // MLN_DRAWABLE_RENDERER
#include <list>
@@ -205,8 +205,18 @@ protected:
/// Remove all the drawables for tiles
virtual void removeAllDrawables();
// Update `renderTileIDs` from `renderTiles`
/// Update `renderTileIDs` from `renderTiles`
void updateRenderTileIDs();
/// Whether a given tile ID is present in the current cover set (`renderTiles`)
bool hasRenderTile(const OverscaledTileID&) const;
/// Get the bucket ID from which a given tile was built
util::SimpleIdentity getRenderTileBucketID(const OverscaledTileID&) const;
/// Set the bucket ID from which a given tile was built
/// @return true if updated, false if missing or unchanged
bool setRenderTileBucketID(const OverscaledTileID&, util::SimpleIdentity bucketID);
#endif // MLN_DRAWABLE_RENDERER
protected:
@@ -223,9 +233,11 @@ protected:
// will need to be overriden to handle their activation.
LayerGroupBasePtr layerGroup;
// The set of Tile IDs in `renderTiles`
std::unordered_set<OverscaledTileID> renderTileIDs;
// The set of Tile IDs in `renderTiles`, along with the
// identity of the bucket from which they were built.
std::unordered_map<OverscaledTileID, util::SimpleIdentity> renderTileIDs;
#endif
// Current layer index as specified by the layerIndexChanged event
int32_t layerIndex{0};

View File

@@ -133,8 +133,8 @@ void Renderer::Impl::render(const RenderTree& renderTree) {
// Run layer tweakers to update any dynamic elements
orchestrator.observeLayerGroups([&](LayerGroupBase& layerGroup) {
if (layerGroup.getLayerTweaker()) {
layerGroup.getLayerTweaker()->execute(layerGroup, renderTree, parameters);
if (const auto& tweaker = layerGroup.getLayerTweaker()) {
tweaker->execute(layerGroup, renderTree, parameters);
}
});