Share identical uniform buffers across drawables for background, line. (#1346)

This commit is contained in:
Tim Sylvester
2023-07-12 09:58:01 -07:00
committed by Bart Louwers
parent 3056f28756
commit 4eef2e3529
18 changed files with 158 additions and 111 deletions

View File

@@ -62,7 +62,9 @@ public:
void createOrUpdate(std::string_view name, const std::vector<uint8_t>& data, gfx::Context&); void createOrUpdate(std::string_view name, const std::vector<uint8_t>& data, gfx::Context&);
void createOrUpdate(std::string_view name, const void* data, std::size_t size, gfx::Context&); void createOrUpdate(std::string_view name, const void* data, std::size_t size, gfx::Context&);
template <typename T> template <typename T>
void createOrUpdate(std::string_view name, const T* data, gfx::Context& context) { std::enable_if_t<!std::is_pointer_v<T>> createOrUpdate(std::string_view name,
const T* data,
gfx::Context& context) {
createOrUpdate(name, data, sizeof(T), context); createOrUpdate(name, data, sizeof(T), context);
} }

View File

@@ -67,8 +67,8 @@ public:
virtual void postRender(RenderOrchestrator&, PaintParameters&) {} virtual void postRender(RenderOrchestrator&, PaintParameters&) {}
/// Call the provided function for each drawable in priority order /// Call the provided function for each drawable in priority order
virtual void observeDrawables(const std::function<void(gfx::Drawable&)>&&) = 0; virtual std::size_t observeDrawables(const std::function<void(gfx::Drawable&)>&&) = 0;
virtual void observeDrawables(const std::function<void(const gfx::Drawable&)>&&) const = 0; virtual std::size_t observeDrawables(const std::function<void(const gfx::Drawable&)>&&) const = 0;
/// Call the provided function for each drawable in undefined order, allowing for removal. /// Call the provided function for each drawable in undefined order, allowing for removal.
/// @param f A function called with each drawable, returning true to keep and false to discard it. /// @param f A function called with each drawable, returning true to keep and false to discard it.
@@ -102,15 +102,17 @@ public:
std::vector<gfx::UniqueDrawable> removeDrawables(mbgl::RenderPass, const OverscaledTileID&); std::vector<gfx::UniqueDrawable> removeDrawables(mbgl::RenderPass, const OverscaledTileID&);
void addDrawable(mbgl::RenderPass, const OverscaledTileID&, gfx::UniqueDrawable&&); void addDrawable(mbgl::RenderPass, const OverscaledTileID&, gfx::UniqueDrawable&&);
void observeDrawables(const std::function<void(gfx::Drawable&)>&&) override; std::size_t observeDrawables(const std::function<void(gfx::Drawable&)>&&) override;
void observeDrawables(const std::function<void(const gfx::Drawable&)>&&) const override; std::size_t observeDrawables(const std::function<void(const gfx::Drawable&)>&&) const override;
std::size_t observeDrawablesRemove(const std::function<bool(gfx::Drawable&)>&&) override; std::size_t observeDrawablesRemove(const std::function<bool(gfx::Drawable&)>&&) override;
/// Call the provided function for each drawable for the given tile /// Call the provided function for each drawable for the given tile
void observeDrawables(mbgl::RenderPass, const OverscaledTileID&, const std::function<void(gfx::Drawable&)>&&); std::size_t observeDrawables(mbgl::RenderPass,
void observeDrawables(mbgl::RenderPass, const OverscaledTileID&,
const OverscaledTileID&, const std::function<void(gfx::Drawable&)>&&);
const std::function<void(const gfx::Drawable&)>&&) const; std::size_t observeDrawables(mbgl::RenderPass,
const OverscaledTileID&,
const std::function<void(const gfx::Drawable&)>&&) const;
std::size_t clearDrawables() override; std::size_t clearDrawables() override;
@@ -133,8 +135,8 @@ public:
std::vector<gfx::UniqueDrawable> removeDrawables(mbgl::RenderPass); std::vector<gfx::UniqueDrawable> removeDrawables(mbgl::RenderPass);
void addDrawable(gfx::UniqueDrawable&&); void addDrawable(gfx::UniqueDrawable&&);
void observeDrawables(const std::function<void(gfx::Drawable&)>&&) override; std::size_t observeDrawables(const std::function<void(gfx::Drawable&)>&&) override;
void observeDrawables(const std::function<void(const gfx::Drawable&)>&&) const override; std::size_t observeDrawables(const std::function<void(const gfx::Drawable&)>&&) const override;
std::size_t observeDrawablesRemove(const std::function<bool(gfx::Drawable&)>&&) override; std::size_t observeDrawablesRemove(const std::function<bool(gfx::Drawable&)>&&) override;
std::size_t clearDrawables() override; std::size_t clearDrawables() override;

View File

@@ -27,20 +27,22 @@ void LayerGroup::addDrawable(gfx::UniqueDrawable&& drawable) {
impl->drawables.emplace(std::move(drawable)); impl->drawables.emplace(std::move(drawable));
} }
void LayerGroup::observeDrawables(const std::function<void(gfx::Drawable&)>&& f) { std::size_t LayerGroup::observeDrawables(const std::function<void(gfx::Drawable&)>&& f) {
for (const auto& item : impl->drawables) { for (const auto& item : impl->drawables) {
if (item) { if (item) {
f(*item); f(*item);
} }
} }
return impl->drawables.size();
} }
void LayerGroup::observeDrawables(const std::function<void(const gfx::Drawable&)>&& f) const { std::size_t LayerGroup::observeDrawables(const std::function<void(const gfx::Drawable&)>&& f) const {
for (const auto& item : impl->drawables) { for (const auto& item : impl->drawables) {
if (item) { if (item) {
f(*item); f(*item);
} }
} }
return impl->drawables.size();
} }
std::size_t LayerGroup::observeDrawablesRemove(const std::function<bool(gfx::Drawable&)>&& f) { std::size_t LayerGroup::observeDrawablesRemove(const std::function<bool(gfx::Drawable&)>&& f) {

View File

@@ -138,12 +138,16 @@ void BackgroundLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTre
}; };
uniforms.createOrUpdate(BackgroundLayerUBOName, &layerUBO, context); uniforms.createOrUpdate(BackgroundLayerUBOName, &layerUBO, context);
} else { } else {
const BackgroundLayerUBO layerUBO = {/* .color = */ evaluated.get<BackgroundColor>(), // UBOs can be shared
/* .opacity = */ evaluated.get<BackgroundOpacity>(), if (!backgroundLayerBuffer) {
/* .pad = */ 0, const BackgroundLayerUBO layerUBO = {/* .color = */ evaluated.get<BackgroundColor>(),
0, /* .opacity = */ evaluated.get<BackgroundOpacity>(),
0}; /* .pad = */ 0,
uniforms.createOrUpdate(BackgroundLayerUBOName, &layerUBO, context); 0,
0};
backgroundLayerBuffer = context.createUniformBuffer(&layerUBO, sizeof(layerUBO));
}
uniforms.addOrReplace(BackgroundLayerUBOName, backgroundLayerBuffer);
} }
}); });
} }

