From 4af4491626e371f19edaaacbe046f2f7a0d309e6 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Tue, 2 May 2023 13:54:50 -0700 Subject: [PATCH] Drawable Renderer (#1570), order drawables --- include/mbgl/gfx/drawable.hpp | 63 +++++++++++++------ include/mbgl/gfx/drawable_builder.hpp | 8 ++- src/mbgl/gfx/drawable_builder.cpp | 1 + src/mbgl/renderer/render_orchestrator.cpp | 7 ++- src/mbgl/renderer/renderer_impl.cpp | 30 ++++++--- src/mbgl/style/layer_impl.hpp | 3 +- .../style/layers/background_layer_impl.cpp | 9 ++- .../style/layers/background_layer_impl.hpp | 4 +- 8 files changed, 92 insertions(+), 33 deletions(-) diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 7e0f4effd..cff718fad 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -28,59 +28,63 @@ using DrawableTweakerPtr = std::shared_ptr; class Drawable { protected: Drawable(std::string name); - + public: virtual ~Drawable() = default; - + const util::SimpleIdentity& getId() const { return uniqueID; } - + /// Draw the drawable virtual void draw(const PaintParameters&) const = 0; - + /// Drawable name is used for debugging and troubleshooting const std::string& getName() const { return name; } void setName(std::string value) { name = std::move(value); } - + /// Which shader to use when rendering this drawable const gfx::ShaderProgramBasePtr& getShader() const { return shader; } void setShader(gfx::ShaderProgramBasePtr value) { shader = std::move(value); } - - /// DrawPriority determines the drawing order + + /// not used for anything yet DrawPriority getDrawPriority() const { return drawPriority; } void setDrawPriority(DrawPriority value) { drawPriority = value; } - + + /// The layer index determines the drawing order + int32_t getLayerIndex() const { return layerIndex; } + void setLayerIndex(int32_t value) { layerIndex = value; } + std::optional getTileID() const { return tileID; } void setTileID(OverscaledTileID value) { tileID = value; } - + mat4 getMatrix() const { return matrix; } void setMatrix(mat4 value) { matrix = value; } - + DepthMaskType getDepthType() const { return depthType; } void setDepthType(DepthMaskType value) { depthType = value; } - + /// Get the number of vertexes std::size_t getVertexCount() const { return getVertexAttributes().getMaxCount(); } - + /// Get the vertex attributes that override default values in the shader program virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0; virtual void setVertexAttributes(const gfx::VertexAttributeArray&) = 0; virtual void setVertexAttributes(gfx::VertexAttributeArray&&) = 0; - + virtual std::vector& getIndexData() const = 0; - + /// Attach a tweaker to be run on this drawable for each frame void addTweaker(DrawableTweakerPtr tweaker) { tweakers.emplace_back(std::move(tweaker)); } template void addTweakers(TIter beg, TIter end) { tweakers.insert(tweakers.end(), beg, end); } - + /// Get the tweakers attached to this drawable const std::vector& getTweakers() const { return tweakers; } - + // Reset a single color attribute for all vertexes virtual void resetColor(const Color&) = 0; - + protected: std::string name; util::SimpleIdentity uniqueID; @@ -88,12 +92,35 @@ protected: mat4 matrix; //= matrix::identity4(); std::optional tileID; DrawPriority drawPriority = 0; + int32_t layerIndex = -1; DepthMaskType depthType; // = DepthMaskType::ReadOnly; - + std::vector tweakers; }; using DrawablePtr = std::shared_ptr; +/// Comparator for sorting drawable pointers primarily by layer index +struct DrawablePtrLessByLayer { + DrawablePtrLessByLayer(bool descending) : desc(descending) { } + bool operator()(const DrawablePtr& left, const DrawablePtr& right) const { + const auto& a = desc ? right : left; + const auto& b = desc ? left : right; + if (!a || !b) { + // nulls are less than non-nulls + return (!a && b); + } + if (a->getLayerIndex() != b->getLayerIndex()) { + return a->getLayerIndex() < b->getLayerIndex(); + } + if (a->getDrawPriority() != b->getDrawPriority()) { + return a->getDrawPriority() < b->getDrawPriority(); + } + return a->getId() < b->getId(); + } +private: + bool desc; +}; + } // namespace gfx } // namespace mbgl diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index f0f4e3601..d4dd7b7d3 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -48,11 +48,14 @@ public: /// Get the ID of the drawable we're currently working on, if any util::SimpleIdentity getDrawableId(); - /// Get the draw priority assigned to generated drawables + /// The draw priority assigned to generated drawables DrawPriority getDrawPriority() const; - /// Set the draw priority assigned to generated drawables void setDrawPriority(DrawPriority); + /// The layer index assigned to generated drawables + int32_t getLayerIndex() const { return layerIndex; } + void setLayerIndex(int32_t value) { layerIndex = value; } + /// Set the draw priority on all drawables including those already generated void resetDrawPriority(DrawPriority); @@ -106,6 +109,7 @@ protected: std::string name; std::string drawableName; DrawPriority drawPriority = 0; + int32_t layerIndex = -1; DepthMaskType depthType = DepthMaskType::ReadOnly; gfx::ShaderProgramBasePtr shader; mat4 matrix; diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index c67798720..030b527f5 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -28,6 +28,7 @@ void DrawableBuilder::flush() { if (!impl->vertices.empty()) { auto draw = getCurrentDrawable(/*createIfNone=*/true); currentDrawable->setDrawPriority(drawPriority); + currentDrawable->setLayerIndex(layerIndex); currentDrawable->setDepthType(depthType); currentDrawable->setShader(shader); currentDrawable->setMatrix(matrix); diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 40a576f86..596e21bf0 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -797,8 +797,13 @@ void RenderOrchestrator::updateLayers(gfx::ShaderRegistry& shaders, kv.second->layerAdded(shaders, context, state, evalParameters, changes); } + // Layer index, similar but not identical to `layerRenderItems` index in render_impl + //int32_t i = static_cast(layerRenderItems.size()) - 1; + //for (auto it = layerRenderItems.begin(); it != layerRenderItems.end() && i >= 0; ++it, --i) { + auto index = static_cast(layerImpls->size()) - 1; + for (auto& impl : *layerImpls) { - impl->update(context, state, evalParameters, changes); + impl->update(index--, context, state, evalParameters, changes); } addChanges(changes); diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index f3dd1b418..bd58d0db7 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -89,6 +89,23 @@ void Renderer::Impl::render(const RenderTree& renderTree) { // Run changes orchestrator.processChanges(); + // Collect drawables + std::vector drawables(orchestrator.getDrawables().size()); + std::transform(orchestrator.getDrawables().begin(), + orchestrator.getDrawables().end(), + drawables.begin(), + std::bind(&RenderOrchestrator::DrawableMap::value_type::second)); + + // Run tweakers to update any dynamic elements + for (auto& drawable : drawables) { + for (auto& tweaker : drawable->getTweakers()) { + tweaker->execute(*drawable, parameters); + } + } + + // Sort the drawables + std::sort(drawables.begin(), drawables.end(), gfx::DrawablePtrLessByLayer(/*descending=*/true)); + // - UPLOAD PASS ------------------------------------------------------------------------------- // Uploads all required buffers and images before we do any actual rendering. { @@ -105,13 +122,8 @@ void Renderer::Impl::render(const RenderTree& renderTree) { renderTree.getLineAtlas().upload(*uploadPass); renderTree.getPatternAtlas().upload(*uploadPass); - for (const auto& pair : orchestrator.getDrawables()) { - auto& drawable = *pair.second; - - // Run tweakers to update any dynamic elements - for (auto& tweaker : drawable.getTweakers()) { - tweaker->execute(drawable, parameters); - } + for (const auto& drawPtr : drawables) { + auto& drawable = *drawPtr; auto& drawableGL = static_cast(drawable); auto& shader = drawable.getShader(); @@ -198,8 +210,8 @@ void Renderer::Impl::render(const RenderTree& renderTree) { parameters.depthRangeSize = 1 - (1 + 2) * parameters.numSublayers * parameters.depthEpsilon; const auto debugGroup(parameters.renderPass->createDebugGroup("drawables")); - for (const auto& pair : orchestrator.getDrawables()) { - const auto& drawable = *pair.second; + for (const auto& drawPtr : drawables) { + auto& drawable = *drawPtr; if (!context.setupDraw(parameters, drawable)) { continue; diff --git a/src/mbgl/style/layer_impl.hpp b/src/mbgl/style/layer_impl.hpp index 91969c256..ededc64a1 100644 --- a/src/mbgl/style/layer_impl.hpp +++ b/src/mbgl/style/layer_impl.hpp @@ -63,7 +63,8 @@ public: virtual void populateFontStack(std::set& fontStack) const; /// Generate any changes needed by the layer - virtual void update(gfx::Context&, + virtual void update(int32_t /*layerIndex*/, + gfx::Context&, const TransformState&, const PropertyEvaluationParameters&, UniqueChangeRequestVec&) const {} diff --git a/src/mbgl/style/layers/background_layer_impl.cpp b/src/mbgl/style/layers/background_layer_impl.cpp index 1419f4a04..72588df6e 100644 --- a/src/mbgl/style/layers/background_layer_impl.cpp +++ b/src/mbgl/style/layers/background_layer_impl.cpp @@ -56,7 +56,8 @@ void BackgroundLayer::Impl::layerRemoved(UniqueChangeRequestVec& changes) const localDrawables.cbegin(), localDrawables.cend(), changes, [](auto& ii) { return ii->second->getId(); }); } -void BackgroundLayer::Impl::update(gfx::Context& context, +void BackgroundLayer::Impl::update(const int32_t layerIndex, + gfx::Context& context, const TransformState& state, const PropertyEvaluationParameters& evalParameters, UniqueChangeRequestVec& changes) const { @@ -96,7 +97,9 @@ void BackgroundLayer::Impl::update(gfx::Context& context, } const bool colorChange = (color != lastColor); + const bool layerChange = (layerIndex != lastLayerIndex); lastColor = color; + lastLayerIndex = layerIndex; const auto zoom = state.getIntegerZoom(); const auto tileCover = util::tileCover(state, zoom); @@ -129,6 +132,9 @@ void BackgroundLayer::Impl::update(gfx::Context& context, if (colorChange) { drawable->resetColor(*color); } + if (layerChange) { + drawable->setLayerIndex(layerIndex); + } } std::unique_ptr builder; @@ -151,6 +157,7 @@ void BackgroundLayer::Impl::update(gfx::Context& context, builder->setColor(*color); builder->setColorMode(gfx::DrawableBuilder::ColorMode::PerDrawable); builder->setDepthType(gfx::DepthMaskType::ReadWrite); + builder->setLayerIndex(layerIndex); } // Tile coordinates are fixed... diff --git a/src/mbgl/style/layers/background_layer_impl.hpp b/src/mbgl/style/layers/background_layer_impl.hpp index 8f7d972cf..e1c136abf 100644 --- a/src/mbgl/style/layers/background_layer_impl.hpp +++ b/src/mbgl/style/layers/background_layer_impl.hpp @@ -41,7 +41,8 @@ public: void layerRemoved(UniqueChangeRequestVec&) const override; /// Generate any changes needed by the layer - void update(gfx::Context&, + void update(int32_t layerIndex, + gfx::Context&, const TransformState&, const PropertyEvaluationParameters&, UniqueChangeRequestVec&) const override; @@ -62,6 +63,7 @@ private: mutable gfx::ShaderProgramBasePtr shader; mutable std::unordered_map tileDrawables; mutable std::optional lastColor; + mutable int32_t lastLayerIndex = -1; mutable struct Stats { size_t tileDrawablesAdded = 0;