From 375083b6cf19ee9890ea07cb5f336d229cc44b69 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Fri, 5 May 2023 15:08:53 -0700 Subject: [PATCH] Drawable Renderer (#1570), work on fill drawables --- include/mbgl/gfx/drawable_builder.hpp | 8 ++ src/mbgl/gfx/drawable_builder.cpp | 20 +++++ src/mbgl/gl/context.cpp | 10 ++- .../renderer/layers/render_fill_layer.cpp | 78 ++++++++++++++++++- src/mbgl/renderer/renderer_impl.cpp | 5 ++ 5 files changed, 116 insertions(+), 5 deletions(-) diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index d4dd7b7d3..1314f1d55 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -95,6 +96,13 @@ public: /// Add a rectangle consisting of two triangles void addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1); + /// Add already-set-up triangles directly + + void addTriangles(const std::vector>& vertices, + std::size_t vertexOffset, std::size_t vertexLength, + const std::vector& indexes, + std::size_t indexOffset, std::size_t indexLength); + /// Add a tweaker to be attached to each emitted drawable void addTweaker(DrawableTweakerPtr tweaker) { tweakers.emplace_back(std::move(tweaker)); } diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index 030b527f5..55fffd935 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -89,5 +89,25 @@ void DrawableBuilder::addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1) { appendTriangle(x1, y1); } +void DrawableBuilder::addTriangles(const std::vector>& vertices, + std::size_t vertexOffset, std::size_t vertexLength, + const std::vector& indexes, + std::size_t indexOffset, std::size_t indexLength) { + // TODO: bulk add in `gfx::VertexVector`... or use vector directly? + //impl->vertices.insert(impl->vertices.end(), + // std::next(vertices.begin(), vertexOffset), + // std::next(vertices.begin(), vertexOffset + vertexLength)); + //impl->indexes.insert(impl->indexes.end(), + // std::next(indexes.begin(), indexOffset), + // std::next(indexes.begin(), indexOffset + indexLength)); + + std::for_each(std::next(vertices.begin(), vertexOffset), + std::next(vertices.begin(), vertexOffset + vertexLength), + [&](const std::array& x){ impl->vertices.emplace_back(Impl::VT({{x}})); }); + for (auto i = std::next(indexes.begin(), indexOffset); i != std::next(indexes.begin(), indexOffset + indexLength); ) { + impl->indexes.emplace_back(*i++, *i++, *i++); + } +} + } // namespace gfx } // namespace mbgl diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 51cebedf3..eea9757ac 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -463,7 +463,15 @@ bool Context::setupDraw(const PaintParameters& parameters, const gfx::Drawable& } setDepthMode(parameters.depthModeForSublayer(0, drawable.getDepthType())); - setStencilMode(gfx::StencilMode::disabled()); + + if (auto tileID = drawable.getTileID()) { + // Doesn't work until the clipping masks are generated + //parameters.stencilModeForClipping(tileID->toUnwrapped()); + setStencilMode(gfx::StencilMode::disabled()); + } else { + setStencilMode(gfx::StencilMode::disabled()); + } + setColorMode(gfx::ColorMode::alphaBlended()); setCullFaceMode(gfx::CullFaceMode::disabled()); diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index f84472b35..b5b7aad80 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -275,11 +276,11 @@ void RenderFillLayer::layerRemoved(UniqueChangeRequestVec& changes) { localDrawables.cbegin(), localDrawables.cend(), changes, [](auto& ii) { return ii->second->getId(); }); } -void RenderFillLayer::update(const int32_t /*layerIndex*/, +void RenderFillLayer::update(const int32_t layerIndex, gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& /*state*/, - UniqueChangeRequestVec& /*changes*/) { + UniqueChangeRequestVec& changes) { std::unique_lock guard(mutex); if (!shader) { @@ -387,17 +388,72 @@ void RenderFillLayer::update(const int32_t /*layerIndex*/, // } // } + std::unordered_set newTileIDs(renderTiles->size()); + std::transform(renderTiles->begin(), renderTiles->end(), + std::inserter(newTileIDs, newTileIDs.begin()), + [](const auto& renderTile)->OverscaledTileID{ return renderTile.get().getOverscaledTileID(); }); + + // For each existing tile drawable... + for (auto iter = tileDrawables.begin(); iter != tileDrawables.end();) { + const auto& drawable = iter->second; + + // Has this tile dropped out of the cover set? + if (newTileIDs.find(iter->first) == newTileIDs.end()) { + // remove it + if (drawable) { + 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; + continue; + } + ++iter; + + // update... + } + + std::unique_ptr builder; + if (unevaluated.get().isUndefined()) { // parameters.renderTileClippingMasks(renderTiles); for (const RenderTile& tile : *renderTiles) { + const auto& tileID = tile.getOverscaledTileID(); + + const auto result = tileDrawables.insert(std::make_pair(tileID, gfx::DrawablePtr())); + if (!result.second) { + // Already present + continue; + } + const auto renderPass = RenderPass::Translucent; const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass); if (!renderData) { continue; } - // auto& bucket = static_cast(*renderData->bucket); - // const auto& evaluated = getEvaluated(renderData->layerProperties); + auto& bucket = static_cast(*renderData->bucket); + //const auto& evaluated = getEvaluated(renderData->layerProperties); + if (!builder) { + builder = context.createDrawableBuilder("fill"); + builder->setShader(shader); + builder->addTweaker(context.createDrawableTweaker()); + //builder->setColor(color); + builder->setColorMode(gfx::DrawableBuilder::ColorMode::PerDrawable); + builder->setDepthType(gfx::DepthMaskType::ReadWrite); + builder->setLayerIndex(layerIndex); + } + + const std::vector>>::Vertex>& verts = bucket.vertices.vector(); + std::vector> rawVerts(verts.size()); + std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x){ return x.a1; }); + + for (const auto& seg : bucket.triangleSegments) { + builder->addTriangles(rawVerts, seg.vertexOffset, seg.vertexLength, + bucket.triangles.vector(), seg.indexOffset, seg.indexLength); + } + // evaluated.get(), // evaluated.get(), // parameters.stencilModeForClipping(tile.id), @@ -427,6 +483,20 @@ void RenderFillLayer::update(const int32_t /*layerIndex*/, // bucket.lineSegments, // FillOutlineProgram::TextureBindings{}); // } + + builder->flush(); + + 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)); + } + } } else { // if (parameters.pass != RenderPass::Translucent) { diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 8eadc83a9..24bac151e 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -210,6 +210,11 @@ void Renderer::Impl::render(const RenderTree& renderTree) { parameters.depthRangeSize = 1 - (1 + 2) * parameters.numSublayers * parameters.depthEpsilon; const auto debugGroup(parameters.renderPass->createDebugGroup("drawables")); + // TODO: Render tile masks + //for (auto& layer : renderLayers) { + // parameters.renderTileClippingMasks(renderTiles); + //} + for (const auto& drawPtr : drawables) { auto& drawable = *drawPtr;