View File

@@ -28,6 +28,7 @@ public:
void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override;
protected: protected:
gfx::UniformBufferPtr backgroundLayerBuffer;
}; };
} // namespace mbgl } // namespace mbgl

View File

@@ -47,6 +47,7 @@ static constexpr std::string_view CircleEvaluatedPropsUBOName = "CircleEvaluated
void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, void CircleLayerTweaker::execute(LayerGroupBase& layerGroup,
const RenderTree& renderTree, const RenderTree& renderTree,
const PaintParameters& parameters) { const PaintParameters& parameters) {
auto& context = parameters.context;
const auto& evaluated = static_cast<const CircleLayerProperties&>(*evaluatedProperties).evaluated; const auto& evaluated = static_cast<const CircleLayerProperties&>(*evaluatedProperties).evaluated;
if (layerGroup.empty()) { if (layerGroup.empty()) {
@@ -58,19 +59,21 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup,
const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str());
#endif #endif
// Updated every frame, but shared across drawables
const CirclePaintParamsUBO paintParamsUBO = { const CirclePaintParamsUBO paintParamsUBO = {
/* .camera_to_center_distance = */ parameters.state.getCameraToCenterDistance(), /* .camera_to_center_distance = */ parameters.state.getCameraToCenterDistance(),
/* .device_pixel_ratio = */ parameters.pixelRatio, /* .device_pixel_ratio = */ parameters.pixelRatio,
/* .padding = */ {0}}; /* .padding = */ {0}};
if (!paintParamsUniformBuffer) { if (!paintParamsUniformBuffer) {
paintParamsUniformBuffer = parameters.context.createUniformBuffer(&paintParamsUBO, sizeof(paintParamsUBO)); paintParamsUniformBuffer = context.createUniformBuffer(&paintParamsUBO, sizeof(paintParamsUBO));
} else { } else {
paintParamsUniformBuffer->update(&paintParamsUBO, sizeof(CirclePaintParamsUBO)); paintParamsUniformBuffer->update(&paintParamsUBO, sizeof(CirclePaintParamsUBO));
} }
const bool pitchWithMap = evaluated.get<CirclePitchAlignment>() == AlignmentType::Map; const bool pitchWithMap = evaluated.get<CirclePitchAlignment>() == AlignmentType::Map;
// Updated only with evaluated properties
if (!evaluatedPropsUniformBuffer) { if (!evaluatedPropsUniformBuffer) {
const CircleEvaluatedPropsUBO evaluatedPropsUBO = { const CircleEvaluatedPropsUBO evaluatedPropsUBO = {
/* .color = */ evaluated.get<CircleColor>().constantOr(CircleColor::defaultValue()), /* .color = */ evaluated.get<CircleColor>().constantOr(CircleColor::defaultValue()),
@@ -84,13 +87,13 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup,
/* .scale_with_map = */ evaluated.get<CirclePitchScale>() == CirclePitchScaleType::Map, /* .scale_with_map = */ evaluated.get<CirclePitchScale>() == CirclePitchScaleType::Map,
/* .pitch_with_map = */ pitchWithMap, /* .pitch_with_map = */ pitchWithMap,
/* .padding = */ 0}; /* .padding = */ 0};
evaluatedPropsUniformBuffer = parameters.context.createUniformBuffer(&evaluatedPropsUBO, evaluatedPropsUniformBuffer = context.createUniformBuffer(&evaluatedPropsUBO, sizeof(evaluatedPropsUBO));
sizeof(evaluatedPropsUBO));
} }
layerGroup.observeDrawables([&](gfx::Drawable& drawable) { layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
drawable.mutableUniformBuffers().addOrReplace(CirclePaintParamsUBOName, paintParamsUniformBuffer); auto& uniforms = drawable.mutableUniformBuffers();
drawable.mutableUniformBuffers().addOrReplace(CircleEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); uniforms.addOrReplace(CirclePaintParamsUBOName, paintParamsUniformBuffer);
uniforms.addOrReplace(CircleEvaluatedPropsUBOName, evaluatedPropsUniformBuffer);
if (!drawable.getTileID()) { if (!drawable.getTileID()) {
return; return;
@@ -106,13 +109,14 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup,
const auto pixelsToTileUnits = tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom())); const auto pixelsToTileUnits = tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom()));
CircleDrawableUBO drawableUBO = { // Updated for each drawable on each frame
const CircleDrawableUBO drawableUBO = {
/* .matrix = */ util::cast<float>(matrix), /* .matrix = */ util::cast<float>(matrix),
/* .extrude_scale = */ /* .extrude_scale = */
pitchWithMap ? std::array<float, 2>{{pixelsToTileUnits}} : parameters.pixelsToGLUnits, pitchWithMap ? std::array<float, 2>{{pixelsToTileUnits}} : parameters.pixelsToGLUnits,
/* .padding = */ {0}}; /* .padding = */ {0}};
drawable.mutableUniformBuffers().createOrUpdate(CircleDrawableUBOName, &drawableUBO, parameters.context); uniforms.createOrUpdate(CircleDrawableUBOName, &drawableUBO, context);
}); });
} }

