shared data-driven attributes (#1325)

This commit is contained in:
Tim Sylvester
2023-07-11 08:36:53 -07:00
committed by Bart Louwers
parent a288b1ffad
commit 95f0cbed33
10 changed files with 146 additions and 58 deletions

View File

@@ -1,7 +1,6 @@
#pragma once
#include <mbgl/gfx/uniform_buffer.hpp>
#include <mbgl/gfx/vertex_attribute.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/identity.hpp>
@@ -28,9 +27,11 @@ enum class DepthMaskType : bool;
class DrawableTweaker;
class DrawMode;
class ShaderProgramBase;
using ShaderProgramBasePtr = std::shared_ptr<ShaderProgramBase>;
class VertexAttributeArray;
using DrawPriority = int64_t;
using DrawableTweakerPtr = std::shared_ptr<DrawableTweaker>;
using ShaderProgramBasePtr = std::shared_ptr<ShaderProgramBase>;
using Texture2DPtr = std::shared_ptr<Texture2D>;
class Drawable {
@@ -160,16 +161,6 @@ public:
virtual const gfx::UniformBufferArray& getUniformBuffers() const = 0;
virtual gfx::UniformBufferArray& mutableUniformBuffers() = 0;
/// Convert from the odd partially-normalized color component array produced by `Color::toArray` into normalized
/// RGBA.
static gfx::VertexAttribute::float4 colorAttrRGBA(const Color& color) {
const auto components = color.toArray();
return {static_cast<float>(components[0] / 255.0),
static_cast<float>(components[1] / 255.0),
static_cast<float>(components[2] / 255.0),
static_cast<float>(components[3])};
}
const UniqueDrawableData& getData() const { return drawableData; }
void setData(UniqueDrawableData&& value) { drawableData = std::move(value); }

View File

@@ -2,7 +2,6 @@
#include <mbgl/gfx/drawable.hpp>
#include <mbgl/gfx/types.hpp>
#include <mbgl/gfx/vertex_attribute.hpp>
#include <array>
#include <memory>
@@ -16,6 +15,7 @@ namespace gfx {
class DrawableTweaker;
class ShaderProgramBase;
class VertexAttributeArray;
using DrawableTweakerPtr = std::shared_ptr<DrawableTweaker>;
using ShaderProgramBasePtr = std::shared_ptr<ShaderProgramBase>;
@@ -100,7 +100,7 @@ public:
void setShader(gfx::ShaderProgramBasePtr value) { shader = std::move(value); }
/// Get the vertex attributes that override default values in the shader program
const gfx::VertexAttributeArray& getVertexAttributes() const { return vertexAttrs; }
const gfx::VertexAttributeArray& getVertexAttributes() const;
/// Set the name given to new drawables
void setDrawableName(std::string value) { drawableName = std::move(value); }
@@ -180,7 +180,6 @@ protected:
gfx::ShaderProgramBasePtr shader;
UniqueDrawable currentDrawable;
std::vector<UniqueDrawable> drawables;
VertexAttributeArray vertexAttrs;
gfx::Drawable::Textures textures;
std::vector<DrawableTweakerPtr> tweakers;

View File

@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/gfx/gfx_types.hpp>
#include <mbgl/renderer/paint_property_binder.hpp>
#include <algorithm>
#include <array>
@@ -149,6 +150,16 @@ public:
}
void resetSharedRawData() { sharedRawData.reset(); }
/// Convert from the odd partially-normalized color component array produced by `Color::toArray` into normalized
/// RGBA.
static float4 colorAttrRGBA(const Color& color) {
const auto components = color.toArray();
return {static_cast<float>(components[0] / 255.0),
static_cast<float>(components[1] / 255.0),
static_cast<float>(components[2] / 255.0),
static_cast<float>(components[3])};
}
protected:
VertexAttribute& operator=(const VertexAttribute&) = default;
VertexAttribute& operator=(VertexAttribute&& other) {
@@ -271,20 +282,37 @@ public:
template <class... DataDrivenPaintProperty, class Binders, class Evaluated>
std::vector<std::string> readDataDrivenPaintProperties(const Binders& binders, const Evaluated& evaluated) {
std::vector<std::string> propertiesAsUniforms;
propertiesAsUniforms.reserve(sizeof...(DataDrivenPaintProperty));
(
[&](const auto& attributeNames) {
for (std::size_t attrIndex = 0; attrIndex < attributeNames.size(); ++attrIndex) {
const auto& attributeName = std::string(attributeNames[attrIndex]);
if (auto& binder = binders.template get<DataDrivenPaintProperty>()) {
using Attribute = typename DataDrivenPaintProperty::Attribute;
using Type = typename Attribute::Type; // ::mbgl::gfx::AttributeType<type_, n_>
using Value = typename Type::Value; // std::array<T, N>
using InterpType = ZoomInterpolatedAttributeType<Type>;
using InterpValue = typename InterpType::Value; // std::array<T, 2*N>
const auto vertexCount = binder->getVertexCount();
const auto isConstant = evaluated.template get<DataDrivenPaintProperty>().isConstant();
if (vertexCount > 0 && !isConstant) {
if (auto& attr = getOrAdd("a_" + attributeName)) {
for (std::size_t i = 0; i < vertexCount; ++i) {
attr->set(i, binder->getVertexValue(i), attrIndex);
if (const auto& sharedVector = binder->getSharedVertexVector()) {
const auto rawSize = static_cast<uint32_t>(sharedVector->getRawSize());
const bool isInterpolated = binder->isInterpolated();
const auto dataType = isInterpolated ? InterpType::DataType : Type::DataType;
assert(rawSize ==
static_cast<uint32_t>(isInterpolated ? sizeof(InterpValue) : sizeof(Value)));
assert(sharedVector->getRawCount() == vertexCount);
attr->setSharedRawData(std::move(sharedVector), 0, 0, rawSize, dataType);
} else {
for (std::size_t i = 0; i < vertexCount; ++i) {
attr->set(i, binder->getVertexValue(i), attrIndex);
}
}
}
propertiesAsUniforms.emplace_back("");
propertiesAsUniforms.emplace_back(std::string());
} else {
propertiesAsUniforms.emplace_back(attributeName);
}

View File

@@ -2,6 +2,7 @@
#include <mbgl/gfx/drawable_builder_impl.hpp>
#include <mbgl/gfx/drawable_impl.hpp>
#include <mbgl/gfx/vertex_attribute.hpp>
#include <mbgl/renderer/render_pass.hpp>
#include <mbgl/util/logging.hpp>
@@ -11,7 +12,7 @@ namespace gfx {
DrawableBuilder::DrawableBuilder(std::string name_)
: name(std::move(name_)),
vertexAttrName("a_pos"),
renderPass(RenderPass::Opaque),
renderPass(mbgl::RenderPass::Opaque),
impl(std::make_unique<Impl>()) {}
DrawableBuilder::~DrawableBuilder() = default;
@@ -30,6 +31,10 @@ void DrawableBuilder::setCullFaceMode(const gfx::CullFaceMode& value) {
impl->cullFaceMode = value;
}
const gfx::VertexAttributeArray& DrawableBuilder::getVertexAttributes() const {
return impl->vertexAttrs;
}
UniqueDrawable& DrawableBuilder::getCurrentDrawable(bool createIfNone) {
if (!currentDrawable && createIfNone) {
currentDrawable = createDrawable();
@@ -125,11 +130,11 @@ void DrawableBuilder::addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1) {
}
void DrawableBuilder::setVertexAttributes(const VertexAttributeArray& attrs) {
vertexAttrs = attrs;
impl->vertexAttrs = attrs;
}
void DrawableBuilder::setVertexAttributes(VertexAttributeArray&& attrs) {
vertexAttrs = std::move(attrs);
impl->vertexAttrs = std::move(attrs);
}
std::size_t DrawableBuilder::addVertices(const std::vector<std::array<int16_t, 2>>& vertices,

View File

@@ -2,6 +2,7 @@
#include <mbgl/gfx/color_mode.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gfx/index_vector.hpp>
#include <mbgl/gfx/vertex_attribute.hpp>
#include <mbgl/gfx/vertex_vector.hpp>
#include <mbgl/programs/segment.hpp>
@@ -24,6 +25,8 @@ struct DrawableBuilder::Impl {
AttributeDataType rawVerticesType = static_cast<AttributeDataType>(-1);
gfx::ColorMode colorMode = gfx::ColorMode::disabled();
gfx::CullFaceMode cullFaceMode = gfx::CullFaceMode::disabled();
VertexAttributeArray vertexAttrs;
};
} // namespace gfx

View File

@@ -105,5 +105,8 @@ private:
std::vector<Vertex> v;
};
template <typename T>
using VertexVectorPtr = std::shared_ptr<VertexVector<T>>;
} // namespace gfx
} // namespace mbgl

View File

@@ -80,7 +80,7 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup,
// UBO depends on more than just evaluated properties, so we need to update every time.
const FillExtrusionDrawablePropsUBO paramsUBO = {
/* .color = */ gfx::Drawable::colorAttrRGBA(constOrDefault<FillExtrusionColor>(evaluated)),
/* .color = */ gfx::VertexAttribute::colorAttrRGBA(constOrDefault<FillExtrusionColor>(evaluated)),
/* .light_color = */ FillExtrusionProgram::lightColor(parameters.evaluatedLight),
/* .pad = */ 0,
/* .light_position = */ FillExtrusionProgram::lightPosition(parameters.evaluatedLight, state),

View File

@@ -80,11 +80,11 @@ auto constOrDefault(const IndexedTuple<TypeList<Is...>, TypeList<Ts...>>& evalua
SymbolDrawablePaintUBO buildPaintUBO(bool isText, const SymbolPaintProperties::PossiblyEvaluated& evaluated) {
return {
/*.fill_color=*/gfx::Drawable::colorAttrRGBA(isText ? constOrDefault<TextColor>(evaluated)
: constOrDefault<IconColor>(evaluated)),
/*.fill_color=*/gfx::VertexAttribute::colorAttrRGBA(isText ? constOrDefault<TextColor>(evaluated)
: constOrDefault<IconColor>(evaluated)),
/*.halo_color=*/
gfx::Drawable::colorAttrRGBA(isText ? constOrDefault<TextHaloColor>(evaluated)
: constOrDefault<IconHaloColor>(evaluated)),
gfx::VertexAttribute::colorAttrRGBA(isText ? constOrDefault<TextHaloColor>(evaluated)
: constOrDefault<IconHaloColor>(evaluated)),
/*.opacity=*/isText ? constOrDefault<TextOpacity>(evaluated) : constOrDefault<IconOpacity>(evaluated),
/*.halo_width=*/
isText ? constOrDefault<TextHaloWidth>(evaluated) : constOrDefault<IconHaloWidth>(evaluated),

View File

@@ -120,25 +120,38 @@ public:
virtual void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) = 0;
#if MLN_LEGACY_RENDERER
virtual void upload(gfx::UploadPass&) = 0;
virtual std::tuple<ExpandToType<As, std::optional<gfx::AttributeBinding>>...> attributeBinding(
const PossiblyEvaluatedType& currentValue) const = 0;
#endif // MLN_LEGACY_RENDERER
virtual void setPatternParameters(const std::optional<ImagePosition>&,
const std::optional<ImagePosition>&,
const CrossfadeParameters&) = 0;
virtual std::tuple<ExpandToType<As, std::optional<gfx::AttributeBinding>>...> attributeBinding(
const PossiblyEvaluatedType& currentValue) const = 0;
virtual std::tuple<ExpandToType<As, float>...> interpolationFactor(float currentZoom) const = 0;
virtual std::tuple<ExpandToType<As, UniformValueType>...> uniformValue(
const PossiblyEvaluatedType& currentValue) const = 0;
virtual std::size_t getVertexCount() const = 0;
/// Indicates that the vertex data is duplicated for interpolation
virtual bool isInterpolated() const { return false; }
virtual std::tuple<ZoomInterpolatedVertexType<As>...> getVertexValue(std::size_t index) const = 0;
virtual gfx::VertexVectorBasePtr getSharedVertexVector() const = 0;
static std::unique_ptr<PaintPropertyBinder> create(const PossiblyEvaluatedType& value, float zoom, T defaultValue);
PaintPropertyStatistics<T> statistics;
};
namespace detail {
const gfx::VertexVectorBasePtr noVector;
}
template <class T, class A>
class ConstantPaintPropertyBinder : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
public:
@@ -153,15 +166,19 @@ public:
const CanonicalTileID&,
const style::expression::Value&) override {}
void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {}
#if MLN_LEGACY_RENDERER
void upload(gfx::UploadPass&) override {}
void setPatternParameters(const std::optional<ImagePosition>&,
const std::optional<ImagePosition>&,
const CrossfadeParameters&) override{};
std::tuple<std::optional<gfx::AttributeBinding>> attributeBinding(
const PossiblyEvaluatedPropertyValue<T>&) const override {
return {};
}
#endif // MLN_LEGACY_RENDERER
void setPatternParameters(const std::optional<ImagePosition>&,
const std::optional<ImagePosition>&,
const CrossfadeParameters&) override{};
std::tuple<float> interpolationFactor(float) const override { return std::tuple<float>{0.0f}; }
@@ -178,6 +195,8 @@ public:
return {ZoomInterpolatedVertexType<A>{0}};
}
gfx::VertexVectorBasePtr getSharedVertexVector() const override { return detail::noVector; }
private:
T constant;
mutable BaseVertex convertedValue;
@@ -199,8 +218,16 @@ public:
const CanonicalTileID&,
const style::expression::Value&) override {}
void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {}
#if MLN_LEGACY_RENDERER
void upload(gfx::UploadPass&) override {}
std::tuple<std::optional<gfx::AttributeBinding>, std::optional<gfx::AttributeBinding>> attributeBinding(
const PossiblyEvaluatedPropertyValue<Faded<T>>&) const override {
return {};
}
#endif // MLN_LEGACY_RENDERER
void setPatternParameters(const std::optional<ImagePosition>& posA,
const std::optional<ImagePosition>& posB,
const CrossfadeParameters&) override {
@@ -212,11 +239,6 @@ public:
}
}
std::tuple<std::optional<gfx::AttributeBinding>, std::optional<gfx::AttributeBinding>> attributeBinding(
const PossiblyEvaluatedPropertyValue<Faded<T>>&) const override {
return {};
}
std::tuple<float, float> interpolationFactor(float) const override { return std::tuple<float, float>{0.0f, 0.0f}; }
std::tuple<std::array<uint16_t, 4>, std::array<uint16_t, 4>> uniformValue(
@@ -230,6 +252,8 @@ public:
return {ZoomInterpolatedVertexType<As>{0}...};
}
gfx::VertexVectorBasePtr getSharedVertexVector() const override { return detail::noVector; }
private:
Faded<T> constant;
std::tuple<std::array<uint16_t, 4>, std::array<uint16_t, 4>> constantPatternPositions;
@@ -244,6 +268,8 @@ public:
SourceFunctionPaintPropertyBinder(style::PropertyExpression<T> expression_, T defaultValue_)
: expression(std::move(expression_)),
defaultValue(std::move(defaultValue_)) {}
~SourceFunctionPaintPropertyBinder() override { sharedVertexVector->release(); }
void setPatternParameters(const std::optional<ImagePosition>&,
const std::optional<ImagePosition>&,
const CrossfadeParameters&) override{};
@@ -302,11 +328,8 @@ public:
}
}
void upload([[maybe_unused]] gfx::UploadPass& uploadPass) override {
#if MLN_LEGACY_RENDERER
vertexBuffer = uploadPass.createVertexBuffer(std::move(vertexVector));
#endif // MLN_LEGACY_RENDERER
}
void upload(gfx::UploadPass& uploadPass) override { vertexBuffer = uploadPass.createVertexBuffer(vertexVector); }
std::tuple<std::optional<gfx::AttributeBinding>> attributeBinding(
const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
@@ -316,6 +339,7 @@ public:
return std::tuple<std::optional<gfx::AttributeBinding>>{gfx::attributeBinding(*vertexBuffer)};
}
}
#endif // MLN_LEGACY_RENDERER
std::tuple<float> interpolationFactor(float) const override { return std::tuple<float>{0.0f}; }
@@ -335,11 +359,19 @@ public:
return {ZoomInterpolatedVertexType<A>{concatenate(value.a1, value.a1)}};
}
gfx::VertexVectorBasePtr getSharedVertexVector() const override { return sharedVertexVector; }
private:
style::PropertyExpression<T> expression;
T defaultValue;
gfx::VertexVector<BaseVertex> vertexVector;
gfx::VertexVectorPtr<BaseVertex> sharedVertexVector = std::make_shared<gfx::VertexVector<BaseVertex>>();
gfx::VertexVector<BaseVertex>& vertexVector = *sharedVertexVector;
#if MLN_LEGACY_RENDERER
std::optional<gfx::VertexBuffer<BaseVertex>> vertexBuffer;
#endif // MLN_LEGACY_RENDERER
FeatureVertexRangeMap featureMap;
};
@@ -355,6 +387,8 @@ public:
: expression(std::move(expression_)),
defaultValue(std::move(defaultValue_)),
zoomRange({zoom, zoom + 1}) {}
~CompositeFunctionPaintPropertyBinder() override { sharedVertexVector->release(); }
void setPatternParameters(const std::optional<ImagePosition>&,
const std::optional<ImagePosition>&,
const CrossfadeParameters&) override{};
@@ -378,13 +412,13 @@ public:
};
this->statistics.add(range.min);
this->statistics.add(range.max);
AttributeValue value = zoomInterpolatedAttributeValue(attributeValue(range.min), attributeValue(range.max));
auto elements = vertexVector.elements();
const AttributeValue value = zoomInterpolatedAttributeValue(attributeValue(range.min),
attributeValue(range.max));
const auto elements = vertexVector.elements();
for (std::size_t i = elements; i < length; ++i) {
vertexVector.emplace_back(Vertex{value});
}
std::optional<std::string> idStr = featureIDtoString(feature.getID());
if (idStr) {
if (auto idStr = featureIDtoString(feature.getID())) {
featureMap[*idStr].emplace_back(FeatureVertexRange{index, elements, length});
}
}
@@ -425,11 +459,8 @@ public:
}
}
void upload([[maybe_unused]] gfx::UploadPass& uploadPass) override {
#if MLN_LEGACY_RENDERER
vertexBuffer = uploadPass.createVertexBuffer(std::move(vertexVector));
#endif // MLN_LEGACY_RENDERER
}
void upload(gfx::UploadPass& uploadPass) override { vertexBuffer = uploadPass.createVertexBuffer(vertexVector); }
std::tuple<std::optional<gfx::AttributeBinding>> attributeBinding(
const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
@@ -439,6 +470,7 @@ public:
return std::tuple<std::optional<gfx::AttributeBinding>>{gfx::attributeBinding(*vertexBuffer)};
}
}
#endif // MLN_LEGACY_RENDERER
std::tuple<float> interpolationFactor(float currentZoom) const override {
const float possiblyRoundedZoom = expression.useIntegerZoom ? std::floor(currentZoom) : currentZoom;
@@ -458,6 +490,10 @@ public:
std::size_t getVertexCount() const override { return vertexVector.elements(); }
bool isInterpolated() const override { return true; }
gfx::VertexVectorBasePtr getSharedVertexVector() const override { return sharedVertexVector; }
std::tuple<ZoomInterpolatedVertexType<A>> getVertexValue(std::size_t index) const override {
return {vertexVector.at(index)};
}
@@ -466,8 +502,14 @@ private:
style::PropertyExpression<T> expression;
T defaultValue;
Range<float> zoomRange;
gfx::VertexVector<Vertex> vertexVector;
gfx::VertexVectorPtr<Vertex> sharedVertexVector = std::make_shared<gfx::VertexVector<Vertex>>();
gfx::VertexVector<Vertex>& vertexVector = *sharedVertexVector;
#if MLN_LEGACY_RENDERER
std::optional<gfx::VertexBuffer<Vertex>> vertexBuffer;
#endif // MLN_LEGACY_RENDERER
FeatureVertexRangeMap featureMap;
};
@@ -485,6 +527,7 @@ public:
: expression(std::move(expression_)),
defaultValue(std::move(defaultValue_)),
zoomRange({zoom, zoom + 1}) {}
~CompositeCrossFadedPaintPropertyBinder() override { sharedPatternToVertexVector->release(); }
void setPatternParameters(const std::optional<ImagePosition>&,
const std::optional<ImagePosition>&,
@@ -533,15 +576,14 @@ public:
void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {}
void upload([[maybe_unused]] gfx::UploadPass& uploadPass) override {
#if MLN_LEGACY_RENDERER
void upload(gfx::UploadPass& uploadPass) override {
if (!patternToVertexVector.empty()) {
assert(!zoomInVertexVector.empty());
assert(!zoomOutVertexVector.empty());
#if MLN_LEGACY_RENDERER
patternToVertexBuffer = uploadPass.createVertexBuffer(std::move(patternToVertexVector));
zoomInVertexBuffer = uploadPass.createVertexBuffer(std::move(zoomInVertexVector));
zoomOutVertexBuffer = uploadPass.createVertexBuffer(std::move(zoomOutVertexVector));
#endif // MLN_LEGACY_RENDERER
patternToVertexBuffer = uploadPass.createVertexBuffer(patternToVertexVector);
zoomInVertexBuffer = uploadPass.createVertexBuffer(zoomInVertexVector);
zoomOutVertexBuffer = uploadPass.createVertexBuffer(zoomOutVertexVector);
}
}
@@ -562,6 +604,7 @@ public:
std::nullopt};
}
}
#endif // MLN_LEGACY_RENDERER
std::tuple<float, float> interpolationFactor(float) const override { return std::tuple<float, float>{0.0f, 0.0f}; }
@@ -582,16 +625,25 @@ public:
ZoomInterpolatedVertexType<A2>{concatenate(zoomValue.a1, zoomValue.a1)}};
}
gfx::VertexVectorBasePtr getSharedVertexVector() const override { return sharedPatternToVertexVector; }
private:
style::PropertyExpression<T> expression;
T defaultValue;
Range<float> zoomRange;
gfx::VertexVector<Vertex> patternToVertexVector;
gfx::VertexVectorPtr<Vertex> sharedPatternToVertexVector = std::make_shared<gfx::VertexVector<Vertex>>();
gfx::VertexVector<Vertex>& patternToVertexVector = *sharedPatternToVertexVector;
gfx::VertexVector<Vertex2> zoomInVertexVector;
gfx::VertexVector<Vertex2> zoomOutVertexVector;
#if MLN_LEGACY_RENDERER
std::optional<gfx::VertexBuffer<Vertex>> patternToVertexBuffer;
std::optional<gfx::VertexBuffer<Vertex2>> zoomInVertexBuffer;
std::optional<gfx::VertexBuffer<Vertex2>> zoomOutVertexBuffer;
#endif // MLN_LEGACY_RENDERER
CrossfadeParameters crossfade;
};
@@ -716,7 +768,9 @@ public:
util::ignore({(binders.template get<Ps>()->setPatternParameters(posA, posB, crossfade), 0)...});
}
#if MLN_LEGACY_RENDERER
void upload(gfx::UploadPass& uploadPass) { util::ignore({(binders.template get<Ps>()->upload(uploadPass), 0)...}); }
#endif // MLN_LEGACY_RENDERER
template <class P>
using ZoomInterpolatedAttributeList = typename Property<P>::ZoomInterpolatedAttributeList;

View File

@@ -41,11 +41,15 @@ namespace mbgl {
using namespace style;
static RendererObserver& nullObserver() {
namespace {
RendererObserver& nullObserver() {
static RendererObserver observer;
return observer;
}
} // namespace
Renderer::Impl::Impl(gfx::RendererBackend& backend_,
float pixelRatio_,
const std::optional<std::string>& localFontFamily_)
@@ -65,6 +69,7 @@ void Renderer::Impl::setObserver(RendererObserver* observer_) {
void Renderer::Impl::preRender([[maybe_unused]] const RenderTree& renderTree,
[[maybe_unused]] const std::shared_ptr<UpdateParameters>& updateParameters) {
[[maybe_unused]] auto& context = backend.getContext();
// Blocks execution until the renderable is available.
backend.getDefaultRenderable().wait();