Bug/fill attributes (#1359)
This commit is contained in:
committed by
Bart Louwers
parent
bc988c024b
commit
4a4389ab9b
@@ -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); }
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user