View File

@@ -64,6 +64,7 @@ auto constOrDefault(const IndexedTuple<TypeList<Is...>, TypeList<Ts...>>& evalua
void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup,
const RenderTree& renderTree, const RenderTree& renderTree,
const PaintParameters& parameters) { const PaintParameters& parameters) {
auto& context = parameters.context;
const auto& props = static_cast<const FillExtrusionLayerProperties&>(*evaluatedProperties); const auto& props = static_cast<const FillExtrusionLayerProperties&>(*evaluatedProperties);
const auto& evaluated = props.evaluated; const auto& evaluated = props.evaluated;
const auto& crossfade = props.crossfade; const auto& crossfade = props.crossfade;
@@ -78,7 +79,8 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup,
const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str());
#endif #endif
// UBO depends on more than just evaluated properties, so we need to update every time. // UBO depends on more than just evaluated properties, so we need to update every time,
// but the resulting buffer can be shared across all the drawables from the layer.
const FillExtrusionDrawablePropsUBO paramsUBO = { const FillExtrusionDrawablePropsUBO paramsUBO = {
/* .color = */ gfx::VertexAttribute::colorAttrRGBA(constOrDefault<FillExtrusionColor>(evaluated)), /* .color = */ gfx::VertexAttribute::colorAttrRGBA(constOrDefault<FillExtrusionColor>(evaluated)),
/* .light_color = */ FillExtrusionProgram::lightColor(parameters.evaluatedLight), /* .light_color = */ FillExtrusionProgram::lightColor(parameters.evaluatedLight),
@@ -94,7 +96,7 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup,
0, 0,
0}; 0};
if (!propsBuffer) { if (!propsBuffer) {
propsBuffer = parameters.context.createUniformBuffer(&paramsUBO, sizeof(paramsUBO)); propsBuffer = context.createUniformBuffer(&paramsUBO, sizeof(paramsUBO));
} else { } else {
propsBuffer->update(&paramsUBO, sizeof(paramsUBO)); propsBuffer->update(&paramsUBO, sizeof(paramsUBO));
} }
@@ -145,7 +147,7 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup,
/* .height_factor = */ heightFactor, /* .height_factor = */ heightFactor,
/* .pad = */ 0}; /* .pad = */ 0};
uniforms.createOrUpdate(FillExtrusionDrawableUBOName, &drawableUBO, parameters.context); uniforms.createOrUpdate(FillExtrusionDrawableUBOName, &drawableUBO, context);
}); });
} }

View File

