diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f6edaa83..7250958c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -295,6 +295,7 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/util/compression.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/constants.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/convert.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/util/default_style.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/enum.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/event.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/exception.hpp @@ -319,7 +320,7 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/util/run_loop.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/size.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/string.hpp - ${PROJECT_SOURCE_DIR}/include/mbgl/util/default_style.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/util/suppress_copies.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/tile_server_options.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/thread.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/tileset.hpp diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 2f2817f18..20eebfa61 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -1,10 +1,12 @@ #pragma once -#include #include +#include +#include #include #include +#include #include namespace mbgl { @@ -22,7 +24,7 @@ using DrawableTweakerPtr = std::shared_ptr; class Drawable { protected: - Drawable() = default; + Drawable(); public: virtual ~Drawable() = default; @@ -40,6 +42,12 @@ public: DrawPriority getDrawPriority() const { return drawPriority; } void setDrawPriority(DrawPriority value) { drawPriority = value; } + std::optional getTileID() const { return tileID; } + void setTileID(OverscaledTileID value) { tileID = value; } + + mat4 getMatrix() const { return matrix; } + void setMatrix(mat4 value) { matrix = value; } + /// Get the number of vertexes std::size_t getVertexCount() const { return getVertexAttributes().getMaxCount(); } @@ -61,7 +69,8 @@ public: protected: util::SimpleIdentity uniqueID; gfx::ShaderProgramBasePtr shader; - + mat4 matrix; //= matrix::identity4(); + std::optional tileID; DrawPriority drawPriority = 0; std::vector tweakers; diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index 63b4856d3..4c4204d15 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -62,6 +62,8 @@ public: /// Get the vertex attributes that override default values in the shader program virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0; + void setMatrix(mat4 value) { matrix = value; } + /// Add a triangle void addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2); /// Add another triangle based on the previous two points @@ -85,6 +87,8 @@ protected: gfx::ShaderProgramBasePtr shader; + mat4 matrix; + DrawablePtr currentDrawable; std::vector drawables; diff --git a/include/mbgl/gl/vertex_attribute_gl.hpp b/include/mbgl/gl/vertex_attribute_gl.hpp index fa02d5a41..2844c7733 100644 --- a/include/mbgl/gl/vertex_attribute_gl.hpp +++ b/include/mbgl/gl/vertex_attribute_gl.hpp @@ -53,7 +53,6 @@ public: VertexAttributeArrayGL(int initCapacity = 10) : VertexAttributeArray(initCapacity) { } VertexAttributeArrayGL(VertexAttributeArrayGL &&other) : VertexAttributeArray(std::move(other)) { } VertexAttributeArrayGL(const VertexAttributeArrayGL&) = delete; - ~VertexAttributeArrayGL() = default; VertexAttributeArrayGL& operator=(VertexAttributeArrayGL &&other) { VertexAttributeArray::operator=(std::move(other)); diff --git a/include/mbgl/renderer/renderer.hpp b/include/mbgl/renderer/renderer.hpp index c264d6e93..69c01a56f 100644 --- a/include/mbgl/renderer/renderer.hpp +++ b/include/mbgl/renderer/renderer.hpp @@ -107,11 +107,6 @@ public: */ const std::vector& getPlacedSymbolsData() const; - /** - Update the layers - */ - void update(const std::shared_ptr&); - // Memory void reduceMemoryUse(); void clearData(); diff --git a/include/mbgl/shaders/gl/shader_program_gl.hpp b/include/mbgl/shaders/gl/shader_program_gl.hpp index 364365cf4..68cef105a 100644 --- a/include/mbgl/shaders/gl/shader_program_gl.hpp +++ b/include/mbgl/shaders/gl/shader_program_gl.hpp @@ -14,7 +14,6 @@ public: VertexAttributeArrayGL&& uniforms, VertexAttributeArrayGL&& attributes); ShaderProgramGL(ShaderProgramGL&& other); - virtual ~ShaderProgramGL() noexcept = default; static constexpr std::string_view Name{"GenericGLShader"}; const std::string_view typeName() const noexcept override { return Name; } diff --git a/include/mbgl/shaders/shader_program_base.hpp b/include/mbgl/shaders/shader_program_base.hpp index a472bdcd9..1456ecaf8 100644 --- a/include/mbgl/shaders/shader_program_base.hpp +++ b/include/mbgl/shaders/shader_program_base.hpp @@ -25,8 +25,6 @@ protected: } public: - virtual ~ShaderProgramBase() noexcept = default; - const util::SimpleIdentity& getID() const { return shaderProgramID; } /// Get the available vertex attributes and their default values diff --git a/include/mbgl/util/suppress_copies.hpp b/include/mbgl/util/suppress_copies.hpp new file mode 100644 index 000000000..cd4b5c332 --- /dev/null +++ b/include/mbgl/util/suppress_copies.hpp @@ -0,0 +1,20 @@ +#pragma once + +namespace mbgl { +namespace util { + +/// Wrapper that doesn't participate in copying. +/// This allows a default-copyable object to have members that aren't copied +template struct SuppressCopies { + SuppressCopies() = default; + SuppressCopies(SuppressCopies const&) {} + SuppressCopies(SuppressCopies&& other) : value(std::forward(other.value)) {} + SuppressCopies& operator=(SuppressCopies o) { std::swap(value, o.value); return *this; } + operator T&() { return value; } + T& get() { return value; } +private: + T value; +}; + +} // namespace util +} // namespace mbgl diff --git a/platform/darwin/src/MLNRendererFrontend.h b/platform/darwin/src/MLNRendererFrontend.h index ea5a802f3..001c7aff8 100644 --- a/platform/darwin/src/MLNRendererFrontend.h +++ b/platform/darwin/src/MLNRendererFrontend.h @@ -35,9 +35,6 @@ public: } else { [nativeView setNeedsRerender]; } - if (renderer) { - renderer->update(updateParameters); - } } void setObserver(mbgl::RendererObserver& observer) override { diff --git a/src/mbgl/gfx/drawable.cpp b/src/mbgl/gfx/drawable.cpp index 59cee65b4..5fe8edd11 100644 --- a/src/mbgl/gfx/drawable.cpp +++ b/src/mbgl/gfx/drawable.cpp @@ -1,8 +1,13 @@ #include +#include namespace mbgl { namespace gfx { +Drawable::Drawable() : + matrix(matrix::identity4()) +{ +} } // namespace gfx } // namespace mbgl diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index 48f737b33..57289dbd8 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -29,6 +29,7 @@ void DrawableBuilder::flush() { auto draw = getCurrentDrawable(/*createIfNone=*/true); currentDrawable->setDrawPriority(drawPriority); currentDrawable->setShader(shader); + currentDrawable->setMatrix(matrix); currentDrawable->setVertexAttributes(getVertexAttributes()); currentDrawable->addTweakers(tweakers.begin(), tweakers.end()); init(); diff --git a/src/mbgl/gl/drawable_gl_impl.hpp b/src/mbgl/gl/drawable_gl_impl.hpp index b22af0932..a2c1196f7 100644 --- a/src/mbgl/gl/drawable_gl_impl.hpp +++ b/src/mbgl/gl/drawable_gl_impl.hpp @@ -51,7 +51,6 @@ public: std::size_t indexOffset = 0; std::size_t indexLength = 0; std::size_t attributeOffset = 0; - mat4 matrix; gfx::DepthMode depthMode = gfx::DepthMode::disabled(); gfx::StencilMode stencilMode; gfx::ColorMode colorMode; diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index ab8677093..f5458b713 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -750,19 +750,6 @@ void RenderOrchestrator::clearData() { glyphManager->evict(fontStacks(*layerImpls)); } -void RenderOrchestrator::update(const std::shared_ptr& parameters) { - if (!parameters) { - return; - } - - // TODO: Removed layers need a chance to remove their drawables - std::vector> changes; - for (auto& layer : *parameters->layers) { - layer->update(changes); - addChanges(changes); - } -} - void RenderOrchestrator::addChanges(UniqueChangeRequestVec& changes) { pendingChanges.insert(pendingChanges.end(), std::make_move_iterator(changes.begin()), @@ -783,14 +770,19 @@ void RenderOrchestrator::removeDrawable(const util::SimpleIdentity& drawableId) void RenderOrchestrator::updateLayers(PaintParameters& parameters) { std::vector> changes; + for (auto& kv : layersRemoved) { kv.second->layerRemoved(parameters, changes); - addChanges(changes); } for (auto& kv : layersAdded) { kv.second->layerAdded(parameters, changes); - addChanges(changes); } + + for (auto& impl : *layerImpls) { + impl->update(parameters, changes); + } + + addChanges(changes); } void RenderOrchestrator::processChanges() { diff --git a/src/mbgl/renderer/renderer.cpp b/src/mbgl/renderer/renderer.cpp index 247069877..b35f9d6c3 100644 --- a/src/mbgl/renderer/renderer.cpp +++ b/src/mbgl/renderer/renderer.cpp @@ -129,10 +129,6 @@ const std::vector& Renderer::getPlacedSymbolsData() const { return impl->orchestrator.getPlacedSymbolsData(); } -void Renderer::update(const std::shared_ptr& parameters) { - impl->orchestrator.update(parameters); -} - void Renderer::reduceMemoryUse() { gfx::BackendScope guard{impl->backend}; impl->reduceMemoryUse(); diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 4eb960e6b..566022454 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -115,12 +115,6 @@ void Renderer::Impl::render(const RenderTree& renderTree) { auto& drawableGL = static_cast(drawable); auto& shader = drawable.getShader(); - // Where should this happen? - const mat4 matrix = parameters.matrixForTile({ 0, 0, 0 }); //tileID.toUnwrapped()); - - shader->setUniform("u_matrix", 0, util::convert(matrix)); - shader->updateUniforms(); - // Generate a vertex array object for the drawable state, if necessary if (shader && !drawableGL.getVertexArray().isValid()) { const auto usage = gfx::BufferUsageType::StaticDraw; @@ -246,6 +240,18 @@ void Renderer::Impl::render(const RenderTree& renderTree) { context.setupDraw(drawable); + mat4 matrix = drawable.getMatrix(); + if (drawable.getTileID()) { + const UnwrappedTileID tileID = {0,0,0};//drawable.getTileID()->toUnwrapped(); + const auto tileMat = parameters.matrixForTile(tileID); + matrix::multiply(matrix, drawable.getMatrix(), tileMat); + } + + if (auto& shader = drawable.getShader()) { + shader->setUniform("u_matrix", 0, util::convert(matrix)); + shader->updateUniforms(); + } + drawable.draw(parameters); } } diff --git a/src/mbgl/style/layer_impl.hpp b/src/mbgl/style/layer_impl.hpp index c13a8dea6..493920c45 100644 --- a/src/mbgl/style/layer_impl.hpp +++ b/src/mbgl/style/layer_impl.hpp @@ -56,7 +56,7 @@ public: virtual void populateFontStack(std::set& fontStack) const; /// Generate any changes needed by the layer - virtual void update(UniqueChangeRequestVec&) const { } + virtual void update(PaintParameters&, UniqueChangeRequestVec&) const { } virtual void layerAdded(PaintParameters&, UniqueChangeRequestVec&) const { } virtual void layerRemoved(PaintParameters&, UniqueChangeRequestVec&) const { } diff --git a/src/mbgl/style/layers/background_layer_impl.cpp b/src/mbgl/style/layers/background_layer_impl.cpp index 873b545de..eaa5620e5 100644 --- a/src/mbgl/style/layers/background_layer_impl.cpp +++ b/src/mbgl/style/layers/background_layer_impl.cpp @@ -8,10 +8,21 @@ #include #include #include +#include + +#include namespace mbgl { namespace style { +BackgroundLayer::Impl::Impl(const Impl& other) : + Layer::Impl(other), + shader(other.shader), + paint(other.paint) +{ + // mutex, drawables, stats not copied +} + bool BackgroundLayer::Impl::hasLayoutDifference(const Layer::Impl&) const { return false; } @@ -19,45 +30,92 @@ bool BackgroundLayer::Impl::hasLayoutDifference(const Layer::Impl&) const { constexpr auto shaderName = "background_generic"; void BackgroundLayer::Impl::layerAdded(PaintParameters& parameters, UniqueChangeRequestVec& changes) const { - if (!shader) { - shader = parameters.shaders.get(shaderName); + { + std::unique_lock guard(mutex); + if (!shader) { + shader = parameters.shaders.get(shaderName); + } } - buildDrawables(changes); + // Add all the tiles + update(parameters, changes); } void BackgroundLayer::Impl::layerRemoved(PaintParameters&, UniqueChangeRequestVec& changes) const { - if (drawable) { + // Remove everything + decltype(tileDrawables) localDrawables; + { + std::unique_lock guard(mutex); + localDrawables = std::move(tileDrawables); + } + + for (auto& kv : localDrawables) { + auto& drawable = kv.second; changes.emplace_back(std::make_unique(drawable->getId())); - drawable.reset(); } } -void BackgroundLayer::Impl::buildDrawables(UniqueChangeRequestVec& changes) const { +void BackgroundLayer::Impl::update(PaintParameters& parameters, UniqueChangeRequestVec& changes) const { + std::unique_lock guard(mutex); - if (!shader) { - return; - } - - auto builder = std::make_unique(); // from GL-specific code via virtual method? + auto builder = std::make_unique(); // from GL-specific code via virtual method on ...Context? builder->setShader(shader); builder->addTweaker(std::make_shared()); // generally shared across drawables - builder->addQuad(0, 0, util::EXTENT, util::EXTENT); - builder->flush(); - changes.reserve(builder->getDrawables().size()); - for (auto &draw : builder->clearDrawables()) { - drawable = draw; - changes.emplace_back(std::make_unique(std::move(draw))); + const auto zoom = parameters.state.getIntegerZoom(); + const auto tileCover = util::tileCover(parameters.state, zoom); + + // Drawables per overscaled or canonical tile? + //const UnwrappedTileID unwrappedTileID = tileID.toUnwrapped(); + + std::unordered_set newTileIDs(tileCover.begin(), tileCover.end()); + + // For each existing tile drawable... + for (auto iter = tileDrawables.begin(); iter != tileDrawables.end(); ) { + // Has this tile dropped out of the cover set? + if (newTileIDs.find(iter->first) == newTileIDs.end()) { + // remove it + const auto& drawable = iter->second; + changes.emplace_back(std::make_unique(drawable->getId())); + //Log::Warning(Event::General, "Removing drawable for " + util::toString(iter->first) + " total " + std::to_string(stats.tileDrawablesRemoved+1)); + iter = tileDrawables.erase(iter); + ++stats.tileDrawablesRemoved; + } else { + ++iter; + } } -} -void BackgroundLayer::Impl::update(UniqueChangeRequestVec& changes) const { - if (!drawable /* && visible/enabled */) { - buildDrawables(changes); -// } else if (drawable && !visible/enabled) { -// changes.emplace_back(std::make_unique(drawable->getId())); -// drawable.reset(); + // For each tile in the cover set, add a tile drawable if one doesn't already exist. + // We currently assume only one drawable per tile. + for (const auto& tileID : tileCover) { + const auto result = tileDrawables.insert(std::make_pair(tileID, gfx::DrawablePtr())); + if (!result.second) { + // Already present + // TODO: Update matrix uniform here or in the tweaker? + continue; + } + + // Tile coordinates are fixed... + builder->addQuad(0, 0, util::EXTENT, util::EXTENT); + + // ... they're placed with the matrix in the uniforms + builder->setMatrix(/*parameters.matrixForTile(tileID.toUnwrapped())*/ matrix::identity4()); + //builder->setUniform("u_matrix", matrix); + + builder->flush(); + + // TODO: Store Tile ID with drawable? + // Drawables aren't always tile-specific, but it may be needed sometimes. + + auto drawables = builder->clearDrawables(); + if (!drawables.empty()) { + auto& drawable = drawables[0]; + drawable->setTileID(tileID); + result.first->second = drawable; + changes.emplace_back(std::make_unique(std::move(drawable))); + ++stats.tileDrawablesAdded; + //Log::Warning(Event::General, "Adding drawable for " + util::toString(tileID) + " total " + std::to_string(stats.tileDrawablesAdded+1)); + } } } diff --git a/src/mbgl/style/layers/background_layer_impl.hpp b/src/mbgl/style/layers/background_layer_impl.hpp index 822782f68..a7bf6931d 100644 --- a/src/mbgl/style/layers/background_layer_impl.hpp +++ b/src/mbgl/style/layers/background_layer_impl.hpp @@ -3,8 +3,11 @@ #include #include #include +#include #include +#include +#include namespace mbgl { namespace gfx { @@ -21,6 +24,7 @@ namespace style { class BackgroundLayer::Impl : public Layer::Impl { public: using Layer::Impl::Impl; + Impl(const Impl&); bool hasLayoutDifference(const Layer::Impl&) const override; void stringifyLayout(rapidjson::Writer&) const override; @@ -29,17 +33,21 @@ public: void layerRemoved(PaintParameters&, UniqueChangeRequestVec&) const override; /// Generate any changes needed by the layer - void update(UniqueChangeRequestVec&) const override; + void update(PaintParameters&, UniqueChangeRequestVec&) const override; private: - void buildDrawables(UniqueChangeRequestVec&) const; - + mutable std::mutex mutex; + mutable gfx::ShaderProgramBasePtr shader; + mutable std::unordered_map tileDrawables; + + mutable struct Stats { + size_t tileDrawablesAdded = 0; + size_t tileDrawablesRemoved = 0; + } stats; + public: BackgroundPaintProperties::Transitionable paint; - mutable gfx::ShaderProgramBasePtr shader; - mutable gfx::DrawablePtr drawable; - DECLARE_LAYER_TYPE_INFO; }; diff --git a/src/mbgl/util/mat4.hpp b/src/mbgl/util/mat4.hpp index 5e56ca170..52e6b5246 100644 --- a/src/mbgl/util/mat4.hpp +++ b/src/mbgl/util/mat4.hpp @@ -28,10 +28,14 @@ namespace mbgl { using mat4 = std::array; +using matf4 = std::array; namespace matrix { void identity(mat4& out); +constexpr mat4 identity4() { return { 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1 }; } +constexpr matf4 identity4f() { return { 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1 }; } + bool invert(mat4& out, const mat4& a); void ortho(mat4& out, double left, double right, double bottom, double top, double near, double far); void perspective(mat4& out, double fovy, double aspect, double near, double far);