Handle the case where styles update without a bucket change, fixing `… (#1874)
This commit is contained in:
@@ -365,13 +365,14 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
auto updateExisting = [&](gfx::Drawable& drawable) {
|
||||
if (drawable.getLayerTweaker() != layerTweaker) {
|
||||
// This drawable was produced on a previous style/bucket, and should not be updated.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& uniforms = drawable.mutableUniformBuffers();
|
||||
uniforms.createOrUpdate(idCircleInterpolateUBOName, &interpolateUBO, context);
|
||||
return true;
|
||||
};
|
||||
if (0 < tileLayerGroup->visitDrawables(renderPass, tileID, std::move(updateExisting))) {
|
||||
if (updateTile(renderPass, tileID, std::move(updateExisting))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -404,24 +404,18 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
|
||||
};
|
||||
|
||||
// If we already have drawables for this tile, update them.
|
||||
if (tileLayerGroup->getDrawableCount(drawPass, tileID) > 0) {
|
||||
// Just update the drawables we already created
|
||||
tileLayerGroup->visitDrawables(drawPass, tileID, [&](gfx::Drawable& drawable) {
|
||||
if (drawable.getLayerTweaker() != layerTweaker) {
|
||||
// This drawable was produced on a previous style/bucket, and should not be updated.
|
||||
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& uniforms = drawable.mutableUniformBuffers();
|
||||
uniforms.createOrUpdate(
|
||||
FillExtrusionLayerTweaker::idFillExtrusionTilePropsUBOName, &tilePropsUBO, context);
|
||||
uniforms.createOrUpdate(
|
||||
FillExtrusionLayerTweaker::idFillExtrusionInterpolateUBOName, &interpUBO, context);
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!shaderGroup) {
|
||||
auto& uniforms = drawable.mutableUniformBuffers();
|
||||
uniforms.createOrUpdate(FillExtrusionLayerTweaker::idFillExtrusionTilePropsUBOName, &tilePropsUBO, context);
|
||||
uniforms.createOrUpdate(FillExtrusionLayerTweaker::idFillExtrusionInterpolateUBOName, &interpUBO, context);
|
||||
return true;
|
||||
};
|
||||
if (updateTile(drawPass, tileID, std::move(updateExisting))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -518,7 +518,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
auto updateExisting = [&](gfx::Drawable& drawable) {
|
||||
if (drawable.getLayerTweaker() != layerTweaker) {
|
||||
// This drawable was produced on a previous style/bucket, and should not be updated.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& uniforms = drawable.mutableUniformBuffers();
|
||||
@@ -539,8 +539,9 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
}
|
||||
|
||||
drawable.setVertexAttributes(vertexAttrs);
|
||||
return true;
|
||||
};
|
||||
if (0 < tileLayerGroup->visitDrawables(renderPass, tileID, std::move(updateExisting))) {
|
||||
if (updateTile(renderPass, tileID, std::move(updateExisting))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -491,7 +491,7 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders,
|
||||
// Only current drawables are updated, ones produced for
|
||||
// a previous style retain the attribute values for that style.
|
||||
if (drawable.getLayerTweaker() != layerTweaker) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
drawable.setVertexAttributes(std::move(hillshadeVertexAttrs));
|
||||
@@ -516,8 +516,9 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders,
|
||||
if (hillshadeImageLocation) {
|
||||
drawable.setTexture(bucket.renderTarget->getTexture(), *hillshadeImageLocation);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (0 < tileLayerGroup->visitDrawables(renderPass, tileID, std::move(updateExisting))) {
|
||||
if (updateTile(renderPass, tileID, std::move(updateExisting))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -537,11 +537,10 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
|
||||
/*pattern_from =*/patternPosA ? util::cast<float>(patternPosA->tlbr()) : std::array<float, 4>{0},
|
||||
/*pattern_to =*/patternPosB ? util::cast<float>(patternPosB->tlbr()) : std::array<float, 4>{0}};
|
||||
|
||||
// update existing drawables
|
||||
tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) {
|
||||
auto updateExisting = [&](gfx::Drawable& drawable) {
|
||||
if (drawable.getLayerTweaker() != layerTweaker) {
|
||||
// This drawable was produced on a previous style/bucket, and should not be updated.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& shader = drawable.getShader();
|
||||
@@ -572,9 +571,9 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
|
||||
}
|
||||
|
||||
// TODO: vertex attributes or `propertiesAsUniforms` updated, is that needed?
|
||||
});
|
||||
|
||||
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) {
|
||||
return true;
|
||||
};
|
||||
if (updateTile(renderPass, tileID, std::move(updateExisting))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -466,20 +466,26 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders,
|
||||
if (!cleared) {
|
||||
// Update existing drawables
|
||||
bool geometryChanged = false;
|
||||
const auto updated = tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) {
|
||||
auto updateExisting = [&](gfx::Drawable& drawable) {
|
||||
// Only current drawables are updated, ones produced for
|
||||
// a previous style retain the attribute values for that style.
|
||||
if (drawable.getLayerTweaker() != layerTweaker) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx::UniqueDrawableBuilder none;
|
||||
if (!geometryChanged && !buildVertexData(none, &drawable, bucket)) {
|
||||
// Masking changed, need to rebuild this tile
|
||||
geometryChanged = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (geometryChanged) {
|
||||
removeTile(renderPass, tileID);
|
||||
// cleared = true;
|
||||
} else if (0 < updated) {
|
||||
return true;
|
||||
};
|
||||
if (updateTile(renderPass, tileID, std::move(updateExisting))) {
|
||||
// If we modified drawables without removing them, we're done with this tile.
|
||||
continue;
|
||||
} else if (geometryChanged) {
|
||||
// If the geometry has changed, the drawable needs to be re-built
|
||||
removeTile(renderPass, tileID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1148,35 +1148,34 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
|
||||
};
|
||||
|
||||
// If we already have drawables for this tile, update them.
|
||||
if (tileLayerGroup->getDrawableCount(passes, tileID) > 0) {
|
||||
gfx::UniformBufferPtr textInterpUBO, iconInterpUBO;
|
||||
// Just update the drawables we already created
|
||||
gfx::UniformBufferPtr textInterpUBO, iconInterpUBO;
|
||||
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;
|
||||
}
|
||||
|
||||
// Just update the drawables we already created
|
||||
tileLayerGroup->visitDrawables(passes, tileID, [&](gfx::Drawable& drawable) {
|
||||
if (drawable.getLayerTweaker() != layerTweaker) {
|
||||
// This drawable was produced on a previous style/bucket, and should not be updated.
|
||||
return;
|
||||
}
|
||||
propertiesAsUniforms.clear();
|
||||
|
||||
propertiesAsUniforms.clear();
|
||||
|
||||
const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderData.layerProperties);
|
||||
updateTileDrawable(drawable,
|
||||
context,
|
||||
bucket,
|
||||
bucketPaintProperties,
|
||||
evaluated,
|
||||
state,
|
||||
textInterpUBO,
|
||||
iconInterpUBO,
|
||||
propertiesAsUniforms);
|
||||
|
||||
// We assume that the properties-as-uniforms doesn't change without the style changing.
|
||||
// That would require updating the shader as well.
|
||||
[[maybe_unused]] const auto& drawData = static_cast<gfx::SymbolDrawableData&>(*drawable.getData());
|
||||
assert(drawData.propertiesAsUniforms == toMap(propertiesAsUniforms));
|
||||
});
|
||||
const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderData.layerProperties);
|
||||
updateTileDrawable(drawable,
|
||||
context,
|
||||
bucket,
|
||||
bucketPaintProperties,
|
||||
evaluated,
|
||||
state,
|
||||
textInterpUBO,
|
||||
iconInterpUBO,
|
||||
propertiesAsUniforms);
|
||||
|
||||
// We assume that the properties-as-uniforms doesn't change without the style changing.
|
||||
// That would require updating the shader as well.
|
||||
[[maybe_unused]] const auto& drawData = static_cast<gfx::SymbolDrawableData&>(*drawable.getData());
|
||||
assert(drawData.propertiesAsUniforms == toMap(propertiesAsUniforms));
|
||||
return true;
|
||||
};
|
||||
if (updateTile(passes, tileID, std::move(updateExisting))) {
|
||||
// re-create collision drawables
|
||||
if (collisionTileLayerGroup) {
|
||||
collisionTileLayerGroup->removeDrawables(passes, tileID);
|
||||
|
||||
@@ -166,6 +166,30 @@ const LayerRenderData* RenderLayer::getRenderDataForPass(const RenderTile& tile,
|
||||
}
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
bool RenderLayer::updateTile(RenderPass renderPass,
|
||||
const OverscaledTileID& tileID,
|
||||
std::function<bool(gfx::Drawable&)> update) {
|
||||
bool anyUpdated = false;
|
||||
if (const auto tileGroup = static_cast<TileLayerGroup*>(layerGroup.get())) {
|
||||
bool unUpdatedDrawables = false;
|
||||
tileGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) {
|
||||
if (update(drawable)) {
|
||||
anyUpdated = true;
|
||||
} else {
|
||||
unUpdatedDrawables = true;
|
||||
}
|
||||
});
|
||||
|
||||
// If any are updated, the caller shouldn't add new ones.
|
||||
// If none are updated and some were skipped, remove those.
|
||||
// This is to handle the case that the style layer changes but the bucket is not re-created.
|
||||
if (!anyUpdated && unUpdatedDrawables) {
|
||||
removeTile(renderPass, tileID);
|
||||
}
|
||||
}
|
||||
return anyUpdated;
|
||||
}
|
||||
|
||||
std::size_t RenderLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) {
|
||||
if (const auto tileGroup = static_cast<TileLayerGroup*>(layerGroup.get())) {
|
||||
const auto n = tileGroup->removeDrawables(renderPass, tileID).size();
|
||||
|
||||
@@ -209,6 +209,16 @@ protected:
|
||||
/// Change the layer index on a layer group associated with this layer
|
||||
void changeLayerIndex(const LayerGroupBasePtr&, int32_t newLayerIndex, UniqueChangeRequestVec&);
|
||||
|
||||
/// Update the drawables for a tile.
|
||||
/// @param renderPass The pass to consider
|
||||
/// @param tileID The tile to consider
|
||||
/// @param updateFunction A function that updates a single drawable. Should return true if the drawable
|
||||
/// was updated or false if it was skipped because it's for a previous style.
|
||||
/// @return true if drawables were updated
|
||||
bool updateTile(RenderPass renderPass,
|
||||
const OverscaledTileID& tileID,
|
||||
std::function<bool(gfx::Drawable&)> updateFunction);
|
||||
|
||||
/// Remove all drawables for the tile from the layer group
|
||||
/// @return The number of drawables actually removed.
|
||||
virtual std::size_t removeTile(RenderPass, const OverscaledTileID&);
|
||||
|
||||
Reference in New Issue
Block a user