@@ -44,6 +44,7 @@ static constexpr std::string_view FillDrawablePropsUBOName = "FillDrawablePropsU
void FillLayerTweaker::execute(LayerGroupBase& layerGroup, void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
const RenderTree& renderTree, const RenderTree& renderTree,
const PaintParameters& parameters) { const PaintParameters& parameters) {
auto& context = parameters.context;
const auto& props = static_cast<const FillLayerProperties&>(*evaluatedProperties); const auto& props = static_cast<const FillLayerProperties&>(*evaluatedProperties);
const auto& evaluated = props.evaluated; const auto& evaluated = props.evaluated;
const auto& crossfade = props.crossfade; const auto& crossfade = props.crossfade;
@@ -65,11 +66,12 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
/* .padding = */ 0, /* .padding = */ 0,
0, 0,
0}; 0};
propsBuffer = parameters.context.createUniformBuffer(&paramsUBO, sizeof(paramsUBO)); propsBuffer = context.createUniformBuffer(&paramsUBO, sizeof(paramsUBO));
} }
layerGroup.observeDrawables([&](gfx::Drawable& drawable) { layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
drawable.mutableUniformBuffers().addOrReplace(FillDrawablePropsUBOName, propsBuffer); auto& uniforms = drawable.mutableUniformBuffers();
uniforms.addOrReplace(FillDrawablePropsUBOName, propsBuffer);
if (!drawable.getTileID()) { if (!drawable.getTileID()) {
return; return;
@@ -114,7 +116,7 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
/*.texsize=*/{static_cast<float>(textureSize.width), static_cast<float>(textureSize.height)}, /*.texsize=*/{static_cast<float>(textureSize.width), static_cast<float>(textureSize.height)},
}; };
drawable.mutableUniformBuffers().createOrUpdate(FillDrawableUBOName, &drawableUBO, parameters.context); uniforms.createOrUpdate(FillDrawableUBOName, &drawableUBO, context);
}); });
} }

View File

@@ -34,6 +34,7 @@ static constexpr std::string_view HeatmapEvaluatedPropsUBOName = "HeatmapEvaluat
void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup,
const RenderTree& renderTree, const RenderTree& renderTree,
const PaintParameters& parameters) { const PaintParameters& parameters) {
auto& context = parameters.context;
const auto& evaluated = static_cast<const HeatmapLayerProperties&>(*evaluatedProperties).evaluated; const auto& evaluated = static_cast<const HeatmapLayerProperties&>(*evaluatedProperties).evaluated;
if (layerGroup.empty()) { if (layerGroup.empty()) {
@@ -46,7 +47,7 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup,
#endif #endif
if (!evaluatedPropsUniformBuffer) { if (!evaluatedPropsUniformBuffer) {
HeatmapEvaluatedPropsUBO evaluatedPropsUBO = { const HeatmapEvaluatedPropsUBO evaluatedPropsUBO = {
/* .weight = */ evaluated.get<HeatmapWeight>().constantOr(HeatmapWeight::defaultValue()), /* .weight = */ evaluated.get<HeatmapWeight>().constantOr(HeatmapWeight::defaultValue()),
/* .radius = */ evaluated.get<HeatmapRadius>().constantOr(HeatmapRadius::defaultValue()), /* .radius = */ evaluated.get<HeatmapRadius>().constantOr(HeatmapRadius::defaultValue()),
/* .intensity = */ evaluated.get<HeatmapIntensity>(), /* .intensity = */ evaluated.get<HeatmapIntensity>(),
@@ -56,7 +57,8 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup,
} }
layerGroup.observeDrawables([&](gfx::Drawable& drawable) { layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
drawable.mutableUniformBuffers().addOrReplace(HeatmapEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); auto& uniforms = drawable.mutableUniformBuffers();
uniforms.addOrReplace(HeatmapEvaluatedPropsUBOName, evaluatedPropsUniformBuffer);
if (!drawable.getTileID()) { if (!drawable.getTileID()) {
return; return;
@@ -71,12 +73,12 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup,
TranslateAnchorType::Viewport, TranslateAnchorType::Viewport,
nearClipped, nearClipped,
inViewportPixelUnits); inViewportPixelUnits);
HeatmapDrawableUBO drawableUBO = { const HeatmapDrawableUBO drawableUBO = {
/* .matrix = */ util::cast<float>(matrix), /* .matrix = */ util::cast<float>(matrix),
/* .extrude_scale = */ tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom())), /* .extrude_scale = */ tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom())),
/* .padding = */ {0}}; /* .padding = */ {0}};
drawable.mutableUniformBuffers().createOrUpdate(HeatmapDrawableUBOName, &drawableUBO, parameters.context); uniforms.createOrUpdate(HeatmapDrawableUBOName, &drawableUBO, context);
}); });
} }

View File

