From 95f0cbed33316fd813a18f27665691c71536e912 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Tue, 11 Jul 2023 08:36:53 -0700 Subject: [PATCH] shared data-driven attributes (#1325) --- include/mbgl/gfx/drawable.hpp | 15 +-- include/mbgl/gfx/drawable_builder.hpp | 5 +- include/mbgl/gfx/vertex_attribute.hpp | 34 ++++- src/mbgl/gfx/drawable_builder.cpp | 11 +- src/mbgl/gfx/drawable_builder_impl.hpp | 3 + src/mbgl/gfx/vertex_vector.hpp | 3 + .../layers/fill_extrusion_layer_tweaker.cpp | 2 +- .../renderer/layers/symbol_layer_tweaker.cpp | 8 +- src/mbgl/renderer/paint_property_binder.hpp | 116 +++++++++++++----- src/mbgl/renderer/renderer_impl.cpp | 7 +- 10 files changed, 146 insertions(+), 58 deletions(-) diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 80c56ebd2..a5dc77842 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include #include @@ -28,9 +27,11 @@ enum class DepthMaskType : bool; class DrawableTweaker; class DrawMode; class ShaderProgramBase; -using ShaderProgramBasePtr = std::shared_ptr; +class VertexAttributeArray; + using DrawPriority = int64_t; using DrawableTweakerPtr = std::shared_ptr; +using ShaderProgramBasePtr = std::shared_ptr; using Texture2DPtr = std::shared_ptr; 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(components[0] / 255.0), - static_cast(components[1] / 255.0), - static_cast(components[2] / 255.0), - static_cast(components[3])}; - } - const UniqueDrawableData& getData() const { return drawableData; } void setData(UniqueDrawableData&& value) { drawableData = std::move(value); } diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index fedfb40d6..1fc575e29 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -16,6 +15,7 @@ namespace gfx { class DrawableTweaker; class ShaderProgramBase; +class VertexAttributeArray; using DrawableTweakerPtr = std::shared_ptr; using ShaderProgramBasePtr = std::shared_ptr; @@ -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 drawables; - VertexAttributeArray vertexAttrs; gfx::Drawable::Textures textures; std::vector tweakers; diff --git a/include/mbgl/gfx/vertex_attribute.hpp b/include/mbgl/gfx/vertex_attribute.hpp index d9f7fca08..9c6889510 100644 --- a/include/mbgl/gfx/vertex_attribute.hpp +++ b/include/mbgl/gfx/vertex_attribute.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -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(components[0] / 255.0), + static_cast(components[1] / 255.0), + static_cast(components[2] / 255.0), + static_cast(components[3])}; + } + protected: VertexAttribute& operator=(const VertexAttribute&) = default; VertexAttribute& operator=(VertexAttribute&& other) { @@ -271,20 +282,37 @@ public: template std::vector readDataDrivenPaintProperties(const Binders& binders, const Evaluated& evaluated) { std::vector 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()) { + using Attribute = typename DataDrivenPaintProperty::Attribute; + using Type = typename Attribute::Type; // ::mbgl::gfx::AttributeType + using Value = typename Type::Value; // std::array + using InterpType = ZoomInterpolatedAttributeType; + using InterpValue = typename InterpType::Value; // std::array + const auto vertexCount = binder->getVertexCount(); const auto isConstant = evaluated.template get().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(sharedVector->getRawSize()); + const bool isInterpolated = binder->isInterpolated(); + const auto dataType = isInterpolated ? InterpType::DataType : Type::DataType; + assert(rawSize == + static_cast(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); } diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index c80970f29..ec76d87a9 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -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()) {} 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>& vertices, diff --git a/src/mbgl/gfx/drawable_builder_impl.hpp b/src/mbgl/gfx/drawable_builder_impl.hpp index a321dac03..4ab943eb8 100644 --- a/src/mbgl/gfx/drawable_builder_impl.hpp +++ b/src/mbgl/gfx/drawable_builder_impl.hpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,8 @@ struct DrawableBuilder::Impl { AttributeDataType rawVerticesType = static_cast(-1); gfx::ColorMode colorMode = gfx::ColorMode::disabled(); gfx::CullFaceMode cullFaceMode = gfx::CullFaceMode::disabled(); + + VertexAttributeArray vertexAttrs; }; } // namespace gfx diff --git a/src/mbgl/gfx/vertex_vector.hpp b/src/mbgl/gfx/vertex_vector.hpp index faccbf9ad..1cb6b1a1f 100644 --- a/src/mbgl/gfx/vertex_vector.hpp +++ b/src/mbgl/gfx/vertex_vector.hpp @@ -105,5 +105,8 @@ private: std::vector v; }; +template +using VertexVectorPtr = std::shared_ptr>; + } // namespace gfx } // namespace mbgl diff --git a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp index d6137622c..416d72938 100644 --- a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp @@ -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(evaluated)), + /* .color = */ gfx::VertexAttribute::colorAttrRGBA(constOrDefault(evaluated)), /* .light_color = */ FillExtrusionProgram::lightColor(parameters.evaluatedLight), /* .pad = */ 0, /* .light_position = */ FillExtrusionProgram::lightPosition(parameters.evaluatedLight, state), diff --git a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp index 8c2dc8d08..7b332b96b 100644 --- a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp @@ -80,11 +80,11 @@ auto constOrDefault(const IndexedTuple, TypeList>& evalua SymbolDrawablePaintUBO buildPaintUBO(bool isText, const SymbolPaintProperties::PossiblyEvaluated& evaluated) { return { - /*.fill_color=*/gfx::Drawable::colorAttrRGBA(isText ? constOrDefault(evaluated) - : constOrDefault(evaluated)), + /*.fill_color=*/gfx::VertexAttribute::colorAttrRGBA(isText ? constOrDefault(evaluated) + : constOrDefault(evaluated)), /*.halo_color=*/ - gfx::Drawable::colorAttrRGBA(isText ? constOrDefault(evaluated) - : constOrDefault(evaluated)), + gfx::VertexAttribute::colorAttrRGBA(isText ? constOrDefault(evaluated) + : constOrDefault(evaluated)), /*.opacity=*/isText ? constOrDefault(evaluated) : constOrDefault(evaluated), /*.halo_width=*/ isText ? constOrDefault(evaluated) : constOrDefault(evaluated), diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp index da79e55ad..53aca7fa4 100644 --- a/src/mbgl/renderer/paint_property_binder.hpp +++ b/src/mbgl/renderer/paint_property_binder.hpp @@ -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>...> attributeBinding( + const PossiblyEvaluatedType& currentValue) const = 0; +#endif // MLN_LEGACY_RENDERER + virtual void setPatternParameters(const std::optional&, const std::optional&, const CrossfadeParameters&) = 0; - virtual std::tuple>...> attributeBinding( - const PossiblyEvaluatedType& currentValue) const = 0; virtual std::tuple...> interpolationFactor(float currentZoom) const = 0; virtual std::tuple...> 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...> getVertexValue(std::size_t index) const = 0; + virtual gfx::VertexVectorBasePtr getSharedVertexVector() const = 0; + static std::unique_ptr create(const PossiblyEvaluatedType& value, float zoom, T defaultValue); PaintPropertyStatistics statistics; }; +namespace detail { +const gfx::VertexVectorBasePtr noVector; +} + template class ConstantPaintPropertyBinder : public PaintPropertyBinder, 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&, - const std::optional&, - const CrossfadeParameters&) override{}; std::tuple> attributeBinding( const PossiblyEvaluatedPropertyValue&) const override { return {}; } +#endif // MLN_LEGACY_RENDERER + + void setPatternParameters(const std::optional&, + const std::optional&, + const CrossfadeParameters&) override{}; std::tuple interpolationFactor(float) const override { return std::tuple{0.0f}; } @@ -178,6 +195,8 @@ public: return {ZoomInterpolatedVertexType{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> attributeBinding( + const PossiblyEvaluatedPropertyValue>&) const override { + return {}; + } +#endif // MLN_LEGACY_RENDERER + void setPatternParameters(const std::optional& posA, const std::optional& posB, const CrossfadeParameters&) override { @@ -212,11 +239,6 @@ public: } } - std::tuple, std::optional> attributeBinding( - const PossiblyEvaluatedPropertyValue>&) const override { - return {}; - } - std::tuple interpolationFactor(float) const override { return std::tuple{0.0f, 0.0f}; } std::tuple, std::array> uniformValue( @@ -230,6 +252,8 @@ public: return {ZoomInterpolatedVertexType{0}...}; } + gfx::VertexVectorBasePtr getSharedVertexVector() const override { return detail::noVector; } + private: Faded constant; std::tuple, std::array> constantPatternPositions; @@ -244,6 +268,8 @@ public: SourceFunctionPaintPropertyBinder(style::PropertyExpression expression_, T defaultValue_) : expression(std::move(expression_)), defaultValue(std::move(defaultValue_)) {} + ~SourceFunctionPaintPropertyBinder() override { sharedVertexVector->release(); } + void setPatternParameters(const std::optional&, const std::optional&, 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> attributeBinding( const PossiblyEvaluatedPropertyValue& currentValue) const override { @@ -316,6 +339,7 @@ public: return std::tuple>{gfx::attributeBinding(*vertexBuffer)}; } } +#endif // MLN_LEGACY_RENDERER std::tuple interpolationFactor(float) const override { return std::tuple{0.0f}; } @@ -335,11 +359,19 @@ public: return {ZoomInterpolatedVertexType{concatenate(value.a1, value.a1)}}; } + gfx::VertexVectorBasePtr getSharedVertexVector() const override { return sharedVertexVector; } + private: style::PropertyExpression expression; T defaultValue; - gfx::VertexVector vertexVector; + + gfx::VertexVectorPtr sharedVertexVector = std::make_shared>(); + gfx::VertexVector& vertexVector = *sharedVertexVector; + +#if MLN_LEGACY_RENDERER std::optional> 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&, const std::optional&, 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 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> attributeBinding( const PossiblyEvaluatedPropertyValue& currentValue) const override { @@ -439,6 +470,7 @@ public: return std::tuple>{gfx::attributeBinding(*vertexBuffer)}; } } +#endif // MLN_LEGACY_RENDERER std::tuple 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> getVertexValue(std::size_t index) const override { return {vertexVector.at(index)}; } @@ -466,8 +502,14 @@ private: style::PropertyExpression expression; T defaultValue; Range zoomRange; - gfx::VertexVector vertexVector; + + gfx::VertexVectorPtr sharedVertexVector = std::make_shared>(); + gfx::VertexVector& vertexVector = *sharedVertexVector; + +#if MLN_LEGACY_RENDERER std::optional> 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&, const std::optional&, @@ -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 interpolationFactor(float) const override { return std::tuple{0.0f, 0.0f}; } @@ -582,16 +625,25 @@ public: ZoomInterpolatedVertexType{concatenate(zoomValue.a1, zoomValue.a1)}}; } + gfx::VertexVectorBasePtr getSharedVertexVector() const override { return sharedPatternToVertexVector; } + private: style::PropertyExpression expression; T defaultValue; Range zoomRange; - gfx::VertexVector patternToVertexVector; + + gfx::VertexVectorPtr sharedPatternToVertexVector = std::make_shared>(); + gfx::VertexVector& patternToVertexVector = *sharedPatternToVertexVector; + gfx::VertexVector zoomInVertexVector; gfx::VertexVector zoomOutVertexVector; + +#if MLN_LEGACY_RENDERER std::optional> patternToVertexBuffer; std::optional> zoomInVertexBuffer; std::optional> zoomOutVertexBuffer; +#endif // MLN_LEGACY_RENDERER + CrossfadeParameters crossfade; }; @@ -716,7 +768,9 @@ public: util::ignore({(binders.template get()->setPatternParameters(posA, posB, crossfade), 0)...}); } +#if MLN_LEGACY_RENDERER void upload(gfx::UploadPass& uploadPass) { util::ignore({(binders.template get()->upload(uploadPass), 0)...}); } +#endif // MLN_LEGACY_RENDERER template using ZoomInterpolatedAttributeList = typename Property

::ZoomInterpolatedAttributeList; diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 1c6638c64..9eca0168d 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -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& 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) { [[maybe_unused]] auto& context = backend.getContext(); + // Blocks execution until the renderable is available. backend.getDefaultRenderable().wait();