diff --git a/CMakeLists.txt b/CMakeLists.txt index d798147d6..f61ea5bf9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -180,6 +180,7 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/platform/settings.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/platform/thread.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/query.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/layer_group.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_frontend.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_observer.hpp @@ -518,6 +519,7 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_manager.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_manager.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_manager_observer.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layer_group.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_background_layer.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_background_layer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_circle_layer.cpp diff --git a/include/mbgl/renderer/change_request.hpp b/include/mbgl/renderer/change_request.hpp index 3a6699726..e75096329 100644 --- a/include/mbgl/renderer/change_request.hpp +++ b/include/mbgl/renderer/change_request.hpp @@ -7,9 +7,15 @@ #include namespace mbgl { - +class ChangeRequest; +class LayerGroup; class RenderOrchestrator; +using ChangeRequestPtr = std::shared_ptr; +using UniqueChangeRequest = std::unique_ptr; +using UniqueChangeRequestVec = std::vector; +using UniqueLayerGroup = std::unique_ptr; + namespace gfx { class Drawable; using DrawablePtr = std::shared_ptr; @@ -30,20 +36,15 @@ public: protected: }; -using ChangeRequestPtr = std::shared_ptr; -using UniqueChangeRequest = std::unique_ptr; -using UniqueChangeRequestVec = std::vector; - /** - Base for drawable-related change requests + Base for change requests based on an ID reference */ -class DrawableRefChangeRequest : public ChangeRequest { +class RefChangeRequest : public ChangeRequest { protected: - DrawableRefChangeRequest(util::SimpleIdentity id) - : drawableID(id) {} - DrawableRefChangeRequest(const DrawableRefChangeRequest &) = default; + RefChangeRequest(util::SimpleIdentity id_) : id(id_) {} + RefChangeRequest(const RefChangeRequest&) = default; - util::SimpleIdentity drawableID; + util::SimpleIdentity id; }; /** @@ -56,7 +57,7 @@ public: AddDrawableRequest(AddDrawableRequest &&other) : drawable(std::move(other.drawable)) {} - void execute(RenderOrchestrator &) override; + void execute(RenderOrchestrator&) override; protected: gfx::DrawablePtr drawable; @@ -65,29 +66,58 @@ protected: /** Remove a drawable from the scene */ -class RemoveDrawableRequest : public DrawableRefChangeRequest { +class RemoveDrawableRequest : public RefChangeRequest { public: RemoveDrawableRequest(util::SimpleIdentity id) - : DrawableRefChangeRequest(id) {} + : RefChangeRequest(id) {} RemoveDrawableRequest(const RemoveDrawableRequest &) = default; - void execute(RenderOrchestrator &) override; + void execute(RenderOrchestrator&) override; }; /** Change the color of all vertexes */ -class ResetColorRequest : public DrawableRefChangeRequest { +class ResetColorRequest : public RefChangeRequest { public: ResetColorRequest(util::SimpleIdentity id, Color color) - : DrawableRefChangeRequest(id), + : RefChangeRequest(id), newColor(color) {} ResetColorRequest(const ResetColorRequest &other) = default; - void execute(RenderOrchestrator &) override; + void execute(RenderOrchestrator&) override; protected: Color newColor; }; + +/** + Add a new layer group to the scene + */ +class AddLayerGroupRequest : public ChangeRequest { +public: + AddLayerGroupRequest(UniqueLayerGroup&& layerGroup_, bool canReplace); + AddLayerGroupRequest(AddLayerGroupRequest&& other); + + void execute(RenderOrchestrator&) override; + +protected: + UniqueLayerGroup layerGroup; + bool replace; +}; + +/** + Remove a layer group from the scene + */ +class RemoveLayerGroupRequest : public RefChangeRequest { +public: + RemoveLayerGroupRequest(util::SimpleIdentity id) + : RefChangeRequest(id) {} + RemoveLayerGroupRequest(const RemoveLayerGroupRequest &) = default; + + void execute(RenderOrchestrator&) override; +}; + + } // namespace mbgl diff --git a/include/mbgl/renderer/layer_group.hpp b/include/mbgl/renderer/layer_group.hpp new file mode 100644 index 000000000..0b59486e4 --- /dev/null +++ b/include/mbgl/renderer/layer_group.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include + +#include +#include + +namespace mbgl { +class LayerGroup; +class PaintParameters; +class RenderOrchestrator; +class TileLayerGroup; + +using LayerGroupPtr = std::shared_ptr; + +namespace gfx { +class Context; +class Drawable; +class UploadPass; + +using DrawablePtr = std::shared_ptr; +using UniqueDrawable = std::unique_ptr; +} // namespace gfx + +/** + A layer-like group of drawables, not a group of layers. + */ +class LayerGroup : public util::SimpleIdentifiable { +protected: + LayerGroup(int32_t layerIndex); + LayerGroup(const LayerGroup&) = delete; + LayerGroup& operator=(const LayerGroup&) = delete; + +public: + virtual ~LayerGroup() = default; + + int32_t getLayerIndex() const { return layerIndex; } + + /// Called before starting each frame + virtual void preRender(RenderOrchestrator&, PaintParameters&) { } + /// Called during the upload pass + virtual void upload(gfx::Context&, gfx::UploadPass&) { } + /// Called during each render pass + virtual void render(RenderOrchestrator&, PaintParameters&) { } + /// Called at the end of each frame + virtual void postRender(RenderOrchestrator&, PaintParameters&) { } + +protected: + int32_t layerIndex; +}; + +/** + A layer group for tile-based drawables + */ +class TileLayerGroup : public LayerGroup { +public: + TileLayerGroup(int32_t layerIndex, std::size_t initialCapacity); + ~TileLayerGroup() override; + + void render(RenderOrchestrator&, PaintParameters&) override; + +protected: + struct Impl; + std::unique_ptr impl; +}; + + +} // namespace mbgl diff --git a/src/mbgl/renderer/change_request.cpp b/src/mbgl/renderer/change_request.cpp index df67fd8ed..4cec5b75b 100644 --- a/src/mbgl/renderer/change_request.cpp +++ b/src/mbgl/renderer/change_request.cpp @@ -8,13 +8,29 @@ void AddDrawableRequest::execute(RenderOrchestrator &orchestrator) { } void RemoveDrawableRequest::execute(RenderOrchestrator &orchestrator) { - orchestrator.removeDrawable(drawableID); + orchestrator.removeDrawable(id); } void ResetColorRequest::execute(RenderOrchestrator &orchestrator) { - if (auto &drawable = orchestrator.getDrawable(drawableID)) { + if (auto &drawable = orchestrator.getDrawable(id)) { drawable->resetColor(newColor); } } +AddLayerGroupRequest::AddLayerGroupRequest(UniqueLayerGroup&& layerGroup_, bool canReplace) + : layerGroup(std::move(layerGroup_)), replace(canReplace) { +} + +AddLayerGroupRequest::AddLayerGroupRequest(AddLayerGroupRequest&& other) + : layerGroup(std::move(other.layerGroup)) { +} + +void AddLayerGroupRequest::execute(RenderOrchestrator &orchestrator) { + orchestrator.addLayerGroup(std::move(layerGroup), replace); +} + +void RemoveLayerGroupRequest::execute(RenderOrchestrator &orchestrator) { + orchestrator.removeLayerGroup(id); +} + } // namespace mbgl diff --git a/src/mbgl/renderer/layer_group.cpp b/src/mbgl/renderer/layer_group.cpp new file mode 100644 index 000000000..737d3afab --- /dev/null +++ b/src/mbgl/renderer/layer_group.cpp @@ -0,0 +1,55 @@ +#include + +#include +#include +#include + +#include + +namespace mbgl { + +struct TileLayerGroupTileKey { + mbgl::RenderPass renderPass; + OverscaledTileID tileID; + bool operator==(const TileLayerGroupTileKey& other) const { + return renderPass == other.renderPass && tileID == other.tileID; + } + struct hash { + size_t operator()(const mbgl::TileLayerGroupTileKey& k) const { + return (std::hash()(k.renderPass) ^ + std::hash()(k.tileID) << 1); + } + }; +}; + +struct TileLayerGroup::Impl { + Impl(std::size_t capacity) : tileDrawables(capacity) { } + + using TileMap = std::unordered_map; + TileMap tileDrawables; +}; + +LayerGroup::LayerGroup(int32_t layerIndex_) : + layerIndex(layerIndex_) { + +} + +TileLayerGroup::TileLayerGroup(int32_t layerIndex_, std::size_t initialCapacity) : + LayerGroup(layerIndex_), + impl(std::make_unique(initialCapacity)) +{ +} + +TileLayerGroup::~TileLayerGroup() { +} + +void TileLayerGroup::render([[maybe_unused]] RenderOrchestrator& orchestrator, [[maybe_unused]] PaintParameters& parameters) { + auto pass = mbgl::RenderPass::Opaque; + auto id = OverscaledTileID{0,0,0,0,0}; + auto key = TileLayerGroupTileKey{pass, id}; + impl->tileDrawables.insert(std::make_pair(key, gfx::UniqueDrawable())); +} + + +} // namespace mbgl + diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index 92357009d..5547f1847 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -4,20 +4,21 @@ #include #include #include -#include -#include +#include +#include #include #include #include +#include #include #include #include #include #include -#include #include +#include +#include #include -#include #include #include @@ -223,6 +224,8 @@ void RenderBackgroundLayer::update(const int32_t layerIndex, shader = context.getGenericShader(shaders, shaderName); } + changes.emplace_back(std::make_unique(std::make_unique(layerIndex, 10), /*replace*/true)); + const auto& evaluated = getEvaluated(evaluatedProperties); // TODO: If background is solid, we can skip drawables and rely on the clear color diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index ad9490f54..4130b1dea 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -776,6 +776,64 @@ const gfx::DrawablePtr& RenderOrchestrator::getDrawable(const util::SimpleIdenti return (hit != drawables.end()) ? hit->second : noDrawable; } +void RenderOrchestrator::onRemoveLayerGroup(LayerGroup&) { + +} + +bool RenderOrchestrator::addLayerGroup(UniqueLayerGroup&& layerGroup, const bool replace) { + const auto index = layerGroup->getLayerIndex(); + const auto result = layerGroupsByLayerIndex.insert(std::make_pair(index, UniqueLayerGroup{})); + if (result.second) { + // added + result.first->second = std::move(layerGroup); + return true; + } else { + // not added + if (replace) { + onRemoveLayerGroup(*result.first->second); + result.first->second = std::move(layerGroup); + return true; + } else { + return false; + } + } +} + +bool RenderOrchestrator::removeLayerGroup(const int32_t layerIndex) { + const auto hit = layerGroupsByLayerIndex.find(layerIndex); + if (hit != layerGroupsByLayerIndex.end()) { + onRemoveLayerGroup(*hit->second); + layerGroupsByLayerIndex.erase(hit); + return true; + } else { + return false; + } +} + +static const UniqueLayerGroup no_group; + +const UniqueLayerGroup& RenderOrchestrator::getLayerGroup(const int32_t layerIndex) const { + const auto hit = layerGroupsByLayerIndex.find(layerIndex); + return (hit == layerGroupsByLayerIndex.end()) ? no_group : hit->second; +} + +void RenderOrchestrator::observeLayerGroups(std::function f) { + for (auto& pair : layerGroupsByLayerIndex) { + if (pair.second) { + f(*pair.second); + } + } +} + +void RenderOrchestrator::observeLayerGroups(std::function f) const { + for (const auto& pair : layerGroupsByLayerIndex) { + if (pair.second) { + f(*pair.second); + } + } +} + + void RenderOrchestrator::updateLayers(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, diff --git a/src/mbgl/renderer/render_orchestrator.hpp b/src/mbgl/renderer/render_orchestrator.hpp index 6d49593c8..2882538e1 100644 --- a/src/mbgl/renderer/render_orchestrator.hpp +++ b/src/mbgl/renderer/render_orchestrator.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -13,6 +14,7 @@ #include #include +#include #include #include #include @@ -101,6 +103,12 @@ public: const gfx::DrawablePtr& getDrawable(const util::SimpleIdentity&); + bool addLayerGroup(UniqueLayerGroup&&, bool replace); + bool removeLayerGroup(const int32_t layerIndex); + const UniqueLayerGroup& getLayerGroup(const int32_t layerIndex) const; + void observeLayerGroups(std::function); + void observeLayerGroups(std::function) const; + void updateLayers(gfx::ShaderRegistry&, gfx::Context&, const TransformState&, @@ -142,6 +150,8 @@ private: /// Move changes into the pending set, clearing the provided collection void addChanges(UniqueChangeRequestVec&); + void onRemoveLayerGroup(LayerGroup&); + RendererObserver* observer; ZoomHistory zoomHistory; @@ -173,9 +183,12 @@ private: RenderLayerReferences orderedLayers; RenderLayerReferences layersNeedPlacement; -protected: DrawableMap drawables; std::vector> pendingChanges; + + using LayerGroupMap = std::map; + LayerGroupMap layerGroupsByLayerIndex; + }; } // namespace mbgl diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index f4f113877..ce999dca2 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -103,6 +103,11 @@ void Renderer::Impl::render(const RenderTree& renderTree) { } } + // Give the layers a chance to do setup + orchestrator.observeLayerGroups([&](LayerGroup& layerGroup){ + layerGroup.preRender(orchestrator, parameters); + }); + // Sort the drawables std::sort(drawables.begin(), drawables.end(), gfx::DrawablePtrLessByLayer(/*descending=*/true)); @@ -155,6 +160,11 @@ void Renderer::Impl::render(const RenderTree& renderTree) { drawableGL.setVertexArray(std::move(vertexArray), std::move(vertexBuffer), std::move(indexBuffer)); } } + + // Give the layers a chance to upload + orchestrator.observeLayerGroups([&](LayerGroup& layerGroup){ + layerGroup.upload(context, *uploadPass); + }); } // - 3D PASS @@ -243,6 +253,11 @@ void Renderer::Impl::render(const RenderTree& renderTree) { } }; + // draw layer groups, opaque pass + orchestrator.observeLayerGroups([&](LayerGroup& layerGroup){ + layerGroup.render(orchestrator, parameters); + }); + parameters.pass = RenderPass::Opaque; parameters.currentLayer = 0; parameters.opaquePassCutoff = 1; @@ -276,6 +291,11 @@ void Renderer::Impl::render(const RenderTree& renderTree) { parameters.opaquePassCutoff = 1; drawDrawables(parameters.pass); + // draw layer groups, translucent pass + orchestrator.observeLayerGroups([&](LayerGroup& layerGroup){ + layerGroup.render(orchestrator, parameters); + }); + parameters.opaquePassCutoff = renderTreeParameters.opaquePassCutOff; // - TRANSLUCENT PASS -------------------------------------------------------------------------- @@ -318,6 +338,11 @@ void Renderer::Impl::render(const RenderTree& renderTree) { } #endif + // Give the layers a chance to do cleanup + orchestrator.observeLayerGroups([&](LayerGroup& layerGroup){ + layerGroup.postRender(orchestrator, parameters); + }); + // Ends the RenderPass parameters.renderPass.reset(); const bool isMapModeContinuous = renderTreeParameters.mapMode == MapMode::Continuous;