@@ -41,7 +41,7 @@ void HeatmapTextureLayerTweaker::execute(LayerGroupBase& layerGroup,
const auto& size = parameters.staticData.backendSize; const auto& size = parameters.staticData.backendSize;
mat4 viewportMat; mat4 viewportMat;
matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1); matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1);
HeatmapTextureDrawableUBO drawableUBO = { const HeatmapTextureDrawableUBO drawableUBO = {
/* .matrix = */ util::cast<float>(viewportMat), /* .matrix = */ util::cast<float>(viewportMat),
/* .world = */ {static_cast<float>(size.width), static_cast<float>(size.height)}, /* .world = */ {static_cast<float>(size.width), static_cast<float>(size.height)},
/* .opacity = */ evaluated.get<HeatmapOpacity>(), /* .opacity = */ evaluated.get<HeatmapOpacity>(),

View File

@@ -120,35 +120,55 @@ static constexpr std::string_view LineSDFPropertiesUBOName = "LineSDFPropertiesU
void LineLayerTweaker::execute(LayerGroupBase& layerGroup, void LineLayerTweaker::execute(LayerGroupBase& layerGroup,
const RenderTree& renderTree, const RenderTree& renderTree,
const PaintParameters& parameters) { const PaintParameters& parameters) {
auto& context = parameters.context;
const auto& evaluated = static_cast<const LineLayerProperties&>(*evaluatedProperties).evaluated; const auto& evaluated = static_cast<const LineLayerProperties&>(*evaluatedProperties).evaluated;
const auto& crossfade = static_cast<const LineLayerProperties&>(*evaluatedProperties).crossfade; const auto& crossfade = static_cast<const LineLayerProperties&>(*evaluatedProperties).crossfade;
const LinePropertiesUBO linePropertiesUBO{ const auto getLinePropsBuffer = [&]() {
/*color =*/evaluated.get<LineColor>().constantOr(LineColor::defaultValue()), if (!linePropertiesBuffer) {
/*blur =*/evaluated.get<LineBlur>().constantOr(LineBlur::defaultValue()), const LinePropertiesUBO linePropertiesUBO{
/*opacity =*/evaluated.get<LineOpacity>().constantOr(LineOpacity::defaultValue()), /*color =*/evaluated.get<LineColor>().constantOr(LineColor::defaultValue()),
/*gapwidth =*/evaluated.get<LineGapWidth>().constantOr(LineGapWidth::defaultValue()), /*blur =*/evaluated.get<LineBlur>().constantOr(LineBlur::defaultValue()),
/*offset =*/evaluated.get<LineOffset>().constantOr(LineOffset::defaultValue()), /*opacity =*/evaluated.get<LineOpacity>().constantOr(LineOpacity::defaultValue()),
/*width =*/evaluated.get<LineWidth>().constantOr(LineWidth::defaultValue()), /*gapwidth =*/evaluated.get<LineGapWidth>().constantOr(LineGapWidth::defaultValue()),
0, /*offset =*/evaluated.get<LineOffset>().constantOr(LineOffset::defaultValue()),
{0, 0}}; /*width =*/evaluated.get<LineWidth>().constantOr(LineWidth::defaultValue()),
const LineGradientPropertiesUBO lineGradientPropertiesUBO{ 0,
/*blur =*/evaluated.get<LineBlur>().constantOr(LineBlur::defaultValue()), {0, 0}};
/*opacity =*/evaluated.get<LineOpacity>().constantOr(LineOpacity::defaultValue()), linePropertiesBuffer = context.createUniformBuffer(&linePropertiesUBO, sizeof(linePropertiesUBO));
/*gapwidth =*/evaluated.get<LineGapWidth>().constantOr(LineGapWidth::defaultValue()), }
/*offset =*/evaluated.get<LineOffset>().constantOr(LineOffset::defaultValue()), return linePropertiesBuffer;
/*width =*/evaluated.get<LineWidth>().constantOr(LineWidth::defaultValue()), };
0, const auto getLineGradientPropsBuffer = [&]() {
{0, 0}}; if (!lineGradientPropertiesBuffer) {
const LineSDFPropertiesUBO lineSDFPropertiesUBO{ const LineGradientPropertiesUBO lineGradientPropertiesUBO{
/*color =*/evaluated.get<LineColor>().constantOr(LineColor::defaultValue()), /*blur =*/evaluated.get<LineBlur>().constantOr(LineBlur::defaultValue()),
/*blur =*/evaluated.get<LineBlur>().constantOr(LineBlur::defaultValue()), /*opacity =*/evaluated.get<LineOpacity>().constantOr(LineOpacity::defaultValue()),
/*opacity =*/evaluated.get<LineOpacity>().constantOr(LineOpacity::defaultValue()), /*gapwidth =*/evaluated.get<LineGapWidth>().constantOr(LineGapWidth::defaultValue()),
/*gapwidth =*/evaluated.get<LineGapWidth>().constantOr(LineGapWidth::defaultValue()), /*offset =*/evaluated.get<LineOffset>().constantOr(LineOffset::defaultValue()),
/*offset =*/evaluated.get<LineOffset>().constantOr(LineOffset::defaultValue()), /*width =*/evaluated.get<LineWidth>().constantOr(LineWidth::defaultValue()),
/*width =*/evaluated.get<LineWidth>().constantOr(LineWidth::defaultValue()), 0,
/*floorwidth =*/evaluated.get<LineFloorWidth>().constantOr(LineFloorWidth::defaultValue()), {0, 0}};
{0, 0}}; lineGradientPropertiesBuffer = context.createUniformBuffer(&lineGradientPropertiesUBO,
sizeof(lineGradientPropertiesUBO));
}
return lineGradientPropertiesBuffer;
};
const auto getLineSDFPropsBuffer = [&]() {
if (!lineSDFPropertiesBuffer) {
const LineSDFPropertiesUBO lineSDFPropertiesUBO{
/*color =*/evaluated.get<LineColor>().constantOr(LineColor::defaultValue()),
/*blur =*/evaluated.get<LineBlur>().constantOr(LineBlur::defaultValue()),
/*opacity =*/evaluated.get<LineOpacity>().constantOr(LineOpacity::defaultValue()),
/*gapwidth =*/evaluated.get<LineGapWidth>().constantOr(LineGapWidth::defaultValue()),
/*offset =*/evaluated.get<LineOffset>().constantOr(LineOffset::defaultValue()),
/*width =*/evaluated.get<LineWidth>().constantOr(LineWidth::defaultValue()),
/*floorwidth =*/evaluated.get<LineFloorWidth>().constantOr(LineFloorWidth::defaultValue()),
{0, 0}};
lineSDFPropertiesBuffer = context.createUniformBuffer(&lineSDFPropertiesUBO, sizeof(lineSDFPropertiesUBO));
}
return lineSDFPropertiesBuffer;
};
layerGroup.observeDrawables([&](gfx::Drawable& drawable) { layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
const auto shader = drawable.getShader(); const auto shader = drawable.getShader();
@@ -175,11 +195,10 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup,
/*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]}, /*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]},
/*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom())), /*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom())),
/*device_pixel_ratio = */ parameters.pixelRatio}; /*device_pixel_ratio = */ parameters.pixelRatio};
uniforms.createOrUpdate(LineUBOName, &lineUBO, sizeof(lineUBO), parameters.context); uniforms.createOrUpdate(LineUBOName, &lineUBO, context);
// properties UBO // properties UBO
uniforms.createOrUpdate( uniforms.addOrReplace(LinePropertiesUBOName, getLinePropsBuffer());
LinePropertiesUBOName, &linePropertiesUBO, sizeof(linePropertiesUBO), parameters.context);
} }
// gradient line // gradient line
else if (shaderUniforms.get(std::string(LineGradientUBOName))) { else if (shaderUniforms.get(std::string(LineGradientUBOName))) {
@@ -189,13 +208,10 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup,
/*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]}, /*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]},
/*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom())), /*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom())),
/*device_pixel_ratio = */ parameters.pixelRatio}; /*device_pixel_ratio = */ parameters.pixelRatio};
uniforms.createOrUpdate(LineGradientUBOName, &lineGradientUBO, sizeof(lineGradientUBO), parameters.context); uniforms.createOrUpdate(LineGradientUBOName, &lineGradientUBO, context);
// properties UBO // properties UBO
uniforms.createOrUpdate(LineGradientPropertiesUBOName, uniforms.addOrReplace(LineGradientPropertiesUBOName, getLineGradientPropsBuffer());
&lineGradientPropertiesUBO,
sizeof(lineGradientPropertiesUBO),
parameters.context);
} }
// pattern line // pattern line
else if (shaderUniforms.get(std::string(LinePatternUBOName))) { else if (shaderUniforms.get(std::string(LinePatternUBOName))) {
@@ -219,7 +235,7 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup,
/*device_pixel_ratio =*/parameters.pixelRatio, /*device_pixel_ratio =*/parameters.pixelRatio,
/*fade =*/crossfade.t, /*fade =*/crossfade.t,
0}; 0};
uniforms.createOrUpdate(LinePatternUBOName, &linePatternUBO, sizeof(linePatternUBO), parameters.context); uniforms.createOrUpdate(LinePatternUBOName, &linePatternUBO, context);
// properties UBO // properties UBO
const LinePatternPropertiesUBO linePatternPropertiesUBO{ const LinePatternPropertiesUBO linePatternPropertiesUBO{
@@ -230,10 +246,7 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup,
/*width =*/evaluated.get<LineWidth>().constantOr(LineWidth::defaultValue()), /*width =*/evaluated.get<LineWidth>().constantOr(LineWidth::defaultValue()),
0, 0,
{0, 0}}; {0, 0}};
uniforms.createOrUpdate(LinePatternPropertiesUBOName, uniforms.createOrUpdate(LinePatternPropertiesUBOName, &linePatternPropertiesUBO, context);
&linePatternPropertiesUBO,
sizeof(linePatternPropertiesUBO),
parameters.context);
} }
// SDF line // SDF line
else if (shaderUniforms.get(std::string(LineSDFUBOName))) { else if (shaderUniforms.get(std::string(LineSDFUBOName))) {
@@ -273,11 +286,10 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup,
/* sdfgamma = */ static_cast<float>(dashPatternTexture.getSize().width) / /* sdfgamma = */ static_cast<float>(dashPatternTexture.getSize().width) /
(std::min(widthA, widthB) * 256.0f * parameters.pixelRatio) / 2.0f, (std::min(widthA, widthB) * 256.0f * parameters.pixelRatio) / 2.0f,
/* mix = */ crossfade.t}; /* mix = */ crossfade.t};
uniforms.createOrUpdate(LineSDFUBOName, &lineSDFUBO, sizeof(lineSDFUBO), parameters.context); uniforms.createOrUpdate(LineSDFUBOName, &lineSDFUBO, context);
// properties UBO // properties UBO
uniforms.createOrUpdate( uniforms.addOrReplace(LineSDFPropertiesUBOName, getLineSDFPropsBuffer());
LineSDFPropertiesUBOName, &lineSDFPropertiesUBO, sizeof(lineSDFPropertiesUBO), parameters.context);
} }
} }
}); });

