From b060abeb9214bb654ccdc5ea3e8ea199fbbac5e2 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Fri, 9 Jun 2023 07:23:17 -0700 Subject: [PATCH] Topic/fill pass (#1225) --- include/mbgl/gfx/drawable.hpp | 15 +- include/mbgl/gfx/drawable_builder.hpp | 9 +- include/mbgl/renderer/layer_group.hpp | 3 +- src/mbgl/gfx/drawable.cpp | 17 + src/mbgl/gfx/drawable_builder.cpp | 6 + src/mbgl/gl/drawable_gl.cpp | 8 +- src/mbgl/gl/layer_group_gl.cpp | 5 + src/mbgl/renderer/layer_group.cpp | 9 +- .../renderer/layers/fill_layer_tweaker.cpp | 10 +- .../renderer/layers/render_fill_layer.cpp | 496 +++++++++--------- src/mbgl/renderer/paint_property_binder.hpp | 4 +- src/mbgl/renderer/render_tile.cpp | 5 + src/mbgl/renderer/render_tile.hpp | 3 + src/mbgl/renderer/tile_render_data.hpp | 1 + src/mbgl/util/std.hpp | 12 +- 15 files changed, 344 insertions(+), 259 deletions(-) diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index d913d7fce..bda93e5e6 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -29,6 +29,7 @@ class ShaderProgramBase; using ShaderProgramBasePtr = std::shared_ptr; using DrawPriority = int64_t; using DrawableTweakerPtr = std::shared_ptr; +using Texture2DPtr = std::shared_ptr; class Drawable { public: @@ -104,6 +105,15 @@ public: /// @param location A sampler location in the shader being used with this drawable. void setTexture(std::shared_ptr texture, int32_t location); + using TexSourceFunc = std::function; + + /// @brief Provide a function to get the current texture + void setTextureSource(int32_t location, TexSourceFunc); + const TexSourceFunc& getTextureSource(int32_t location) const; + + /// @brief Provide all texture sources at once + void setTextureSources(std::vector); + /// Whether the drawble should be drawn bool getEnabled() const { return enabled; } void setEnabled(bool value) { enabled = value; } @@ -120,8 +130,8 @@ public: int32_t getSubLayerIndex() const { return subLayerIndex; } void setSubLayerIndex(int32_t value) { subLayerIndex = value; } - std::optional getTileID() const { return tileID; } - void setTileID(OverscaledTileID value) { tileID = value; } + const std::optional& getTileID() const { return tileID; } + void setTileID(const OverscaledTileID& value) { tileID = value; } DepthMaskType getDepthType() const { return depthType; } void setDepthType(DepthMaskType value) { depthType = value; } @@ -174,6 +184,7 @@ protected: std::unique_ptr impl; Textures textures; + std::vector textureSources; std::vector tweakers; }; diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index 77ce6bc9b..735be0a96 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -21,6 +21,7 @@ class ShaderProgramBase; using DrawableTweakerPtr = std::shared_ptr; using ShaderProgramBasePtr = std::shared_ptr; +using Texture2DPtr = std::shared_ptr; /** Base class for drawable builders, which construct Drawables from primitives @@ -111,7 +112,12 @@ public: /// @brief Attach the given texture at the given sampler location. /// @param texture Texture2D instance /// @param location A sampler location in the shader being used. - void setTexture(const std::shared_ptr& texture, int32_t location); + void setTexture(const gfx::Texture2DPtr&, int32_t location); + + using TexSourceFunc = std::function; + + /// @brief Provide a function to get the current texture + void setTextureSource(int32_t location, TexSourceFunc); /// Add a triangle void addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2); @@ -171,6 +177,7 @@ protected: ColorAttrMode colorAttrMode = ColorAttrMode::PerVertex; VertexAttributeArray vertexAttrs; gfx::Drawable::Textures textures; + std::vector textureSources; struct Impl; std::unique_ptr impl; diff --git a/include/mbgl/renderer/layer_group.hpp b/include/mbgl/renderer/layer_group.hpp index 7cddc03f3..1e81b0571 100644 --- a/include/mbgl/renderer/layer_group.hpp +++ b/include/mbgl/renderer/layer_group.hpp @@ -102,7 +102,8 @@ public: void observeDrawables(std::function) override; /// Call the provided function for each drawable for the given tile - void observeDrawables(mbgl::RenderPass, const OverscaledTileID&, std::function) const; + void observeDrawables(mbgl::RenderPass, const OverscaledTileID&, std::function&&); + void observeDrawables(mbgl::RenderPass, const OverscaledTileID&, std::function&&) const; std::size_t clearDrawables(); diff --git a/src/mbgl/gfx/drawable.cpp b/src/mbgl/gfx/drawable.cpp index edb1d3347..aaa3b1ee3 100644 --- a/src/mbgl/gfx/drawable.cpp +++ b/src/mbgl/gfx/drawable.cpp @@ -46,5 +46,22 @@ void Drawable::removeTexture(int32_t location) { } } +/// @brief Provide a function to get the current texture +void Drawable::setTextureSource(int32_t location, TexSourceFunc source) { + textureSources.resize(std::max(textureSources.size(), static_cast(location + 1))); + textureSources[location] = std::move(source); +} + +static const Drawable::TexSourceFunc noSource; + +const Drawable::TexSourceFunc& Drawable::getTextureSource(int32_t location) const { + return (static_cast(location) < textureSources.size()) ? textureSources[location] : noSource; +} + +/// @brief Provide all texture sources at once +void Drawable::setTextureSources(std::vector sources) { + textureSources = std::move(sources); +} + } // namespace gfx } // namespace mbgl diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index b32bf4f52..86900629a 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -50,6 +50,7 @@ void DrawableBuilder::flush() { draw->setCullFaceMode(impl->cullFaceMode); draw->setShader(shader); draw->setTextures(textures); + draw->setTextureSources(textureSources); if (auto drawAttrs = getVertexAttributes().clone()) { vertexAttrs.observeAttributes([&](const std::string& iName, const VertexAttribute& iAttr) { @@ -112,6 +113,11 @@ void DrawableBuilder::setTexture(const std::shared_ptr& texture, textures.emplace_back(texture, location); } +void DrawableBuilder::setTextureSource(int32_t location, TexSourceFunc source) { + textureSources.resize(std::max(textureSources.size(), static_cast(location + 1))); + textureSources[location] = std::move(source); +} + void DrawableBuilder::addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) { const auto n = static_cast(impl->vertices.elements()); impl->vertices.emplace_back(Impl::VT({{{x0, y0}}})); diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index 662185c37..fe874d91a 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -39,7 +39,7 @@ void DrawableGL::draw(const PaintParameters& parameters) const { context.setDepthMode(parameters.depthModeForSublayer(getSubLayerIndex(), getDepthType())); // force disable depth test for debugging - // setDepthMode({gfx::DepthFunctionType::Always, gfx::DepthMaskType::ReadOnly, {0,1}}); + // context.setDepthMode({gfx::DepthFunctionType::Always, gfx::DepthMaskType::ReadOnly, {0,1}}); if (needsStencil && tileID) { context.setStencilMode(parameters.stencilModeForClipping(tileID->toUnwrapped())); @@ -176,6 +176,12 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { }; } + for (std::size_t i = 0; i < textureSources.size(); ++i) { + if (const auto& source = textureSources[i]) { + setTexture(source(), static_cast(i)); + } + } + const bool texturesNeedUpload = std::any_of( textures.begin(), textures.end(), [](const auto& tex) { return tex.texture->needsUpload(); }); diff --git a/src/mbgl/gl/layer_group_gl.cpp b/src/mbgl/gl/layer_group_gl.cpp index e48e5247f..419abe3f3 100644 --- a/src/mbgl/gl/layer_group_gl.cpp +++ b/src/mbgl/gl/layer_group_gl.cpp @@ -62,6 +62,11 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) parameters.renderTileClippingMasks(tileIDs); } +#if !defined(NDEBUG) + const auto label = getName() + (getName().empty() ? "" : "-") + "render"; + const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); +#endif + observeDrawables([&](gfx::Drawable& drawable) { if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) { return; diff --git a/src/mbgl/renderer/layer_group.cpp b/src/mbgl/renderer/layer_group.cpp index a3cd5f290..0b212f4a8 100644 --- a/src/mbgl/renderer/layer_group.cpp +++ b/src/mbgl/renderer/layer_group.cpp @@ -103,7 +103,14 @@ void TileLayerGroup::observeDrawables(std::function void TileLayerGroup::observeDrawables(mbgl::RenderPass pass, const OverscaledTileID& tileID, - std::function f) const { + std::function&& f) { + const auto range = impl->tileDrawables.equal_range({pass, tileID}); + std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); }); +} + +void TileLayerGroup::observeDrawables(mbgl::RenderPass pass, + const OverscaledTileID& tileID, + std::function&& f) const { const auto range = impl->tileDrawables.equal_range({pass, tileID}); std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); }); } diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp index 25718df08..cfbcdb3aa 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace mbgl { @@ -44,15 +45,6 @@ struct alignas(16) FillDrawableUBO { }; static_assert(sizeof(FillDrawableUBO) == 208); -// move to utils, or does it already exist somewhere? -template -auto concat(const std::array& a1, const std::array& a2) { - std::array result; - std::copy(a1.cbegin(), a1.cend(), result.begin()); - std::copy(a2.cbegin(), a2.cend(), result.begin() + N); - return result; -} - void FillLayerTweaker::execute(LayerGroup& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 46bb828aa..7a4ecddf2 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ #include #include #include +#include namespace mbgl { @@ -277,6 +279,101 @@ void RenderFillLayer::removeTile(RenderPass renderPass, const OverscaledTileID& stats.tileDrawablesRemoved += tileLayerGroup->removeDrawables(renderPass, tileID).size(); } +using FloatAttr = gfx::AttributeType; +using FloatPairAttr = gfx::AttributeType; +using FloatPair = FloatPairAttr::Value; +using UShortQuadAttr = gfx::AttributeType; +using UShortQuad = UShortQuadAttr::Value; +using FloatVertex = gfx::detail::VertexType; +using FloatPairVertex = gfx::detail::VertexType; +using UShortQuadVertex = gfx::detail::VertexType; +using FloatBinder = PaintPropertyBinder, FloatAttr>; +using FloatPairBinder = + PaintPropertyBinder, FloatPairAttr>; +using ColorBinder = PaintPropertyBinder, FloatPairAttr>; +using ImageBinder = PaintPropertyBinder>, + UShortQuadAttr, + UShortQuadAttr>; + +bool bindFloat(const FloatBinder& binder, gfx::VertexAttributeArray& attrs, std::string attributeName) { + const auto count = binder.getVertexCount(); + if (auto& attr = attrs.getOrAdd(std::move(attributeName))) { + for (std::size_t i = 0; i < count; ++i) { + const auto& value = static_cast(binder.getVertexValue(i))->a1; + const auto& from = value; // TODO: should be two different values, right? + const auto& to = value; + attr->set(i, util::concat(from, to)); + } + return true; + } + return false; +} +bool bindFloat(const std::unique_ptr& binder, + gfx::VertexAttributeArray& attrs, + std::string attributeName) { + return binder && bindFloat(*binder, attrs, std::move(attributeName)); +} + +bool bindFloatPair(const FloatPairBinder& binder, gfx::VertexAttributeArray& attrs, std::string attributeName) { + const auto count = binder.getVertexCount(); + // check that vertexVector.elements() == sum(segments.vertexLength) + if (auto& attr = attrs.getOrAdd(std::move(attributeName))) { + for (std::size_t i = 0; i < count; ++i) { + const auto& value = static_cast(binder.getVertexValue(i))->a1; + const auto& from = value; // TODO: should be two different values, right? + const auto& to = value; + attr->set(i, util::concat(from, to)); + } + return true; + } + return false; +} +bool bindFloatPair(const std::unique_ptr& binder, + gfx::VertexAttributeArray& attrs, + std::string attributeName) { + return binder && bindFloatPair(*binder, attrs, std::move(attributeName)); +} + +bool bindColor(const ColorBinder& binder, gfx::VertexAttributeArray& attrs, std::string attributeName) { + const auto count = binder.getVertexCount(); + // check that vertexVector.elements() == sum(segments.vertexLength) + if (auto& attr = attrs.getOrAdd(std::move(attributeName))) { + for (std::size_t i = 0; i < count; ++i) { + const auto& value = static_cast(binder.getVertexValue(i))->a1; + const auto& from = value; // TODO: should be two different values, right? + const auto& to = value; + attr->set(i, util::concat(from, to)); + } + return true; + } + return false; +} +bool bindColor(const std::unique_ptr& binder, + gfx::VertexAttributeArray& attrs, + std::string attributeName) { + return binder && bindColor(*binder, attrs, std::move(attributeName)); +} + +bool bindImage(const ImageBinder& binder, gfx::VertexAttributeArray& attrs, std::string attributeName) { + const auto count = binder.getVertexCount(); + // check that vertexVector.elements() == sum(segments.vertexLength) + if (auto& attr = attrs.getOrAdd(std::move(attributeName))) { + for (std::size_t i = 0; i < count; ++i) { + const auto& value = static_cast(binder.getVertexValue(i))->a1; + attr->set(i, util::cast(value)); + } + return true; + } + return false; +} +bool bindImage(const std::unique_ptr& binder, + gfx::VertexAttributeArray& attrs, + std::string attributeName) { + return binder && bindImage(*binder, attrs, std::move(attributeName)); +} + void RenderFillLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& /*state*/, @@ -329,276 +426,195 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, gfx::VertexAttributeArray patternVertexAttrs; gfx::VertexAttributeArray patternOutlineVertexAttrs; - const auto finish = [&](gfx::DrawableBuilder& builder, RenderPass pass, const OverscaledTileID& tileID) { + constexpr auto samplerLocation = 0; + const auto layerPrefix = getID() + "/"; + const auto renderPass = static_cast(evaluatedProperties->renderPasses); + + const auto finish = [&](gfx::DrawableBuilder& builder, const OverscaledTileID& tileID) { builder.flush(); for (auto& drawable : builder.clearDrawables()) { drawable->setTileID(tileID); - tileLayerGroup->addDrawable(pass, tileID, std::move(drawable)); + tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.tileDrawablesAdded; } }; - const auto commonInit = [](gfx::DrawableBuilder& builder) { + const auto commonInit = [&](gfx::DrawableBuilder& builder) { builder.setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None); builder.setCullFaceMode(gfx::CullFaceMode::disabled()); builder.setNeedsStencil(true); }; - for (const auto renderPass : {RenderPass::Opaque, RenderPass::Translucent}) { - if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) { + tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) { + // If the render pass has changed or the tile has dropped out of the cover set, remove it. + const auto tileID = drawable->getTileID(); + if (drawable->getRenderPass() != renderPass || (tileID && newTileIDs.find(*tileID) == newTileIDs.end())) { + drawable.reset(); + ++stats.tileDrawablesRemoved; + } + }); + + for (const RenderTile& tile : *renderTiles) { + const auto& tileID = tile.getOverscaledTileID(); + + // If we already have drawables for this tile, skip. + if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) { continue; } - tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) { - // Has this tile dropped out of the cover set? - const auto tileID = drawable->getTileID(); - if (tileID && newTileIDs.find(*tileID) == newTileIDs.end()) { - // remove it - drawable.reset(); - ++stats.tileDrawablesRemoved; + const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass); + if (!renderData) { + removeTile(renderPass, tileID); + continue; + } + + auto& bucket = static_cast(*renderData->bucket); + const auto& evaluated = getEvaluated(renderData->layerProperties); + const auto& crossfade = getCrossfade(renderData->layerProperties); + + std::vector> rawVerts; + const auto buildVertices = [&]() { + const std::vector>>::Vertex>& + verts = bucket.vertices.vector(); + if (rawVerts.size() < verts.size()) { + rawVerts.resize(verts.size()); + std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; }); } - }); + }; - constexpr auto samplerLocation = 0; - const auto layerPrefix = getID() + "/"; + fillVertexAttrs.clear(); + outlineVertexAttrs.clear(); - for (const RenderTile& tile : *renderTiles) { - const auto& tileID = tile.getOverscaledTileID(); + const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID()); - // If we already have drawables for this tile, skip. - // If a drawable needs to be updated, that's handled in the layer tweaker. - if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) { + if (unevaluated.get().isUndefined()) { + // Fill will occur in opaque or translucent pass based on `opaquePassCutoff`. + // Outline always occurs in translucent pass, defaults to fill color + const auto doOutline = evaluated.get(); + + bindColor(paintPropertyBinders.get(), fillVertexAttrs, "a_color"); + bindFloat(paintPropertyBinders.get(), fillVertexAttrs, "a_opacity"); + + if (doOutline) { + bindColor(paintPropertyBinders.get(), outlineVertexAttrs, "a_outline_color"); + bindFloat(paintPropertyBinders.get(), outlineVertexAttrs, "a_opacity"); + } + + if (!fillBuilder && fillShader) { + if (auto builder = context.createDrawableBuilder(layerPrefix + "fill")) { + commonInit(*builder); + builder->setShader(fillShader); + builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite + : gfx::DepthMaskType::ReadOnly); + builder->setSubLayerIndex(0); + builder->setRenderPass(renderPass); + fillBuilder = std::move(builder); + } + } + if (doOutline && !outlineBuilder && outlineShader) { + if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-outline")) { + commonInit(*builder); + builder->setShader(outlineShader); + builder->setLineWidth(2.0f); + builder->setDepthType(gfx::DepthMaskType::ReadOnly); + builder->setSubLayerIndex(unevaluated.get().isUndefined() ? 2 : 0); + builder->setRenderPass(RenderPass::Translucent); + outlineBuilder = std::move(builder); + } + } + + if (fillBuilder) { + buildVertices(); + fillBuilder->setVertexAttributes(fillVertexAttrs); + fillBuilder->addVertices(rawVerts, 0, rawVerts.size()); + fillBuilder->setSegments(gfx::Triangles(), + bucket.triangles.vector(), + reinterpret_cast>&>(bucket.triangleSegments)); + finish(*fillBuilder, tileID); + } + if (outlineBuilder) { + buildVertices(); + outlineBuilder->setVertexAttributes(outlineVertexAttrs); + outlineBuilder->addVertices(rawVerts, 0, rawVerts.size()); + outlineBuilder->setSegments(gfx::Lines(2), + bucket.lines.vector(), + reinterpret_cast>&>(bucket.lineSegments)); + finish(*outlineBuilder, tileID); + } + } else { // FillPattern is defined + if ((renderPass & RenderPass::Translucent) == 0) { continue; } - const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass); - if (!renderData) { - removeTile(renderPass, tileID); - continue; + // Outline does not default to fill in the pattern case + const auto doOutline = evaluated.get() && unevaluated.get().isUndefined(); + const auto& fillPatternValue = evaluated.get().constantOr(Faded{"", ""}); + const auto patternPosA = tile.getPattern(fillPatternValue.from.id()); + const auto patternPosB = tile.getPattern(fillPatternValue.to.id()); + paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade); + + // if (samplerLocation < 0) curShader->getSamplerLocation("u_image"); + + bindFloat(paintPropertyBinders.get(), fillVertexAttrs, "a_opacity"); + bindImage(paintPropertyBinders.get(), fillVertexAttrs, "a_pattern_from"); + bindImage(paintPropertyBinders.get(), fillVertexAttrs, "a_pattern_to"); + + if (doOutline) { + bindFloat(paintPropertyBinders.get(), outlineVertexAttrs, "a_opacity"); + bindImage(paintPropertyBinders.get(), outlineVertexAttrs, "a_pattern_from"); + bindImage(paintPropertyBinders.get(), outlineVertexAttrs, "a_pattern_to"); } - auto& bucket = static_cast(*renderData->bucket); - const auto& evaluated = getEvaluated(renderData->layerProperties); - const auto& crossfade = getCrossfade(renderData->layerProperties); - - std::vector> rawVerts; - const auto buildVertices = [&]() { - const std::vector>>::Vertex>& - verts = bucket.vertices.vector(); - if (rawVerts.size() < verts.size()) { - rawVerts.resize(verts.size()); - std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; }); - } - }; - - fillVertexAttrs.clear(); - outlineVertexAttrs.clear(); - - const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID()); - - if (unevaluated.get().isUndefined()) { - const auto evalColor = evaluated.get().constantOr(Color()); - const auto fillOpacity = evaluated.get().constantOr(0); - const auto fillColor = evalColor * (fillOpacity > 0.0f ? fillOpacity : 1.0f); - const auto fillRenderPass = (fillColor.a >= 1.0f - /* && parameters.currentLayer >= parameters.opaquePassCutoff*/) - ? RenderPass::Opaque - : RenderPass::Translucent; - const auto doFill = fillRenderPass == renderPass; - const auto doOutline = evaluated.get() && renderPass == RenderPass::Translucent; - - if (!doFill && !doOutline) { - removeTile(renderPass, tileID); - continue; - } - - if (doFill) { - if (auto& binder = paintPropertyBinders.get()) { - const auto count = binder->getVertexCount(); - // check that vertexVector.elements() == sum(segments.vertexLength) - if (auto& attr = fillVertexAttrs.getOrAdd("a_color")) { - for (std::size_t i = 0; i < count; ++i) { - const auto& packed = - static_cast>*>( - binder->getVertexValue(i)) - ->a1; - attr->set(i, - {packed[0], packed[1], packed[0], packed[1]}); - } - } + if (!patternBuilder && patternShader) { + if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-pattern")) { + commonInit(*builder); + builder->setShader(patternShader); + builder->setDepthType(gfx::DepthMaskType::ReadWrite); + builder->setSubLayerIndex(1); + builder->setRenderPass(RenderPass::Translucent); + if (const auto& atlases = tile.getAtlasTextures()) { + builder->setTextureSource(samplerLocation, [=]() { return atlases ? atlases->icon : nullptr; }); } + patternBuilder = std::move(builder); } - if (doOutline) { - if (auto& binder = paintPropertyBinders.get()) { - const auto count = binder->getVertexCount(); - if (auto& attr = outlineVertexAttrs.getOrAdd("a_outline_color")) { - for (std::size_t i = 0; i < count; ++i) { - const auto& packed = - static_cast>*>( - binder->getVertexValue(i)) - ->a1; - attr->set(i, - {packed[0], packed[1], packed[0], packed[1]}); - } - } - } - } - if (auto& binder = paintPropertyBinders.get()) { - const auto count = binder->getVertexCount(); - for (auto& attrs : - {std::reference_wrapper(fillVertexAttrs), std::reference_wrapper(outlineVertexAttrs)}) { - if (auto& attr = attrs.get().getOrAdd("a_opacity")) { - for (std::size_t i = 0; i < count; ++i) { - const auto& opacity = - static_cast>*>( - binder->getVertexValue(i)) - ->a1; - attr->set(i, {opacity[0], opacity[0]}); - } - } + } + if (doOutline && !outlinePatternBuilder && outlinePatternShader) { + if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-outline-pattern")) { + commonInit(*builder); + builder->setShader(outlinePatternShader); + builder->setLineWidth(2.0f); + builder->setDepthType(gfx::DepthMaskType::ReadOnly); + builder->setSubLayerIndex(2); + builder->setRenderPass(RenderPass::Translucent); + if (const auto& atlases = tile.getAtlasTextures()) { + builder->setTextureSource(samplerLocation, [=]() { return atlases ? atlases->icon : nullptr; }); } + outlinePatternBuilder = std::move(builder); } + } - if (doFill && !fillBuilder && fillShader) { - if (auto builder = context.createDrawableBuilder(layerPrefix + "fill")) { - commonInit(*builder); - builder->setShader(fillShader); - builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite - : gfx::DepthMaskType::ReadOnly); - builder->setSubLayerIndex(0); - fillBuilder = std::move(builder); - } - } - if (doOutline && !outlineBuilder && outlineShader) { - if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-outline")) { - commonInit(*builder); - builder->setShader(outlineShader); - builder->setLineWidth(2.0f); - builder->setDepthType(gfx::DepthMaskType::ReadOnly); - builder->setSubLayerIndex(unevaluated.get().isUndefined() ? 2 : 0); - outlineBuilder = std::move(builder); - } - } - - if (fillBuilder) { - buildVertices(); - fillBuilder->setRenderPass(renderPass); - fillBuilder->setVertexAttributes(fillVertexAttrs); - fillBuilder->addVertices(rawVerts, 0, rawVerts.size()); - fillBuilder->setSegments( - gfx::Triangles(), - bucket.triangles.vector(), - reinterpret_cast>&>(bucket.triangleSegments)); - finish(*fillBuilder, renderPass, tileID); - } - if (outlineBuilder) { - buildVertices(); - outlineBuilder->setRenderPass(renderPass); - outlineBuilder->setVertexAttributes(outlineVertexAttrs); - outlineBuilder->addVertices(rawVerts, 0, rawVerts.size()); - outlineBuilder->setSegments( - gfx::Lines(2), - bucket.lines.vector(), - reinterpret_cast>&>(bucket.lineSegments)); - finish(*outlineBuilder, renderPass, tileID); - } - } else { // FillPattern is defined - if (renderPass != RenderPass::Translucent) { - continue; - } - - const auto doOutline = evaluated.get() && - unevaluated.get().isUndefined(); - const auto& fillPatternValue = evaluated.get().constantOr( - Faded{"", ""}); - const auto patternPosA = tile.getPattern(fillPatternValue.from.id()); - const auto patternPosB = tile.getPattern(fillPatternValue.to.id()); - paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade); - - // if (samplerLocation < 0) curShader->getSamplerLocation("u_image"); - - if (auto& binder = paintPropertyBinders.get()) { - const auto count = binder->getVertexCount(); - for (auto& attrs : {std::reference_wrapper(patternVertexAttrs), - std::reference_wrapper(patternOutlineVertexAttrs)}) { - if (auto& attr = attrs.get().getOrAdd("a_opacity")) { - for (std::size_t i = 0; i < count; ++i) { - const auto& opacity = - static_cast>*>( - binder->getVertexValue(i)) - ->a1; - attr->set(i, {opacity[0], opacity[0]}); - } - } - } - } - // if (auto& binder = paintPropertyBinders.get()) { - // const auto count = binder->getVertexCount(); - // for (auto& attrs : - // {std::reference_wrapper(patternVertexAttrs), - // std::reference_wrapper(patternOutlineVertexAttrs)}) { - // if (auto& attr = attrs.get().getOrAdd("a_pattern_from")) { - // for (std::size_t i = 0; i < count; ++i) { - // const auto& opacity = - // static_cast>*>( - // binder->getVertexValue(i)) - // ->a1; - // attr->set(i, {}); - // } - // } - // } - // } - - if (!patternBuilder && patternShader) { - if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-pattern")) { - commonInit(*builder); - builder->setShader(fillShader); - builder->setDepthType(gfx::DepthMaskType::ReadWrite); - builder->setSubLayerIndex(1); - if (auto& tex = tile.getIconAtlasTexture()) { - builder->setTexture(tex, samplerLocation); - } - patternBuilder = std::move(builder); - } - } - if (doOutline && !outlinePatternBuilder && outlinePatternShader) { - if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-outline-pattern")) { - commonInit(*builder); - builder->setShader(outlineShader); - builder->setLineWidth(2.0f); - builder->setDepthType(gfx::DepthMaskType::ReadOnly); - builder->setSubLayerIndex(2); - if (auto& tex = tile.getIconAtlasTexture()) { - builder->setTexture(tex, samplerLocation); - } - outlinePatternBuilder = std::move(builder); - } - } - - if (patternBuilder) { - buildVertices(); - patternBuilder->setRenderPass(renderPass); - patternBuilder->setVertexAttributes(fillVertexAttrs); - patternBuilder->addVertices(rawVerts, 0, rawVerts.size()); - patternBuilder->setSegments( - gfx::Triangles(), - bucket.triangles.vector(), - reinterpret_cast>&>(bucket.triangleSegments)); - finish(*patternBuilder, renderPass, tileID); - } - if (outlinePatternBuilder) { - buildVertices(); - outlinePatternBuilder->setRenderPass(renderPass); - outlinePatternBuilder->setVertexAttributes(outlineVertexAttrs); - outlinePatternBuilder->addVertices(rawVerts, 0, rawVerts.size()); - outlinePatternBuilder->setSegments( - gfx::Lines(2), - bucket.lines.vector(), - reinterpret_cast>&>(bucket.lineSegments)); - finish(*outlinePatternBuilder, renderPass, tileID); - } + if (patternBuilder) { + buildVertices(); + patternBuilder->setRenderPass(renderPass); + patternBuilder->setVertexAttributes(fillVertexAttrs); + patternBuilder->addVertices(rawVerts, 0, rawVerts.size()); + patternBuilder->setSegments( + gfx::Triangles(), + bucket.triangles.vector(), + reinterpret_cast>&>(bucket.triangleSegments)); + finish(*patternBuilder, tileID); + } + if (outlinePatternBuilder) { + buildVertices(); + outlinePatternBuilder->setRenderPass(renderPass); + outlinePatternBuilder->setVertexAttributes(outlineVertexAttrs); + outlinePatternBuilder->addVertices(rawVerts, 0, rawVerts.size()); + outlinePatternBuilder->setSegments( + gfx::Lines(2), + bucket.lines.vector(), + reinterpret_cast>&>(bucket.lineSegments)); + finish(*outlinePatternBuilder, tileID); } } } diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp index 5f39d1463..19dbcc483 100644 --- a/src/mbgl/renderer/paint_property_binder.hpp +++ b/src/mbgl/renderer/paint_property_binder.hpp @@ -222,9 +222,9 @@ public: return constantPatternPositions; } - std::size_t getVertexCount() const override { return 0; } + std::size_t getVertexCount() const override { return 1; } const /*std::tuple>&*/ void* getVertexValue(std::size_t) const override { - return nullptr; // ? + return &constantPatternPositions; } private: diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp index ac7e8767a..06f7f8de6 100644 --- a/src/mbgl/renderer/render_tile.cpp +++ b/src/mbgl/renderer/render_tile.cpp @@ -124,6 +124,11 @@ gfx::TextureBinding RenderTile::getIconAtlasTextureBinding(gfx::TextureFilterTyp return {getIconAtlasTexture()->getResource(), filter}; } +static const std::shared_ptr noAtlas; +const std::shared_ptr& RenderTile::getAtlasTextures() const { + return renderData ? renderData->getAtlasTextures() : noAtlas; +} + void RenderTile::upload(gfx::UploadPass& uploadPass) const { assert(renderData); renderData->upload(uploadPass); diff --git a/src/mbgl/renderer/render_tile.hpp b/src/mbgl/renderer/render_tile.hpp index 6f2219dfe..8236cfcff 100644 --- a/src/mbgl/renderer/render_tile.hpp +++ b/src/mbgl/renderer/render_tile.hpp @@ -27,6 +27,7 @@ class PaintParameters; class DebugBucket; class SourcePrepareParameters; class FeatureIndex; +class TileAtlasTextures; class TileRenderData; class RenderTile final { @@ -66,6 +67,8 @@ public: const gfx::Texture2DPtr& getIconAtlasTexture() const; gfx::TextureBinding getIconAtlasTextureBinding(gfx::TextureFilterType) const; + const std::shared_ptr& getAtlasTextures() const; + void upload(gfx::UploadPass&) const; void prepare(const SourcePrepareParameters&); void finishRender(PaintParameters&) const; diff --git a/src/mbgl/renderer/tile_render_data.hpp b/src/mbgl/renderer/tile_render_data.hpp index a3d3b7215..12ce5701d 100644 --- a/src/mbgl/renderer/tile_render_data.hpp +++ b/src/mbgl/renderer/tile_render_data.hpp @@ -30,6 +30,7 @@ public: virtual ~TileRenderData(); const gfx::Texture2DPtr& getGlyphAtlasTexture() const; const gfx::Texture2DPtr& getIconAtlasTexture() const; + const std::shared_ptr& getAtlasTextures() const { return atlasTextures; } // To be implemented for concrete tile types. virtual std::optional getPattern(const std::string&) const; virtual const LayerRenderData* getLayerRenderData(const style::Layer::Impl&) const; diff --git a/src/mbgl/util/std.hpp b/src/mbgl/util/std.hpp index 1db20e09e..577b9c4a9 100644 --- a/src/mbgl/util/std.hpp +++ b/src/mbgl/util/std.hpp @@ -8,7 +8,7 @@ namespace mbgl { namespace util { template -void erase_if(Container &container, ForwardIterator it, Predicate pred) { +void erase_if(Container& container, ForwardIterator it, Predicate pred) { while (it != container.end()) { if (pred(*it)) { it = container.erase(it); @@ -19,9 +19,17 @@ void erase_if(Container &container, ForwardIterator it, Predicate pred) { } template -void erase_if(Container &container, Predicate pred) { +void erase_if(Container& container, Predicate pred) { erase_if(container, container.begin(), pred); } +template +auto concat(const std::array& a1, const std::array& a2) { + std::array result; + std::copy(a1.cbegin(), a1.cend(), result.begin()); + std::copy(a2.cbegin(), a2.cend(), result.begin() + N); + return result; +} + } // namespace util } // namespace mbgl