View File

@@ -19,10 +19,14 @@ public:
LineLayerTweaker(Immutable<style::LayerProperties> properties) LineLayerTweaker(Immutable<style::LayerProperties> properties)
: LayerTweaker(properties){}; : LayerTweaker(properties){};
public:
~LineLayerTweaker() override = default; ~LineLayerTweaker() override = default;
void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override;
protected:
gfx::UniformBufferPtr linePropertiesBuffer;
gfx::UniformBufferPtr lineGradientPropertiesBuffer;
gfx::UniformBufferPtr lineSDFPropertiesBuffer;
}; };
} // namespace mbgl } // namespace mbgl

View File

@@ -38,7 +38,7 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup,
const auto& evaluated = static_cast<const RasterLayerProperties&>(*evaluatedProperties).evaluated; const auto& evaluated = static_cast<const RasterLayerProperties&>(*evaluatedProperties).evaluated;
layerGroup.observeDrawables([&](gfx::Drawable& drawable) { layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
auto spinWeights = [](float spin) -> std::array<float, 4> { const auto spinWeights = [](float spin) -> std::array<float, 4> {
spin = util::deg2radf(spin); spin = util::deg2radf(spin);
const float s = std::sin(spin); const float s = std::sin(spin);
const float c = std::cos(spin); const float c = std::cos(spin);
@@ -46,14 +46,14 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup,
{(2 * c + 1) / 3, (-std::sqrt(3.0f) * s - c + 1) / 3, (std::sqrt(3.0f) * s - c + 1) / 3, 0}}; {(2 * c + 1) / 3, (-std::sqrt(3.0f) * s - c + 1) / 3, (std::sqrt(3.0f) * s - c + 1) / 3, 0}};
return spin_weights; return spin_weights;
}; };
auto saturationFactor = [](float saturation) -> float { const auto saturationFactor = [](float saturation) -> float {
if (saturation > 0) { if (saturation > 0) {
return 1.f - 1.f / (1.001f - saturation); return 1.f - 1.f / (1.001f - saturation);
} else { } else {
return -saturation; return -saturation;
} }
}; };
auto contrastFactor = [](float contrast) -> float { const auto contrastFactor = [](float contrast) -> float {
if (contrast > 0) { if (contrast > 0) {
return 1 / (1 - contrast); return 1 / (1 - contrast);
} else { } else {
@@ -93,7 +93,7 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup,
0, 0,
0}; 0};
auto& uniforms = drawable.mutableUniformBuffers(); auto& uniforms = drawable.mutableUniformBuffers();
uniforms.createOrUpdate("RasterDrawableUBO", &drawableUBO, sizeof(drawableUBO), parameters.context); uniforms.createOrUpdate("RasterDrawableUBO", &drawableUBO, parameters.context);
}); });
} }

View File

@@ -352,14 +352,17 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
std::get<0>(paintPropertyBinders.get<CircleStrokeOpacity>()->interpolationFactor(zoom)), std::get<0>(paintPropertyBinders.get<CircleStrokeOpacity>()->interpolationFactor(zoom)),
/* .padding = */ 0}; /* .padding = */ 0};
tileLayerGroup->observeDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { // If there are already drawables for this tile, update their UBOs and move on to the next tile.
drawable.mutableUniformBuffers().createOrUpdate(CircleInterpolateUBOName, &interpolateUBO, context); auto updateExisting = [&](gfx::Drawable& drawable) {
}); auto& uniforms = drawable.mutableUniformBuffers();
uniforms.createOrUpdate(CircleInterpolateUBOName, &interpolateUBO, context);
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) { };
if (0 < tileLayerGroup->observeDrawables(renderPass, tileID, std::move(updateExisting))) {
continue; continue;
} }
const auto interpBuffer = context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO));
gfx::VertexAttributeArray circleVertexAttrs; gfx::VertexAttributeArray circleVertexAttrs;
const auto propertiesAsUniforms = circleVertexAttrs.readDataDrivenPaintProperties<CircleColor, const auto propertiesAsUniforms = circleVertexAttrs.readDataDrivenPaintProperties<CircleColor,
CircleRadius, CircleRadius,
@@ -400,7 +403,9 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
for (auto& drawable : circleBuilder->clearDrawables()) { for (auto& drawable : circleBuilder->clearDrawables()) {
drawable->setTileID(tileID); drawable->setTileID(tileID);
drawable->mutableUniformBuffers().createOrUpdate(CircleInterpolateUBOName, &interpolateUBO, context);
auto& uniforms = drawable->mutableUniformBuffers();
uniforms.addOrReplace(CircleInterpolateUBOName, interpBuffer);
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
++stats.drawablesAdded; ++stats.drawablesAdded;

View File

@@ -399,25 +399,25 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
/* .padding = */ 0, /* .padding = */ 0,
0}; 0};
// TODO: only update if properties re-evaluated?
const FillDrawableTilePropsUBO tileProps = { const FillDrawableTilePropsUBO tileProps = {
/* pattern_from = */ patternPosA ? util::cast<float>(patternPosA->tlbr()) : std::array<float, 4>{0}, /* 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}, /* pattern_to = */ patternPosB ? util::cast<float>(patternPosB->tlbr()) : std::array<float, 4>{0},
}; };
// If we already have drawables for this tile, update them. // If we already have drawables for this tile, update them.
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) { auto updateExisting = [&](gfx::Drawable& drawable) {
// TODO: Share buffers auto& uniforms = drawable.mutableUniformBuffers();
tileLayerGroup->observeDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { uniforms.createOrUpdate(FillLayerTweaker::FillInterpolateUBOName, &interpolateUBO, context);
drawable.mutableUniformBuffers().createOrUpdate( uniforms.createOrUpdate(FillLayerTweaker::FillTilePropsUBOName, &tileProps, context);
FillLayerTweaker::FillInterpolateUBOName, &interpolateUBO, context); };
drawable.mutableUniformBuffers().createOrUpdate( if (0 < tileLayerGroup->observeDrawables(renderPass, tileID, std::move(updateExisting))) {
FillLayerTweaker::FillTilePropsUBOName, &tileProps, context);
});
continue; 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` // `Fill*Program` all use `style::FillPaintProperties`
gfx::VertexAttributeArray vertexAttrs; gfx::VertexAttributeArray vertexAttrs;
const auto uniformProps = const auto uniformProps =

View File

@@ -121,11 +121,11 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup,
const auto isText = (symbolData.symbolType == SymbolType::Text); const auto isText = (symbolData.symbolType == SymbolType::Text);
if (isText && !textPaintBuffer) { if (isText && !textPaintBuffer) {
auto props = buildPaintUBO(true, evaluated); const auto props = buildPaintUBO(true, evaluated);
textPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props)); textPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props));
} }
if (!isText && !iconPaintBuffer) { if (!isText && !iconPaintBuffer) {
auto props = buildPaintUBO(false, evaluated); const auto props = buildPaintUBO(false, evaluated);
iconPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props)); iconPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props));
} }

View File

@@ -83,18 +83,20 @@ void TileLayerGroup::addDrawable(mbgl::RenderPass pass, const OverscaledTileID&
} }
} }
void TileLayerGroup::observeDrawables(const std::function<void(gfx::Drawable&)>&& f) { std::size_t TileLayerGroup::observeDrawables(const std::function<void(gfx::Drawable&)>&& f) {
assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); assert(impl->drawablesByTile.size() == impl->sortedDrawables.size());
for (auto* drawable : impl->sortedDrawables) { for (auto* drawable : impl->sortedDrawables) {
f(*drawable); f(*drawable);
} }
return impl->sortedDrawables.size();
} }
void TileLayerGroup::observeDrawables(const std::function<void(const gfx::Drawable&)>&& f) const { std::size_t TileLayerGroup::observeDrawables(const std::function<void(const gfx::Drawable&)>&& f) const {
assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); assert(impl->drawablesByTile.size() == impl->sortedDrawables.size());
for (const auto* drawable : impl->sortedDrawables) { for (const auto* drawable : impl->sortedDrawables) {
f(*drawable); f(*drawable);
} }
return impl->sortedDrawables.size();
} }
std::size_t TileLayerGroup::observeDrawablesRemove(const std::function<bool(gfx::Drawable&)>&& f) { std::size_t TileLayerGroup::observeDrawablesRemove(const std::function<bool(gfx::Drawable&)>&& f) {
@@ -114,20 +116,22 @@ std::size_t TileLayerGroup::observeDrawablesRemove(const std::function<bool(gfx:
return (oldSize - impl->drawablesByTile.size()); return (oldSize - impl->drawablesByTile.size());
} }
void TileLayerGroup::observeDrawables(mbgl::RenderPass pass, std::size_t TileLayerGroup::observeDrawables(mbgl::RenderPass pass,
const OverscaledTileID& tileID, const OverscaledTileID& tileID,
const std::function<void(gfx::Drawable&)>&& f) { const std::function<void(gfx::Drawable&)>&& f) {
assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); assert(impl->drawablesByTile.size() == impl->sortedDrawables.size());
const auto range = impl->drawablesByTile.equal_range({pass, tileID}); const auto range = impl->drawablesByTile.equal_range({pass, tileID});
std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); }); std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); });
return std::distance(range.first, range.second);
} }
void TileLayerGroup::observeDrawables(mbgl::RenderPass pass, std::size_t TileLayerGroup::observeDrawables(mbgl::RenderPass pass,
const OverscaledTileID& tileID, const OverscaledTileID& tileID,
const std::function<void(const gfx::Drawable&)>&& f) const { const std::function<void(const gfx::Drawable&)>&& f) const {
assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); assert(impl->drawablesByTile.size() == impl->sortedDrawables.size());
const auto range = impl->drawablesByTile.equal_range({pass, tileID}); const auto range = impl->drawablesByTile.equal_range({pass, tileID});
std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); }); std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); });
return std::distance(range.first, range.second);
} }
std::size_t TileLayerGroup::clearDrawables() { std::size_t TileLayerGroup::clearDrawables() {

View File

@@ -378,7 +378,8 @@ void GeometryTileWorker::parse() {
continue; continue;
} }
std::vector<std::string> layerIDs(group.size()); std::vector<std::string> layerIDs;
layerIDs.reserve(group.size());
for (const auto& layer : group) { for (const auto& layer : group) {
layerIDs.push_back(layer->baseImpl->id); layerIDs.push_back(layer->baseImpl->id);
} }