From 810be67fa23afeb8112037b9cd43bca5462c1728 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Thu, 28 Sep 2023 11:18:42 -0700 Subject: [PATCH] Issue/1687 (#1697) Co-authored-by: Bart Louwers Co-authored-by: mwilsnd --- bazel/core.bzl | 17 ++ include/mbgl/gfx/drawable.hpp | 8 + include/mbgl/gfx/drawable_builder.hpp | 5 + include/mbgl/gfx/shader_group.hpp | 14 +- include/mbgl/gfx/vertex_attribute.hpp | 29 ++- include/mbgl/renderer/layer_group.hpp | 12 +- include/mbgl/renderer/layer_tweaker.hpp | 37 ++- include/mbgl/shaders/gl/shader_group_gl.hpp | 61 +++-- include/mbgl/shaders/layer_ubo.hpp | 2 - include/mbgl/shaders/mtl/background.hpp | 11 +- .../mbgl/shaders/mtl/background_pattern.hpp | 6 +- include/mbgl/shaders/mtl/circle.hpp | 22 +- include/mbgl/shaders/mtl/clipping_mask.hpp | 10 +- include/mbgl/shaders/mtl/common.hpp | 3 - include/mbgl/shaders/mtl/fill.hpp | 82 +------ include/mbgl/shaders/mtl/fill_extrusion.hpp | 18 +- .../shaders/mtl/fill_extrusion_pattern.hpp | 6 +- include/mbgl/shaders/mtl/heatmap.hpp | 16 +- include/mbgl/shaders/mtl/heatmap_texture.hpp | 14 +- include/mbgl/shaders/mtl/hillshade.hpp | 14 +- .../mbgl/shaders/mtl/hillshade_prepare.hpp | 14 +- include/mbgl/shaders/mtl/line.hpp | 46 +--- include/mbgl/shaders/mtl/line_gradient.hpp | 22 +- include/mbgl/shaders/mtl/raster.hpp | 15 +- include/mbgl/shaders/mtl/shader_group.hpp | 18 +- include/mbgl/shaders/mtl/shader_program.hpp | 6 + include/mbgl/shaders/mtl/symbol_icon.hpp | 25 +- include/mbgl/shaders/mtl/symbol_sdf.hpp | 29 +-- .../mbgl/shaders/mtl/symbol_text_and_icon.hpp | 29 +-- include/mbgl/util/string_indexer.hpp | 2 +- src/mbgl/gfx/vertex_attribute.cpp | 3 +- src/mbgl/gl/context.cpp | 3 +- src/mbgl/gl/drawable_gl.cpp | 6 +- src/mbgl/gl/drawable_gl_builder.cpp | 1 + src/mbgl/gl/layer_group_gl.cpp | 3 +- src/mbgl/mtl/context.cpp | 9 +- src/mbgl/mtl/drawable.cpp | 6 +- src/mbgl/mtl/drawable_builder.cpp | 1 + src/mbgl/renderer/layer_group.cpp | 13 ++ src/mbgl/renderer/layer_tweaker.cpp | 34 +-- .../layers/background_layer_tweaker.cpp | 3 + .../renderer/layers/circle_layer_tweaker.cpp | 31 ++- .../layers/collision_layer_tweaker.cpp | 2 +- .../layers/fill_extrusion_layer_tweaker.cpp | 18 +- .../renderer/layers/fill_layer_tweaker.cpp | 46 ++-- .../renderer/layers/heatmap_layer_tweaker.cpp | 19 +- .../layers/heatmap_texture_layer_tweaker.cpp | 4 + .../layers/hillshade_layer_tweaker.cpp | 8 +- .../hillshade_prepare_layer_tweaker.cpp | 4 +- .../renderer/layers/line_layer_tweaker.cpp | 19 +- .../renderer/layers/raster_layer_tweaker.cpp | 4 + .../layers/render_background_layer.cpp | 13 +- .../renderer/layers/render_circle_layer.cpp | 68 +++--- .../renderer/layers/render_circle_layer.hpp | 11 - .../layers/render_fill_extrusion_layer.cpp | 38 ++- .../renderer/layers/render_fill_layer.cpp | 82 +++---- .../renderer/layers/render_fill_layer.hpp | 11 - .../renderer/layers/render_heatmap_layer.cpp | 109 ++++----- .../renderer/layers/render_heatmap_layer.hpp | 21 +- .../layers/render_hillshade_layer.cpp | 112 +++++---- .../layers/render_hillshade_layer.hpp | 3 +- .../renderer/layers/render_line_layer.cpp | 171 ++++++-------- .../renderer/layers/render_line_layer.hpp | 10 - .../renderer/layers/render_raster_layer.cpp | 216 +++++++++--------- .../renderer/layers/render_raster_layer.hpp | 14 +- .../renderer/layers/render_symbol_layer.cpp | 116 ++++++---- .../renderer/layers/render_symbol_layer.hpp | 12 +- .../renderer/layers/symbol_layer_tweaker.cpp | 24 +- .../renderer/layers/symbol_layer_tweaker.hpp | 3 + src/mbgl/renderer/render_layer.cpp | 44 +++- src/mbgl/renderer/render_layer.hpp | 14 +- src/mbgl/renderer/render_target.cpp | 7 +- src/mbgl/renderer/renderer_impl.cpp | 7 +- src/mbgl/shaders/mtl/background.cpp | 17 ++ src/mbgl/shaders/mtl/background_pattern.cpp | 14 ++ src/mbgl/shaders/mtl/circle.cpp | 27 +++ src/mbgl/shaders/mtl/clipping_mask.cpp | 16 ++ src/mbgl/shaders/mtl/fill.cpp | 82 +++++++ src/mbgl/shaders/mtl/fill_extrusion.cpp | 24 ++ .../shaders/mtl/fill_extrusion_pattern.cpp | 14 ++ src/mbgl/shaders/mtl/heatmap.cpp | 21 ++ src/mbgl/shaders/mtl/heatmap_texture.cpp | 20 ++ src/mbgl/shaders/mtl/hillshade.cpp | 19 ++ src/mbgl/shaders/mtl/hillshade_prepare.cpp | 20 ++ src/mbgl/shaders/mtl/line.cpp | 49 ++++ src/mbgl/shaders/mtl/line_gradient.cpp | 27 +++ src/mbgl/shaders/mtl/raster.cpp | 19 ++ src/mbgl/shaders/mtl/shader_program.cpp | 26 ++- src/mbgl/shaders/mtl/symbol_icon.cpp | 30 +++ src/mbgl/shaders/mtl/symbol_sdf.cpp | 36 +++ src/mbgl/shaders/mtl/symbol_text_and_icon.cpp | 36 +++ src/mbgl/util/hash.hpp | 20 ++ test/CMakeLists.txt | 3 +- test/util/hash.test.cpp | 54 +++++ 94 files changed, 1467 insertions(+), 1043 deletions(-) create mode 100644 src/mbgl/shaders/mtl/background.cpp create mode 100644 src/mbgl/shaders/mtl/background_pattern.cpp create mode 100644 src/mbgl/shaders/mtl/circle.cpp create mode 100644 src/mbgl/shaders/mtl/clipping_mask.cpp create mode 100644 src/mbgl/shaders/mtl/fill.cpp create mode 100644 src/mbgl/shaders/mtl/fill_extrusion.cpp create mode 100644 src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp create mode 100644 src/mbgl/shaders/mtl/heatmap.cpp create mode 100644 src/mbgl/shaders/mtl/heatmap_texture.cpp create mode 100644 src/mbgl/shaders/mtl/hillshade.cpp create mode 100644 src/mbgl/shaders/mtl/hillshade_prepare.cpp create mode 100644 src/mbgl/shaders/mtl/line.cpp create mode 100644 src/mbgl/shaders/mtl/line_gradient.cpp create mode 100644 src/mbgl/shaders/mtl/raster.cpp create mode 100644 src/mbgl/shaders/mtl/symbol_icon.cpp create mode 100644 src/mbgl/shaders/mtl/symbol_sdf.cpp create mode 100644 src/mbgl/shaders/mtl/symbol_text_and_icon.cpp create mode 100644 test/util/hash.test.cpp diff --git a/bazel/core.bzl b/bazel/core.bzl index 6329df8eb..e59e7c4a9 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -1019,6 +1019,23 @@ MLN_DRAWABLES_MTL_SOURCE = [ "src/mbgl/mtl/upload_pass.cpp", "src/mbgl/mtl/vertex_attribute.cpp", "src/mbgl/shaders/mtl/shader_program.cpp", + "src/mbgl/shaders/mtl/background.cpp", + "src/mbgl/shaders/mtl/background_pattern.cpp", + "src/mbgl/shaders/mtl/circle.cpp", + "src/mbgl/shaders/mtl/clipping_mask.cpp", + "src/mbgl/shaders/mtl/fill.cpp", + "src/mbgl/shaders/mtl/fill_extrusion.cpp", + "src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp", + "src/mbgl/shaders/mtl/heatmap.cpp", + "src/mbgl/shaders/mtl/heatmap_texture.cpp", + "src/mbgl/shaders/mtl/hillshade.cpp", + "src/mbgl/shaders/mtl/hillshade_prepare.cpp", + "src/mbgl/shaders/mtl/line.cpp", + "src/mbgl/shaders/mtl/line_gradient.cpp", + "src/mbgl/shaders/mtl/raster.cpp", + "src/mbgl/shaders/mtl/symbol_icon.cpp", + "src/mbgl/shaders/mtl/symbol_sdf.cpp", + "src/mbgl/shaders/mtl/symbol_text_and_icon.cpp", ] MLN_DRAWABLES_MTL_HEADERS = [ diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index b13a93b75..13feb6e59 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -18,8 +18,11 @@ namespace mbgl { class Color; class PaintParameters; +class LayerTweaker; enum class RenderPass : uint8_t; +using LayerTweakerPtr = std::shared_ptr; + namespace gfx { class ColorMode; @@ -234,6 +237,10 @@ public: /// Get drawable user-defined type size_t getType() const { return type; } + /// Associate the drawable with a layer tweaker. This is used to manage the lifetime of the tweaker. + void setLayerTweaker(LayerTweakerPtr tweaker) { layerTweaker = std::move(tweaker); } + const LayerTweakerPtr& getLayerTweaker() const { return layerTweaker; } + protected: bool enabled = true; bool enableColor = true; @@ -257,6 +264,7 @@ protected: Textures textures; std::vector tweakers; + LayerTweakerPtr layerTweaker; std::size_t type = 0; }; diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index b13249425..bc5fd59f0 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -145,6 +145,9 @@ public: /// @param location A sampler location in the shader being used. void setTexture(const gfx::Texture2DPtr&, int32_t location); + /// Direct access to the current texture set + const gfx::Drawable::Textures& getTextures() const { return textures; } + /// Add a tweaker to emitted drawable void addTweaker(DrawableTweakerPtr value) { tweakers.emplace_back(std::move(value)); } @@ -225,5 +228,7 @@ protected: std::unique_ptr impl; }; +using UniqueDrawableBuilder = std::unique_ptr; + } // namespace gfx } // namespace mbgl diff --git a/include/mbgl/gfx/shader_group.hpp b/include/mbgl/gfx/shader_group.hpp index cf1fd9b27..3aa8760dd 100644 --- a/include/mbgl/gfx/shader_group.hpp +++ b/include/mbgl/gfx/shader_group.hpp @@ -6,9 +6,12 @@ #include #include #include -#include +#include namespace mbgl { + +using StringIdentity = std::size_t; + namespace gfx { class Context; @@ -138,12 +141,13 @@ public: /// @brief Get a shader from the group by its set of data driven properties as uniforms. /// if no shader is found, create and register the shader. - /// @param propertiesAsUniforms Vector of data driven properties as uniforms. + /// @param propertiesAsUniforms Set of data driven properties as uniforms. /// @param firstAttribName Name of the first attribute /// @return A `gfx::ShaderPtr` - virtual gfx::ShaderPtr getOrCreateShader(gfx::Context&, - [[maybe_unused]] const std::vector& propertiesAsUniforms, - [[maybe_unused]] std::string_view firstAttribName = "a_pos") { + virtual gfx::ShaderPtr getOrCreateShader( + gfx::Context&, + [[maybe_unused]] const std::unordered_set& propertiesAsUniforms, + [[maybe_unused]] std::string_view firstAttribName = "a_pos") { return {}; } diff --git a/include/mbgl/gfx/vertex_attribute.hpp b/include/mbgl/gfx/vertex_attribute.hpp index 17c0c53e4..4ce7dc0d9 100644 --- a/include/mbgl/gfx/vertex_attribute.hpp +++ b/include/mbgl/gfx/vertex_attribute.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -364,9 +365,15 @@ public: } /// Specialized DataDrivenPaintProperty reader + /// @param binders Property binders for the target shader + /// @param evaluated Evaluated properties + /// @param propertiesAsUniforms [out] A set of string identities for the properties which will be constant, not + /// attributes. + /// @details The property name IDs refer to the "a\_" prefixed values to match the shader definitions. template - std::vector readDataDrivenPaintProperties(const Binders& binders, const Evaluated& evaluated) { - std::vector propertiesAsUniforms; + void readDataDrivenPaintProperties(const Binders& binders, + const Evaluated& evaluated, + std::unordered_set& propertiesAsUniforms) { propertiesAsUniforms.reserve(sizeof...(DataDrivenPaintProperty)); ( [&](const auto& attributeNames) { @@ -377,15 +384,14 @@ public: using Type = typename Attribute::Type; // ::mbgl::gfx::AttributeType using InterpType = ZoomInterpolatedAttributeType; + auto& attributeNameID = DataDrivenPaintProperty::AttributeNameIDs[attrIndex]; + if (!attributeNameID) { + attributeNameID = StringIndexer::get(attributePrefix + attributeName.data()); + } + const auto vertexCount = binder->getVertexCount(); const auto isConstant = evaluated.template get().isConstant(); if (vertexCount > 0 && !isConstant) { - auto& attributeNameID = DataDrivenPaintProperty::AttributeNameIDs[attrIndex]; - if (!attributeNameID) { - static const std::string attributePrefix = "a_"; - attributeNameID = StringIndexer::get(attributePrefix + attributeName.data()); - } - if (auto& attr = getOrAdd(*attributeNameID)) { if (const auto& sharedVector = binder->getSharedVertexVector()) { const auto rawSize = static_cast(sharedVector->getRawSize()); @@ -402,15 +408,13 @@ public: } } } - propertiesAsUniforms.emplace_back(std::string()); } else { - propertiesAsUniforms.emplace_back(attributeName); + propertiesAsUniforms.emplace(*attributeNameID); } } } }(DataDrivenPaintProperty::AttributeNames), ...); - return propertiesAsUniforms; } /// Copy another collection into this one @@ -435,7 +439,8 @@ protected: protected: AttributeMap attrs; - static std::unique_ptr nullref; + static const std::unique_ptr nullref; + static const std::string attributePrefix; }; } // namespace gfx diff --git a/include/mbgl/renderer/layer_group.hpp b/include/mbgl/renderer/layer_group.hpp index dd708f8ea..8780ba8d3 100644 --- a/include/mbgl/renderer/layer_group.hpp +++ b/include/mbgl/renderer/layer_group.hpp @@ -13,6 +13,7 @@ namespace mbgl { class LayerGroupBase; class PaintParameters; class RenderOrchestrator; +class RenderTree; class TileLayerGroup; using LayerGroupBasePtr = std::shared_ptr; @@ -28,6 +29,7 @@ using UniqueDrawable = std::unique_ptr; class LayerTweaker; using LayerTweakerPtr = std::shared_ptr; +using LayerTweakerWeakPtr = std::weak_ptr; /** A layer-like group of drawables, not a group of layers. @@ -86,16 +88,16 @@ public: /// @return The number of items removed virtual std::size_t removeDrawablesIf(const std::function&& f) = 0; - /// Attach a tweaker to be run on this layer group for each frame - void setLayerTweaker(LayerTweakerPtr tweaker) { layerTweaker = std::move(tweaker); } + /// Attach a tweaker to be run on this layer group for each frame. + /// Tweaker lifetime is controlled by the render layer and drawables, the layer group retains a weak reference. + void addLayerTweaker(const LayerTweakerPtr& tweaker) { layerTweakers.emplace_back(tweaker); } - /// Get the tweaker attached to this layer group - const LayerTweakerPtr& getLayerTweaker() const { return layerTweaker; } + void runTweakers(const RenderTree&, PaintParameters&); protected: bool enabled = true; int32_t layerIndex; - LayerTweakerPtr layerTweaker; + std::vector layerTweakers; std::string name; }; diff --git a/include/mbgl/renderer/layer_tweaker.hpp b/include/mbgl/renderer/layer_tweaker.hpp index 2b81f1746..403746419 100644 --- a/include/mbgl/renderer/layer_tweaker.hpp +++ b/include/mbgl/renderer/layer_tweaker.hpp @@ -1,25 +1,31 @@ #pragma once +#include #include #include #include #include -#include +#include namespace mbgl { + namespace gfx { +class Drawable; class UniformBuffer; using UniformBufferPtr = std::shared_ptr; } // namespace gfx + namespace shaders { enum class AttributeSource : int32_t; struct ExpressionInputsUBO; } // namespace shaders + namespace style { class LayerProperties; enum class TranslateAnchorType : bool; } // namespace style + class TransformState; class LayerGroupBase; class PaintParameters; @@ -27,6 +33,7 @@ class RenderTree; class UnwrappedTileID; using mat4 = std::array; +using StringIdentity = std::size_t; /** Base class for layer tweakers, which manipulate layer group per frame @@ -45,16 +52,20 @@ public: /// Build the common expression inupts UBO static shaders::ExpressionInputsUBO buildExpressionUBO(double zoom, uint64_t frameCount); + /// @brief Check whether a property name exists within the previously set collection. + bool hasPropertyAsUniform(StringIdentity) const; + shaders::AttributeSource getAttributeSource(StringIdentity) const; + + template + shaders::AttributeSource getAttributeSource(size_t index) { + using ShaderClass = shaders::ShaderSource; + return getAttributeSource(ShaderClass::attributes[index].nameID); + } +#endif // MLN_RENDER_BACKEND_METAL + /// @brief Set the collection of attribute names which will be provided at uniform values rather than per-vertex /// attributes. - /// @details These values should not have "a_" prefixes, as produced by `readDataDrivenPaintProperties`. - void setPropertiesAsUniforms(std::vector); - - /// @brief Check whether a property name exists within the previously set collection. - /// @details The string value provided is expected to have the "a_" prefix, as defined in the shader classes. - bool hasPropertyAsUniform(std::string_view) const; - shaders::AttributeSource getAttributeSource(const std::string_view& attribName) const; -#endif // MLN_RENDER_BACKEND_METAL + void setPropertiesAsUniforms(const std::unordered_set&); void enableOverdrawInspector(bool); @@ -63,6 +74,9 @@ public: void updateProperties(Immutable); protected: + /// Determine whether this tweaker should apply to the given drawable + bool checkTweakDrawable(const gfx::Drawable&) const; + /// Calculate matrices for this tile. /// @param nearClipped If true, the near plane is moved further to enhance depth buffer precision. /// @param inViewportPixelUnits If false, the translation is scaled based on the current zoom. @@ -78,14 +92,15 @@ protected: protected: std::string id; Immutable evaluatedProperties; - bool propertiesUpdated = true; #if MLN_RENDER_BACKEND_METAL // For Metal, whether a property is provided through attribtues or uniforms is specified in // a uniform buffer rather than by a shader compiled with different preprocessor definitions. - std::vector propertiesAsUniforms; + std::unordered_set propertiesAsUniforms; #endif // MLN_RENDER_BACKEND_METAL + bool propertiesUpdated = true; + bool propertiesChanged = true; bool overdrawInspector = false; }; diff --git a/include/mbgl/shaders/gl/shader_group_gl.hpp b/include/mbgl/shaders/gl/shader_group_gl.hpp index cec5740f7..9c54ed5ea 100644 --- a/include/mbgl/shaders/gl/shader_group_gl.hpp +++ b/include/mbgl/shaders/gl/shader_group_gl.hpp @@ -4,6 +4,10 @@ #include #include #include +#include + +#include +#include namespace mbgl { namespace gl { @@ -13,40 +17,61 @@ class ShaderGroupGL final : public gfx::ShaderGroup { public: ShaderGroupGL(const ProgramParameters& programParameters_) : ShaderGroup(), - programParameters(programParameters_){}; + programParameters(programParameters_) {} ~ShaderGroupGL() noexcept override = default; gfx::ShaderPtr getOrCreateShader(gfx::Context& context, - const std::vector& propertiesAsUniforms, + const std::unordered_set& propertiesAsUniforms, std::string_view firstAttribName) override { - constexpr auto& name = shaders::ShaderSource::name; constexpr auto& vert = shaders::ShaderSource::vertex; constexpr auto& frag = shaders::ShaderSource::fragment; - uint32_t key = 0; + // Generate a map key for the specified combination of properties + const size_t key = util::order_independent_hash(propertiesAsUniforms.begin(), propertiesAsUniforms.end()); + + // We could cache these by key here to avoid creating a string key each time, but we + // would need another mutex. We could also push string IDs down into `ShaderGroup`. + const std::string shaderName = getShaderName(key); + auto shader = get(shaderName); + if (shader) { + return shader; + } + + // No match, we need to create the shader. std::string additionalDefines; - for (unsigned int i = 0; i < propertiesAsUniforms.size(); i++) { - if (propertiesAsUniforms[i].empty()) { - continue; + additionalDefines.reserve(propertiesAsUniforms.size() * 48); + for (const auto nameID : propertiesAsUniforms) { + // We expect the names to be prefixed by "a_", but we need just the base here. + const auto prefixedAttrName = StringIndexer::get(nameID); + const auto* prefix = prefixedAttrName.data(); + if (prefix[0] == 'a' && prefix[1] == '_') { + prefix += 2; } - key |= 1 << i; + additionalDefines += "#define HAS_UNIFORM_u_"; - additionalDefines += propertiesAsUniforms[i]; + additionalDefines += prefix; additionalDefines += "\n"; } - const std::string shaderName = std::string(name) + "#" + std::to_string(key); - auto shader = get(shaderName); - if (!shader) { - auto& glContext = static_cast(context); - shader = ShaderProgramGL::create( - glContext, programParameters, shaderName, firstAttribName, vert, frag, additionalDefines); - if (!shader || !registerShader(shader, shaderName)) { - throw std::runtime_error("Failed to register " + shaderName + " with shader group!"); - } + + auto& glContext = static_cast(context); + shader = ShaderProgramGL::create( + glContext, programParameters, shaderName, firstAttribName, vert, frag, additionalDefines); + if (!shader || !registerShader(shader, shaderName)) { + throw std::runtime_error("Failed to register " + shaderName + " with shader group!"); } return shader; } +protected: + std::string getShaderName(std::size_t key) { + constexpr auto& name = shaders::ShaderSource::name; + + // This could be more efficient. + std::ostringstream stream; + stream << name << '#' << key; + return stream.str(); + } + private: ProgramParameters programParameters; }; diff --git a/include/mbgl/shaders/layer_ubo.hpp b/include/mbgl/shaders/layer_ubo.hpp index 7caac8f20..ea69aa070 100644 --- a/include/mbgl/shaders/layer_ubo.hpp +++ b/include/mbgl/shaders/layer_ubo.hpp @@ -5,8 +5,6 @@ #include #include -#define MLN_STRINGIZE(X) #X - namespace mbgl { namespace shaders { diff --git a/include/mbgl/shaders/mtl/background.hpp b/include/mbgl/shaders/mtl/background.hpp index b5e799fca..5dc954ebe 100644 --- a/include/mbgl/shaders/mtl/background.hpp +++ b/include/mbgl/shaders/mtl/background.hpp @@ -14,14 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Float3, 1, "a_pos"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(1, true, true, BackgroundLayerUBO), - MLN_MTL_UNIFORM_BLOCK(2, true, false, BackgroundDrawableUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( #include diff --git a/include/mbgl/shaders/mtl/background_pattern.hpp b/include/mbgl/shaders/mtl/background_pattern.hpp index 428fb855a..8cbd69f68 100644 --- a/include/mbgl/shaders/mtl/background_pattern.hpp +++ b/include/mbgl/shaders/mtl/background_pattern.hpp @@ -9,11 +9,7 @@ template <> struct ShaderSource : public ShaderSource { static constexpr auto name = "BackgroundPatternShader"; - static constexpr UniformBlockInfo uniforms[] = { - {1, sizeof(BackgroundLayerUBO), true, false, "BackgroundLayerUBO"}, - {2, sizeof(BackgroundDrawableUBO), true, false, "BackgroundDrawableUBO"}, - {3, sizeof(BackgroundPatternLayerUBO), true, false, "BackgroundPatternLayerUBO"}, - }; + static const std::array uniforms; }; } // namespace shaders diff --git a/include/mbgl/shaders/mtl/circle.hpp b/include/mbgl/shaders/mtl/circle.hpp index 42eb9fc18..fc049990c 100644 --- a/include/mbgl/shaders/mtl/circle.hpp +++ b/include/mbgl/shaders/mtl/circle.hpp @@ -14,25 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Float2, 1, "a_color"}, - {2, gfx::AttributeDataType::Float2, 1, "a_radius"}, - {3, gfx::AttributeDataType::Float2, 1, "a_blur"}, - {4, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - {5, gfx::AttributeDataType::Float4, 1, "a_stroke_color"}, - {6, gfx::AttributeDataType::Float2, 1, "a_stroke_width"}, - {7, gfx::AttributeDataType::Float2, 1, "a_stroke_opacity"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(8, true, false, CircleDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(9, true, true, CirclePaintParamsUBO), - MLN_MTL_UNIFORM_BLOCK(10, true, true, CircleEvaluatedPropsUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, false, CircleInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(12, true, true, CirclePermutationUBO), - MLN_MTL_UNIFORM_BLOCK(13, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( diff --git a/include/mbgl/shaders/mtl/clipping_mask.hpp b/include/mbgl/shaders/mtl/clipping_mask.hpp index 5c62c52a7..e86707dfe 100644 --- a/include/mbgl/shaders/mtl/clipping_mask.hpp +++ b/include/mbgl/shaders/mtl/clipping_mask.hpp @@ -20,13 +20,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Float3, 1, "a_pos"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(1, true, false, ClipUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( #include diff --git a/include/mbgl/shaders/mtl/common.hpp b/include/mbgl/shaders/mtl/common.hpp index 04257e9d6..de61c8a0c 100644 --- a/include/mbgl/shaders/mtl/common.hpp +++ b/include/mbgl/shaders/mtl/common.hpp @@ -1,8 +1,5 @@ #pragma once -#define MLN_MTL_UNIFORM_BLOCK(idx, vert, frag, struc) \ - { idx, vert, frag, sizeof(struc), MLN_STRINGIZE(struc) } - namespace mbgl { namespace shaders { diff --git a/include/mbgl/shaders/mtl/fill.hpp b/include/mbgl/shaders/mtl/fill.hpp index 472e579b0..e16881ac9 100644 --- a/include/mbgl/shaders/mtl/fill.hpp +++ b/include/mbgl/shaders/mtl/fill.hpp @@ -14,24 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Float2, 1, "a_color"}, - {2, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - - // This shader doesn't use it, but we need this so that the layer can assign the same - // attributes to all the drawables. If/When `VertexAttributeArray::resolve` allows it, - // this can be removed. - {8, gfx::AttributeDataType::Float2, 1, "a_outline_color"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(3, true, false, FillDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(4, true, true, FillEvaluatedPropsUBO), - MLN_MTL_UNIFORM_BLOCK(5, true, false, FillInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(6, true, true, FillPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(7, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( @@ -104,22 +89,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Float2, 1, "a_outline_color"}, - {2, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - - // See `a_outline_color` in FillShader - {8, gfx::AttributeDataType::Float2, 1, "a_color"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(3, true, false, FillOutlineDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(4, true, true, FillOutlineEvaluatedPropsUBO), - MLN_MTL_UNIFORM_BLOCK(5, true, false, FillOutlineInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(6, true, true, FillOutlinePermutationUBO), - MLN_MTL_UNIFORM_BLOCK(7, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( @@ -203,24 +175,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"}, - {2, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"}, - {3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(4, true, true, FillPatternDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(5, true, false, FillPatternTilePropsUBO), - MLN_MTL_UNIFORM_BLOCK(6, true, true, FillPatternEvaluatedPropsUBO), - MLN_MTL_UNIFORM_BLOCK(7, true, false, FillPatternInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(8, true, true, FillPatternPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(9, true, false, ExpressionInputsUBO), - }; - - static constexpr TextureInfo textures[] = { - {0, "u_image"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( @@ -341,24 +298,9 @@ struct ShaderSource attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( diff --git a/include/mbgl/shaders/mtl/fill_extrusion.hpp b/include/mbgl/shaders/mtl/fill_extrusion.hpp index 22a751df0..da20b28cf 100644 --- a/include/mbgl/shaders/mtl/fill_extrusion.hpp +++ b/include/mbgl/shaders/mtl/fill_extrusion.hpp @@ -14,21 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Short4, 1, "a_normal_ed"}, - {2, gfx::AttributeDataType::Float4, 1, "a_color"}, - {3, gfx::AttributeDataType::Float, 1, "a_base"}, - {4, gfx::AttributeDataType::Float, 1, "a_height"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(5, true, false, FillExtrusionDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(6, true, false, FillExtrusionDrawablePropsUBO), - MLN_MTL_UNIFORM_BLOCK(7, true, false, FillExtrusionInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(8, true, false, FillExtrusionPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(9, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( struct alignas(16) FillExtrusionInterpolateUBO { diff --git a/include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp b/include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp index ec96161af..20904c7fa 100644 --- a/include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp +++ b/include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp @@ -14,9 +14,9 @@ struct ShaderSource attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( )"; diff --git a/include/mbgl/shaders/mtl/heatmap.hpp b/include/mbgl/shaders/mtl/heatmap.hpp index 9aef72564..8ea16d229 100644 --- a/include/mbgl/shaders/mtl/heatmap.hpp +++ b/include/mbgl/shaders/mtl/heatmap.hpp @@ -14,19 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Float2, 1, "a_weight"}, - {2, gfx::AttributeDataType::Float2, 1, "a_radius"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(3, true, false, HeatmapDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(4, true, true, HeatmapEvaluatedPropsUBO), - MLN_MTL_UNIFORM_BLOCK(5, true, false, HeatmapInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(6, true, true, HeatmapPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(7, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( diff --git a/include/mbgl/shaders/mtl/heatmap_texture.hpp b/include/mbgl/shaders/mtl/heatmap_texture.hpp index 3c4873f8f..d9a621489 100644 --- a/include/mbgl/shaders/mtl/heatmap_texture.hpp +++ b/include/mbgl/shaders/mtl/heatmap_texture.hpp @@ -14,16 +14,10 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(1, true, true, HeatmapTextureDrawableUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_image"}, - {1, "u_color_ramp"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; + static constexpr auto source = R"( struct VertexStage { diff --git a/include/mbgl/shaders/mtl/hillshade.hpp b/include/mbgl/shaders/mtl/hillshade.hpp index 1fa97b3b8..4248ce134 100644 --- a/include/mbgl/shaders/mtl/hillshade.hpp +++ b/include/mbgl/shaders/mtl/hillshade.hpp @@ -14,17 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(2, true, true, HillshadeDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(3, false, true, HillshadeEvaluatedPropsUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_image"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( diff --git a/include/mbgl/shaders/mtl/hillshade_prepare.hpp b/include/mbgl/shaders/mtl/hillshade_prepare.hpp index be57aef91..532f9f579 100644 --- a/include/mbgl/shaders/mtl/hillshade_prepare.hpp +++ b/include/mbgl/shaders/mtl/hillshade_prepare.hpp @@ -14,16 +14,10 @@ struct ShaderSource static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(2, true, true, HillshadePrepareDrawableUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_image"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; + static constexpr auto source = R"( struct VertexStage { diff --git a/include/mbgl/shaders/mtl/line.hpp b/include/mbgl/shaders/mtl/line.hpp index 9fed89140..e5b44db07 100644 --- a/include/mbgl/shaders/mtl/line.hpp +++ b/include/mbgl/shaders/mtl/line.hpp @@ -14,24 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"}, - {1, gfx::AttributeDataType::UByte4, 1, "a_data"}, - {2, gfx::AttributeDataType::Float4, 1, "a_color"}, - {3, gfx::AttributeDataType::Float2, 1, "a_blur"}, - {4, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - {5, gfx::AttributeDataType::Float2, 1, "a_gapwidth"}, - {6, gfx::AttributeDataType::Float2, 1, "a_offset"}, - {7, gfx::AttributeDataType::Float2, 1, "a_width"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(8, true, true, LineUBO), - MLN_MTL_UNIFORM_BLOCK(9, true, false, LinePropertiesUBO), - MLN_MTL_UNIFORM_BLOCK(10, true, false, LineInterpolationUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, true, LinePermutationUBO), - MLN_MTL_UNIFORM_BLOCK(12, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = {}; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( @@ -143,28 +128,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"}, - {1, gfx::AttributeDataType::UByte4, 1, "a_data"}, - {2, gfx::AttributeDataType::Float2, 1, "a_blur"}, - {3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - {4, gfx::AttributeDataType::Float2, 1, "a_gapwidth"}, - {5, gfx::AttributeDataType::Float2, 1, "a_offset"}, - {6, gfx::AttributeDataType::Float2, 1, "a_width"}, - {7, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"}, - {8, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(9, true, true, LinePatternUBO), - MLN_MTL_UNIFORM_BLOCK(10, true, false, LinePatternPropertiesUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, false, LinePatternInterpolationUBO), - MLN_MTL_UNIFORM_BLOCK(12, true, false, LinePatternTilePropertiesUBO), - MLN_MTL_UNIFORM_BLOCK(13, true, true, LinePermutationUBO), - MLN_MTL_UNIFORM_BLOCK(14, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_image"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( diff --git a/include/mbgl/shaders/mtl/line_gradient.hpp b/include/mbgl/shaders/mtl/line_gradient.hpp index 6d2b90416..ca718159c 100644 --- a/include/mbgl/shaders/mtl/line_gradient.hpp +++ b/include/mbgl/shaders/mtl/line_gradient.hpp @@ -14,25 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"}, - {1, gfx::AttributeDataType::UByte4, 1, "a_data"}, - {2, gfx::AttributeDataType::Float2, 1, "a_blur"}, - {3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, - {4, gfx::AttributeDataType::Float2, 1, "a_gapwidth"}, - {5, gfx::AttributeDataType::Float2, 1, "a_offset"}, - {6, gfx::AttributeDataType::Float2, 1, "a_width"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(7, true, true, LineGradientUBO), - MLN_MTL_UNIFORM_BLOCK(8, true, false, LineGradientPropertiesUBO), - MLN_MTL_UNIFORM_BLOCK(9, true, false, LineGradientInterpolationUBO), - MLN_MTL_UNIFORM_BLOCK(10, true, true, LinePermutationUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_image"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( struct VertexStage { diff --git a/include/mbgl/shaders/mtl/raster.hpp b/include/mbgl/shaders/mtl/raster.hpp index ca9f6b3a1..4b9022991 100644 --- a/include/mbgl/shaders/mtl/raster.hpp +++ b/include/mbgl/shaders/mtl/raster.hpp @@ -14,17 +14,10 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - {0, gfx::AttributeDataType::Short2, 1, "a_pos"}, - {1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(2, true, true, RasterDrawableUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_image0"}, - {1, "u_image1"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; + static constexpr auto source = R"( struct VertexStage { diff --git a/include/mbgl/shaders/mtl/shader_group.hpp b/include/mbgl/shaders/mtl/shader_group.hpp index 05a402a85..40aa8a977 100644 --- a/include/mbgl/shaders/mtl/shader_group.hpp +++ b/include/mbgl/shaders/mtl/shader_group.hpp @@ -22,32 +22,20 @@ public: ~ShaderGroup() noexcept override = default; gfx::ShaderPtr getOrCreateShader(gfx::Context& gfxContext, - const std::vector& propertiesAsUniforms, + const std::unordered_set& propertiesAsUniforms, std::string_view /*firstAttribName*/) override { constexpr auto& name = shaders::ShaderSource::name; constexpr auto& source = shaders::ShaderSource::source; constexpr auto& vertMain = shaders::ShaderSource::vertexMainFunction; constexpr auto& fragMain = shaders::ShaderSource::fragmentMainFunction; - uint32_t key = 0; - assert(propertiesAsUniforms.size() < 32); - std::unordered_map additionalDefines(propertiesAsUniforms.size()); - for (unsigned int i = 0; i < propertiesAsUniforms.size(); i++) { - if (!propertiesAsUniforms[i].empty()) { - key |= 1U << i; - auto name = std::string("HAS_UNIFORM_u_") + propertiesAsUniforms[i]; - additionalDefines.insert(std::make_pair(std::move(name), "1")); - } - } - - const std::string shaderName = std::string(name); // + "#" + std::to_string(key); + const std::string shaderName = std::string(name); const auto shaderSource = std::string(shaders::prelude) + source; auto shader = get(shaderName); if (!shader) { auto& context = static_cast(gfxContext); - shader = context.createProgram( - shaderName, shaderSource, vertMain, fragMain, programParameters, additionalDefines); + shader = context.createProgram(shaderName, shaderSource, vertMain, fragMain, programParameters, {}); assert(shader); if (!shader || !registerShader(shader, shaderName)) { assert(false); diff --git a/include/mbgl/shaders/mtl/shader_program.hpp b/include/mbgl/shaders/mtl/shader_program.hpp index 11ea96bc4..772f1dc2d 100644 --- a/include/mbgl/shaders/mtl/shader_program.hpp +++ b/include/mbgl/shaders/mtl/shader_program.hpp @@ -15,21 +15,27 @@ namespace mbgl { namespace shaders { struct AttributeInfo { + AttributeInfo(std::size_t index, gfx::AttributeDataType dataType, std::size_t count, std::string_view name); std::size_t index; gfx::AttributeDataType dataType; std::size_t count; std::string_view name; + StringIdentity nameID; }; struct UniformBlockInfo { + UniformBlockInfo(std::size_t index, bool vertex, bool fragment, std::size_t size, std::string_view name); std::size_t index; bool vertex; bool fragment; std::size_t size; std::string_view name; + StringIdentity nameID; }; struct TextureInfo { + TextureInfo(std::size_t index, std::string_view name); std::size_t index; std::string_view name; + StringIdentity nameID; }; } // namespace shaders namespace mtl { diff --git a/include/mbgl/shaders/mtl/symbol_icon.hpp b/include/mbgl/shaders/mtl/symbol_icon.hpp index 5f307c164..0cd4ada77 100644 --- a/include/mbgl/shaders/mtl/symbol_icon.hpp +++ b/include/mbgl/shaders/mtl/symbol_icon.hpp @@ -14,28 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - // always attributes - {0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"}, - {1, gfx::AttributeDataType::UShort4, 1, "a_data"}, - {2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"}, - {3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"}, - {4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"}, - - // sometimes uniforms - {5, gfx::AttributeDataType::Float, 1, "a_opacity"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(8, true, true, SymbolDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(9, true, true, SymbolDrawablePaintUBO), - MLN_MTL_UNIFORM_BLOCK(10, true, false, SymbolDrawableTilePropsUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, false, SymbolDrawableInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(12, true, true, SymbolPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(13, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_texture"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( struct VertexStage { diff --git a/include/mbgl/shaders/mtl/symbol_sdf.hpp b/include/mbgl/shaders/mtl/symbol_sdf.hpp index c1e8db6ee..c9858636b 100644 --- a/include/mbgl/shaders/mtl/symbol_sdf.hpp +++ b/include/mbgl/shaders/mtl/symbol_sdf.hpp @@ -14,32 +14,9 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - // always attributes - {0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"}, - {1, gfx::AttributeDataType::UShort4, 1, "a_data"}, - {2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"}, - {3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"}, - {4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"}, - - // sometimes uniforms - {5, gfx::AttributeDataType::Float4, 1, "a_fill_color"}, - {6, gfx::AttributeDataType::Float4, 1, "a_halo_color"}, - {7, gfx::AttributeDataType::Float, 1, "a_opacity"}, - {8, gfx::AttributeDataType::Float, 1, "a_halo_width"}, - {9, gfx::AttributeDataType::Float, 1, "a_halo_blur"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(10, true, true, SymbolDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, false, SymbolDrawablePaintUBO), - MLN_MTL_UNIFORM_BLOCK(12, true, true, SymbolDrawableTilePropsUBO), - MLN_MTL_UNIFORM_BLOCK(13, true, false, SymbolDrawableInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(14, true, true, SymbolPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(15, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_texture"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( struct VertexStage { diff --git a/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp b/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp index b9d7bdfb7..afd4dd4b8 100644 --- a/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp +++ b/include/mbgl/shaders/mtl/symbol_text_and_icon.hpp @@ -14,32 +14,9 @@ struct ShaderSource static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static constexpr AttributeInfo attributes[] = { - // always attributes - {0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"}, - {1, gfx::AttributeDataType::UShort4, 1, "a_data"}, - {2, gfx::AttributeDataType::Float3, 1, "a_projected_pos"}, - {3, gfx::AttributeDataType::Float, 1, "a_fade_opacity"}, - - // sometimes uniforms - {4, gfx::AttributeDataType::Float4, 1, "a_fill_color"}, - {5, gfx::AttributeDataType::Float4, 1, "a_halo_color"}, - {6, gfx::AttributeDataType::Float, 1, "a_opacity"}, - {7, gfx::AttributeDataType::Float, 1, "a_halo_width"}, - {8, gfx::AttributeDataType::Float, 1, "a_halo_blur"}, - }; - static constexpr UniformBlockInfo uniforms[] = { - MLN_MTL_UNIFORM_BLOCK(9, true, true, SymbolDrawableUBO), - MLN_MTL_UNIFORM_BLOCK(10, true, false, SymbolDrawablePaintUBO), - MLN_MTL_UNIFORM_BLOCK(11, true, true, SymbolDrawableTilePropsUBO), - MLN_MTL_UNIFORM_BLOCK(12, true, false, SymbolDrawableInterpolateUBO), - MLN_MTL_UNIFORM_BLOCK(13, true, true, SymbolPermutationUBO), - MLN_MTL_UNIFORM_BLOCK(14, true, false, ExpressionInputsUBO), - }; - static constexpr TextureInfo textures[] = { - {0, "u_texture"}, - {1, "u_texture_icon"}, - }; + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; static constexpr auto source = R"( #define SDF 1.0 diff --git a/include/mbgl/util/string_indexer.hpp b/include/mbgl/util/string_indexer.hpp index 8cd5afbd3..cf4f5b6c7 100644 --- a/include/mbgl/util/string_indexer.hpp +++ b/include/mbgl/util/string_indexer.hpp @@ -11,7 +11,7 @@ namespace mbgl { -using StringIdentity = size_t; +using StringIdentity = std::size_t; class StringIndexer { public: diff --git a/src/mbgl/gfx/vertex_attribute.cpp b/src/mbgl/gfx/vertex_attribute.cpp index a1862fef9..b1e6c3c5d 100644 --- a/src/mbgl/gfx/vertex_attribute.cpp +++ b/src/mbgl/gfx/vertex_attribute.cpp @@ -17,7 +17,8 @@ std::size_t VertexAttribute::getCount() const { return sharedRawData ? sharedRawData->getRawCount() : items.size(); } -std::unique_ptr VertexAttributeArray::nullref = nullptr; +const std::unique_ptr VertexAttributeArray::nullref; +const std::string VertexAttributeArray::attributePrefix = "a_"; VertexAttributeArray::VertexAttributeArray(VertexAttributeArray&& other) : attrs(std::move(other.attrs)) {} diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 82cef14a2..1eecdd458 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -489,12 +489,11 @@ gfx::UniformBufferPtr Context::createUniformBuffer(const void* data, std::size_t } gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders, const std::string& name) { - std::vector emptyProperties(0); auto shaderGroup = shaders.getShaderGroup(name); if (!shaderGroup) { return nullptr; } - return std::static_pointer_cast(shaderGroup->getOrCreateShader(*this, emptyProperties)); + return std::static_pointer_cast(shaderGroup->getOrCreateShader(*this, {})); } TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) { diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index f9adc544e..314243ff0 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -122,9 +122,11 @@ void DrawableGL::bindUniformBuffers() const { const auto& uniformBuffer = getUniformBuffers().get(element.first); if (!uniformBuffer) { using namespace std::string_literals; + const auto tileID = getTileID() ? util::toString(*getTileID()) : ""; Log::Error(Event::General, - "DrawableGL::bindUniformBuffers: UBO "s + std::string(StringIndexer::get(element.first)) + - " not found. skipping."); + "bindUniformBuffers: UBO "s + std::string(StringIndexer::get(element.first)) + + " not found for " + util::toString(getID()) + " / " + getName() + " / " + tileID + + ". skipping."); assert(false); continue; } diff --git a/src/mbgl/gl/drawable_gl_builder.cpp b/src/mbgl/gl/drawable_gl_builder.cpp index 6b1a55134..caa3afdb9 100644 --- a/src/mbgl/gl/drawable_gl_builder.cpp +++ b/src/mbgl/gl/drawable_gl_builder.cpp @@ -43,6 +43,7 @@ void DrawableGLBuilder::init() { impl->buildIndexes.clear(); impl->segments.clear(); impl->vertices.clear(); + textures.clear(); } } // namespace gl diff --git a/src/mbgl/gl/layer_group_gl.cpp b/src/mbgl/gl/layer_group_gl.cpp index d8df4c621..0ce9a50e6 100644 --- a/src/mbgl/gl/layer_group_gl.cpp +++ b/src/mbgl/gl/layer_group_gl.cpp @@ -103,7 +103,8 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) #if !defined(NDEBUG) std::string label_tile; if (const auto& tileID = drawable.getTileID()) { - label_tile = drawable.getName() + "/" + util::toString(*tileID); + label_tile = util::toString(drawable.getID().id()) + "/" + drawable.getName() + "/" + + util::toString(*tileID); } const auto labelPtr = (label_tile.empty() ? drawable.getName() : label_tile).c_str(); const auto debugGroupTile = parameters.encoder->createDebugGroup(labelPtr); diff --git a/src/mbgl/mtl/context.cpp b/src/mbgl/mtl/context.cpp index b92adf543..1100e34d3 100644 --- a/src/mbgl/mtl/context.cpp +++ b/src/mbgl/mtl/context.cpp @@ -151,12 +151,9 @@ gfx::UniformBufferPtr Context::createUniformBuffer(const void* data, std::size_t } gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders, const std::string& name) { - std::vector emptyProperties(0); - auto shaderGroup = shaders.getShaderGroup(name); - if (!shaderGroup) { - return nullptr; - } - return std::static_pointer_cast(shaderGroup->getOrCreateShader(*this, emptyProperties)); + const auto shaderGroup = shaders.getShaderGroup(name); + auto shader = shaderGroup ? shaderGroup->getOrCreateShader(*this, {}) : gfx::ShaderProgramBasePtr{}; + return std::static_pointer_cast(std::move(shader)); } TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) { diff --git a/src/mbgl/mtl/drawable.cpp b/src/mbgl/mtl/drawable.cpp index 2caaaf3b6..57d9c1fc9 100644 --- a/src/mbgl/mtl/drawable.cpp +++ b/src/mbgl/mtl/drawable.cpp @@ -377,9 +377,11 @@ void Drawable::bindUniformBuffers(const RenderPass& renderPass) const { const auto& uniformBuffer = getUniformBuffers().get(element.first); if (!uniformBuffer) { using namespace std::string_literals; + const auto tileID = getTileID() ? util::toString(*getTileID()) : ""; + const auto tileLabel = util::toString(getID()) + "/" + getName() + "/" + tileID; Log::Error(Event::General, - "Drawable::bindUniformBuffers: UBO "s + StringIndexer::get(element.first) + - " not found. skipping."); + "bindUniformBuffers: UBO "s + StringIndexer::get(element.first) + " not found on " + + tileLabel + ". skipping."); assert(false); continue; } diff --git a/src/mbgl/mtl/drawable_builder.cpp b/src/mbgl/mtl/drawable_builder.cpp index ec436fbc7..fe2454472 100644 --- a/src/mbgl/mtl/drawable_builder.cpp +++ b/src/mbgl/mtl/drawable_builder.cpp @@ -43,6 +43,7 @@ void DrawableBuilder::init() { impl->buildIndexes.clear(); impl->segments.clear(); impl->vertices.clear(); + textures.clear(); } } // namespace mtl diff --git a/src/mbgl/renderer/layer_group.cpp b/src/mbgl/renderer/layer_group.cpp index cc9ffdb97..48c423d6a 100644 --- a/src/mbgl/renderer/layer_group.cpp +++ b/src/mbgl/renderer/layer_group.cpp @@ -2,8 +2,10 @@ #include #include +#include #include #include +#include #include @@ -16,6 +18,17 @@ void LayerGroupBase::addDrawable(gfx::UniqueDrawable& drawable) { } } +void LayerGroupBase::runTweakers(const RenderTree& renderTree, PaintParameters& parameters) { + for (auto it = layerTweakers.begin(); it != layerTweakers.end();) { + if (auto tweaker = it->lock()) { + tweaker->execute(*this, renderTree, parameters); + ++it; + } else { + it = layerTweakers.erase(it); + } + } +} + struct LayerGroup::Impl { using DrawableCollection = std::set; DrawableCollection drawables; diff --git a/src/mbgl/renderer/layer_tweaker.cpp b/src/mbgl/renderer/layer_tweaker.cpp index b982f2978..01e0a2761 100644 --- a/src/mbgl/renderer/layer_tweaker.cpp +++ b/src/mbgl/renderer/layer_tweaker.cpp @@ -19,6 +19,12 @@ LayerTweaker::LayerTweaker(std::string id_, Immutable pr : id(std::move(id_)), evaluatedProperties(std::move(properties)) {} +bool LayerTweaker::checkTweakDrawable(const gfx::Drawable& drawable) const { + // Apply to a drawable if it references us, or if doesn't reference anything. + const auto& tweaker = drawable.getLayerTweaker(); + return !tweaker || tweaker.get() == this; +} + mat4 LayerTweaker::getTileMatrix(const UnwrappedTileID& tileID, const RenderTree& renderTree, const TransformState& state, @@ -60,27 +66,25 @@ shaders::ExpressionInputsUBO LayerTweaker::buildExpressionUBO(double zoom, uint6 0}; } -void LayerTweaker::setPropertiesAsUniforms(std::vector props) { - if (props != propertiesAsUniforms) { - propertiesAsUniforms = std::move(props); - propertiesChanged = true; - } -} -bool LayerTweaker::hasPropertyAsUniform(const std::string_view attrName) const { - // `attrName` is expected to have the "a_" prefix, while the values in `propertiesAsUniforms` - // do not. Search for the former within the latter without allocating temporary strings. - return propertiesAsUniforms.end() != - std::find_if(propertiesAsUniforms.begin(), propertiesAsUniforms.end(), [&](const auto& name) { - return name.size() + 2 == attrName.size() && 0 == std::strcmp(name.data(), attrName.data() + 2); - }); +bool LayerTweaker::hasPropertyAsUniform(const StringIdentity attrNameID) const { + return propertiesAsUniforms.find(attrNameID) != propertiesAsUniforms.end(); } using namespace shaders; -AttributeSource LayerTweaker::getAttributeSource(const std::string_view& attribName) const { - return hasPropertyAsUniform(attribName) ? AttributeSource::Constant : AttributeSource::PerVertex; +AttributeSource LayerTweaker::getAttributeSource(const StringIdentity attribNameID) const { + return hasPropertyAsUniform(attribNameID) ? AttributeSource::Constant : AttributeSource::PerVertex; } #endif // MLN_RENDER_BACKEND_METAL +void LayerTweaker::setPropertiesAsUniforms([[maybe_unused]] const std::unordered_set& props) { +#if MLN_RENDER_BACKEND_METAL + if (props != propertiesAsUniforms) { + propertiesAsUniforms = props; + propertiesChanged = true; + } +#endif +} + void LayerTweaker::enableOverdrawInspector(bool value) { if (overdrawInspector != value) { overdrawInspector = value; diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.cpp b/src/mbgl/renderer/layers/background_layer_tweaker.cpp index ceb875b3f..d4ee0b033 100644 --- a/src/mbgl/renderer/layers/background_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/background_layer_tweaker.cpp @@ -54,6 +54,9 @@ void BackgroundLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTre std::optional samplerLocation{}; layerGroup.visitDrawables([&](gfx::Drawable& drawable) { assert(drawable.getTileID()); + if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { + return; + } // We assume that drawables don't change between pattern and non-pattern. const auto& shader = drawable.getShader(); diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp index 9d1500127..090ad72cb 100644 --- a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp @@ -60,20 +60,15 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const auto zoom = parameters.state.getZoom(); #if MLN_RENDER_BACKEND_METAL - using ShaderClass = shaders::ShaderSource; if (propertiesChanged) { - const auto source = [this](const std::string_view& attrName) { - return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex; - }; - const CirclePermutationUBO permutationUBO = { - /* .color = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}}, - /* .radius = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}}, - /* .blur = */ {/*.source=*/source(ShaderClass::attributes[3].name), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/source(ShaderClass::attributes[4].name), /*.expression=*/{}}, - /* .stroke_color = */ {/*.source=*/source(ShaderClass::attributes[5].name), /*.expression=*/{}}, - /* .stroke_width = */ {/*.source=*/source(ShaderClass::attributes[6].name), /*.expression=*/{}}, - /* .stroke_opacity = */ {/*.source=*/source(ShaderClass::attributes[7].name), /*.expression=*/{}}, + /* .color = */ {/*.source=*/getAttributeSource(1), /*.expression=*/{}}, + /* .radius = */ {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, + /* .blur = */ {/*.source=*/getAttributeSource(3), /*.expression=*/{}}, + /* .opacity = */ {/*.source=*/getAttributeSource(4), /*.expression=*/{}}, + /* .stroke_color = */ {/*.source=*/getAttributeSource(5), /*.expression=*/{}}, + /* .stroke_width = */ {/*.source=*/getAttributeSource(6), /*.expression=*/{}}, + /* .stroke_opacity = */ {/*.source=*/getAttributeSource(7), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, /* .pad = */ 0, 0, @@ -114,16 +109,16 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, } layerGroup.visitDrawables([&](gfx::Drawable& drawable) { - auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.addOrReplace(idCirclePaintParamsUBOName, paintParamsUniformBuffer); - uniforms.addOrReplace(idCircleEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); - - if (!drawable.getTileID()) { - assert(!"Circles only render with tiles"); + assert(drawable.getTileID() || !"Circles only render with tiles"); + if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; } const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.addOrReplace(idCirclePaintParamsUBOName, paintParamsUniformBuffer); + uniforms.addOrReplace(idCircleEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); + const auto& translation = evaluated.get(); const auto anchor = evaluated.get(); constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix diff --git a/src/mbgl/renderer/layers/collision_layer_tweaker.cpp b/src/mbgl/renderer/layers/collision_layer_tweaker.cpp index 5e8d0bd9a..508f16888 100644 --- a/src/mbgl/renderer/layers/collision_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/collision_layer_tweaker.cpp @@ -50,7 +50,7 @@ void CollisionLayerTweaker::execute(LayerGroupBase& layerGroup, #endif layerGroup.visitDrawables([&](gfx::Drawable& drawable) { - if (!drawable.getTileID() || !drawable.getData()) { + if (!drawable.getTileID() || !drawable.getData() || !checkTweakDrawable(drawable)) { return; } diff --git a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp index deb0c8ab9..8ac8bf6f6 100644 --- a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp @@ -16,6 +16,10 @@ #include #include +#if MLN_RENDER_BACKEND_METAL +#include +#endif + namespace mbgl { using namespace shaders; @@ -79,9 +83,9 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, const auto zoom = parameters.state.getZoom(); if (propertiesChanged) { const FillExtrusionPermutationUBO permutationUBO = { - /* .color = */ {/*.source=*/getAttributeSource("a_color"), /*.expression=*/{}}, - /* .base = */ {/*.source=*/getAttributeSource("a_base"), /*.expression=*/{}}, - /* .height = */ {/*.source=*/getAttributeSource("a_height"), /*.expression=*/{}}, + /* .color = */ {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, + /* .base = */ {/*.source=*/getAttributeSource(3), /*.expression=*/{}}, + /* .height = */ {/*.source=*/getAttributeSource(4), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, /* .pad = */ 0, 0, @@ -102,15 +106,15 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, #endif layerGroup.visitDrawables([&](gfx::Drawable& drawable) { - auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.addOrReplace(idFillExtrusionDrawablePropsUBOName, propsBuffer); - - if (!drawable.getTileID()) { + if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; } const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.addOrReplace(idFillExtrusionDrawablePropsUBOName, propsBuffer); + const auto& translation = evaluated.get(); const auto anchor = evaluated.get(); constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp index ebd33424f..14ded51d4 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp @@ -77,12 +77,6 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); #endif -#if MLN_RENDER_BACKEND_METAL - const auto source = [this](const std::string_view& attrName) { - return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex; - }; -#endif - bool fillUniformBufferUpdated = false; bool fillOutlineUniformBufferUpdated = false; bool fillPatternUniformBufferUpdated = false; @@ -92,11 +86,10 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, if (fillUniformBufferUpdated) return; #if MLN_RENDER_BACKEND_METAL - using ShaderClass = ShaderSource; if (propertiesChanged || !fillPermutationUniformBuffer) { const FillPermutationUBO permutationUBO = { - /* .color = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}}, + /* .color = */ {/*.source=*/getAttributeSource(1), /*.expression=*/{}}, + /* .opacity = */ {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, 0, 0, @@ -131,11 +124,11 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, if (fillOutlineUniformBufferUpdated) return; #if MLN_RENDER_BACKEND_METAL - using ShaderClass = ShaderSource; if (propertiesChanged || !fillOutlinePermutationUniformBuffer) { const FillOutlinePermutationUBO permutationUBO = { - /* .outline_color = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}}, + /* .outline_color = */ {/*.source=*/getAttributeSource(1), + /*.expression=*/{}}, + /* .opacity = */ {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, 0, 0, @@ -172,12 +165,14 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, if (fillPatternUniformBufferUpdated) return; #if MLN_RENDER_BACKEND_METAL - using ShaderClass = ShaderSource; if (propertiesChanged || !fillPatternPermutationUniformBuffer) { const FillPatternPermutationUBO permutationUBO = { - /* .pattern_from = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}}, - /* .pattern_to = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/source(ShaderClass::attributes[3].name), /*.expression=*/{}}, + /* .pattern_from = */ {/*.source=*/getAttributeSource(1), + /*.expression=*/{}}, + /* .pattern_to = */ + {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, + /* .opacity = */ + {/*.source=*/getAttributeSource(3), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, 0, 0, @@ -211,12 +206,14 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, if (fillOutlinePatternUniformBufferUpdated) return; #if MLN_RENDER_BACKEND_METAL - using ShaderClass = ShaderSource; - if (propertiesChanged || !fillOutlinePermutationUniformBuffer) { + if (propertiesChanged || !fillOutlinePatternPermutationUniformBuffer) { const FillOutlinePatternPermutationUBO permutationUBO = { - /* .pattern_from = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}}, - /* .pattern_to = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/source(ShaderClass::attributes[3].name), /*.expression=*/{}}, + /* .pattern_from = */ {/*.source=*/getAttributeSource(1), + /*.expression=*/{}}, + /* .pattern_to = */ + {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, + /* .opacity = */ + {/*.source=*/getAttributeSource(3), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, 0, 0, @@ -255,6 +252,10 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, #endif layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { + return; + } + auto& uniforms = drawable.mutableUniformBuffers(); // auto& drawableType = drawable.getShader()->typeName(); @@ -287,9 +288,6 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, } } } - if (!drawable.getTileID()) { - return; - } if (uniforms.get(idFillInterpolateUBOName)) { UpdateFillUniformBuffers(); diff --git a/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp b/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp index 4fa4f5699..6cfc4a57a 100644 --- a/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp @@ -43,15 +43,10 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, const auto zoom = parameters.state.getZoom(); #if MLN_RENDER_BACKEND_METAL - using ShaderClass = shaders::ShaderSource; if (propertiesChanged) { - const auto source = [this](const std::string_view& attrName) { - return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex; - }; - const HeatmapPermutationUBO permutationUBO = { - /* .weight = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}}, - /* .radius = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}}, + /* .weight = */ {/*.source=*/getAttributeSource(1), /*.expression=*/{}}, + /* .radius = */ {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, /* .pad1/2/3 = */ 0, 0, @@ -85,13 +80,15 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, } layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { + return; + } + + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + auto& uniforms = drawable.mutableUniformBuffers(); uniforms.addOrReplace(idHeatmapEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); - if (!drawable.getTileID()) { - return; - } - const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); constexpr bool nearClipped = false; constexpr bool inViewportPixelUnits = false; const auto matrix = getTileMatrix(tileID, diff --git a/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp b/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp index 2331c6846..d7542bbbd 100644 --- a/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp @@ -33,6 +33,10 @@ void HeatmapTextureLayerTweaker::execute(LayerGroupBase& layerGroup, #endif layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + if (!checkTweakDrawable(drawable)) { + return; + } + const auto& size = parameters.staticData.backendSize; mat4 viewportMat; matrix::ortho(viewportMat, 0, size.width, size.height, 0, -1, 1); diff --git a/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp b/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp index 088785304..7e030ba36 100644 --- a/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp @@ -55,12 +55,14 @@ void HillshadeLayerTweaker::execute(LayerGroupBase& layerGroup, } layerGroup.visitDrawables([&](gfx::Drawable& drawable) { - drawable.mutableUniformBuffers().addOrReplace(idHillshadeEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); - - if (!drawable.getTileID()) { + if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; } + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + + drawable.mutableUniformBuffers().addOrReplace(idHillshadeEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); + const auto matrix = getTileMatrix( tileID, renderTree, parameters.state, {0.f, 0.f}, TranslateAnchorType::Viewport, false, false, true); HillshadeDrawableUBO drawableUBO = {/* .matrix = */ util::cast(matrix), diff --git a/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp b/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp index dfd33efe5..d8971b00a 100644 --- a/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp @@ -42,7 +42,7 @@ void HillshadePrepareLayerTweaker::execute(LayerGroupBase& layerGroup, #endif layerGroup.visitDrawables([&](gfx::Drawable& drawable) { - if (!drawable.getTileID() || !drawable.getData()) { + if (!drawable.getTileID() || !drawable.getData() || !checkTweakDrawable(drawable)) { return; } const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); @@ -52,7 +52,7 @@ void HillshadePrepareLayerTweaker::execute(LayerGroupBase& layerGroup, matrix::ortho(matrix, 0, util::EXTENT, -util::EXTENT, 0, -1, 1); matrix::translate(matrix, matrix, 0, -util::EXTENT, 0); - HillshadePrepareDrawableUBO drawableUBO = { + const HillshadePrepareDrawableUBO drawableUBO = { /* .matrix = */ util::cast(matrix), /* .unpack = */ getUnpackVector(drawableData.encoding), /* .dimension = */ {static_cast(drawableData.stride), static_cast(drawableData.stride)}, diff --git a/src/mbgl/renderer/layers/line_layer_tweaker.cpp b/src/mbgl/renderer/layers/line_layer_tweaker.cpp index a0275e54b..cef597f7c 100644 --- a/src/mbgl/renderer/layers/line_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/line_layer_tweaker.cpp @@ -112,19 +112,14 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, }; #if MLN_RENDER_BACKEND_METAL - using LineShaderClass = shaders::ShaderSource; if (propertiesChanged) { - const auto source = [this](const std::string_view& attrName) { - return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex; - }; - const LinePermutationUBO permutationUBO = { - /* .color = */ {/*.source=*/source(LineShaderClass::attributes[2].name), /*.expression=*/{}}, - /* .blur = */ {/*.source=*/source(LineShaderClass::attributes[3].name), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/source(LineShaderClass::attributes[4].name), /*.expression=*/{}}, - /* .gapwidth = */ {/*.source=*/source(LineShaderClass::attributes[5].name), /*.expression=*/{}}, - /* .offset = */ {/*.source=*/source(LineShaderClass::attributes[6].name), /*.expression=*/{}}, - /* .width = */ {/*.source=*/source(LineShaderClass::attributes[7].name), /*.expression=*/{}}, + /* .color = */ {/*.source=*/getAttributeSource(2), /*.expression=*/{}}, + /* .blur = */ {/*.source=*/getAttributeSource(3), /*.expression=*/{}}, + /* .opacity = */ {/*.source=*/getAttributeSource(4), /*.expression=*/{}}, + /* .gapwidth = */ {/*.source=*/getAttributeSource(5), /*.expression=*/{}}, + /* .offset = */ {/*.source=*/getAttributeSource(6), /*.expression=*/{}}, + /* .width = */ {/*.source=*/getAttributeSource(7), /*.expression=*/{}}, /* .floorwidth = */ {/*.source=*/AttributeSource::Constant, /*.expression=*/{}}, /* .pattern_from = */ {/*.source=*/AttributeSource::Constant, /*.expression=*/{}}, /* .pattern_to = */ {/*.source=*/AttributeSource::Constant, /*.expression=*/{}}, @@ -149,7 +144,7 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, layerGroup.visitDrawables([&](gfx::Drawable& drawable) { const auto shader = drawable.getShader(); - if (!drawable.getTileID() || !shader) { + if (!drawable.getTileID() || !shader || !checkTweakDrawable(drawable)) { return; } diff --git a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp index 945309f8c..2854f82dd 100644 --- a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp @@ -25,6 +25,10 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup, const auto& evaluated = static_cast(*evaluatedProperties).evaluated; layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + if (!checkTweakDrawable(drawable)) { + return; + } + const auto spinWeights = [](float spin) -> std::array { spin = util::deg2radf(spin); const float s = std::sin(spin); diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index b13b44914..6f50db3d4 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -67,7 +66,8 @@ void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters& paramet #if MLN_DRAWABLE_RENDERER if (layerGroup) { - layerGroup->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); } #endif } @@ -250,12 +250,18 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders, if (!layerGroup) { if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { - layerGroup_->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); setLayerGroup(std::move(layerGroup_), changes); + } else { + return; } } auto* tileLayerGroup = static_cast(layerGroup.get()); + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + if (!hasPattern && !plainShader) { plainShader = context.getGenericShader(shaders, std::string(BackgroundPlainShaderName)); } @@ -312,6 +318,7 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); tileLayerGroup->addDrawable(drawPasses, tileID, std::move(drawable)); ++stats.drawablesAdded; } diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index b3c704d95..f2e83ea1e 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -93,7 +93,10 @@ void RenderCircleLayer::evaluate(const PropertyEvaluationParameters& parameters) evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - updateLayerTweaker(); + if (layerGroup) { + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); + } #endif // MLN_DRAWABLE_RENDERER } @@ -276,19 +279,6 @@ static const StringIdentity idVertexAttribName = StringIndexer::get("a_pos"); using namespace shaders; -#if MLN_DRAWABLE_RENDERER -void RenderCircleLayer::updateLayerTweaker() { - if (layerGroup) { - tweaker = std::make_shared(getID(), evaluatedProperties); -#if MLN_RENDER_BACKEND_METAL - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); -#endif // MLN_RENDER_BACKEND_METAL - tweaker->enableOverdrawInspector(overdrawInspector); - layerGroup->setLayerTweaker(tweaker); - } -} -#endif // MLN_DRAWABLE_RENDERER - void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, @@ -305,12 +295,19 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, // Set up a layer group if (!layerGroup) { if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { - layerGroup_->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); setLayerGroup(std::move(layerGroup_), changes); + } else { + return; } } auto* tileLayerGroup = static_cast(layerGroup.get()); + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); + if (!circleShaderGroup) { circleShaderGroup = shaders.getShaderGroup(CircleShaderGroupName); } @@ -319,14 +316,6 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, return; } - const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); - if (overdrawInspector != overdraw) { - overdrawInspector = overdraw; - if (tweaker) { - tweaker->enableOverdrawInspector(overdrawInspector); - } - } - std::unique_ptr circleBuilder; constexpr auto renderPass = RenderPass::Translucent; @@ -338,6 +327,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, [&](gfx::Drawable& drawable) { return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); }); const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + std::unordered_set propertiesAsUniforms; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -375,6 +365,11 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, // If there are already drawables for this tile, update their UBOs and move on to the next tile. auto updateExisting = [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + // This drawable was produced on a previous style/bucket, and should not be updated. + return; + } + auto& uniforms = drawable.mutableUniformBuffers(); uniforms.createOrUpdate(idCircleInterpolateUBOName, &interpolateUBO, context); }; @@ -384,30 +379,28 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, const auto interpBuffer = context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO)); + propertiesAsUniforms.clear(); gfx::VertexAttributeArray circleVertexAttrs; - auto propertiesAsUniforms_ = circleVertexAttrs.readDataDrivenPaintProperties( - paintPropertyBinders, evaluated); + circleVertexAttrs.readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); if (!circleShaderGroup) { continue; } - const auto circleShader = circleShaderGroup->getOrCreateShader(context, propertiesAsUniforms_); + const auto circleShader = circleShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!circleShader) { continue; } -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL if (const auto& attr = circleVertexAttrs.add(idVertexAttribName)) { attr->setSharedRawData(bucket.sharedVertices, @@ -434,6 +427,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : circleBuilder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); auto& uniforms = drawable->mutableUniformBuffers(); uniforms.addOrReplace(idCircleInterpolateUBOName, interpBuffer); diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp index 43ed687c3..da8c50dbb 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.hpp +++ b/src/mbgl/renderer/layers/render_circle_layer.hpp @@ -49,10 +49,6 @@ private: void render(PaintParameters&) override; #endif // MLN_LEGACY_RENDERER -#if MLN_DRAWABLE_RENDERER - void updateLayerTweaker(); -#endif // MLN_DRAWABLE_RENDERER - private: // Paint properties style::CirclePaintProperties::Unevaluated unevaluated; @@ -64,13 +60,6 @@ private: #if MLN_DRAWABLE_RENDERER gfx::ShaderGroupPtr circleShaderGroup; - - CircleLayerTweakerPtr tweaker; -#if MLN_RENDER_BACKEND_METAL - std::vector propertiesAsUniforms; -#endif // MLN_RENDER_BACKEND_METAL - - bool overdrawInspector = false; #endif }; diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index d0364ac7b..f60ac813f 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #endif // MLN_DRAWABLE_RENDERER @@ -75,7 +76,8 @@ void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& para #if MLN_DRAWABLE_RENDERER if (layerGroup) { - layerGroup->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); } #endif // MLN_DRAWABLE_RENDERER } @@ -275,7 +277,7 @@ bool RenderFillExtrusionLayer::queryIntersectsFeature(const GeometryCoordinates& void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, - const std::shared_ptr&, + const std::shared_ptr& updateParameters, const RenderTree& /*renderTree*/, UniqueChangeRequestVec& changes) { if (!renderTiles || renderTiles->empty() || passes == RenderPass::None) { @@ -286,11 +288,19 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, // Set up a layer group if (!layerGroup) { if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { - layerGroup_->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); setLayerGroup(std::move(layerGroup_), changes); + } else { + return; } } + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); + if (!fillExtrusionGroup) { fillExtrusionGroup = shaders.getShaderGroup("FillExtrusionShader"); } @@ -331,6 +341,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, return; } + std::unordered_set propertiesAsUniforms; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -388,6 +399,11 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, if (tileLayerGroup->getDrawableCount(drawPass, tileID) > 0) { // Just update the drawables we already created tileLayerGroup->visitDrawables(drawPass, tileID, [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + // This drawable was produced on a previous style/bucket, and should not be updated. + return; + } + auto& uniforms = drawable.mutableUniformBuffers(); uniforms.createOrUpdate( FillExtrusionLayerTweaker::idFillExtrusionTilePropsUBOName, &tilePropsUBO, context); @@ -398,20 +414,25 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, } gfx::VertexAttributeArray vertexAttrs; - const auto uniformProps = vertexAttrs.readDataDrivenPaintProperties(binders, evaluated); + propertiesAsUniforms.clear(); + vertexAttrs.readDataDrivenPaintProperties(binders, evaluated, propertiesAsUniforms); if (!shaderGroup) { continue; } const auto shader = std::static_pointer_cast( - shaderGroup->getOrCreateShader(context, uniformProps)); + shaderGroup->getOrCreateShader(context, propertiesAsUniforms)); if (!shader) { continue; } + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); + } + // The non-pattern path in `render()` only uses two-pass rendering if there's translucency. // The pattern path always uses two passes. const auto doDepthPass = (!opaque || hasPattern); @@ -501,6 +522,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder.clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); auto& uniforms = drawable->mutableUniformBuffers(); uniforms.createOrUpdate( diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index fcba89c00..d2627b4b5 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -104,9 +104,9 @@ void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) { #if MLN_DRAWABLE_RENDERER if (layerGroup) { - layerGroup->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); } - updateLayerTweaker(); #endif } @@ -308,17 +308,6 @@ bool RenderFillLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeo #if MLN_DRAWABLE_RENDERER -void RenderFillLayer::updateLayerTweaker() { - if (layerGroup) { - tweaker = std::make_shared(getID(), evaluatedProperties); -#if MLN_RENDER_BACKEND_METAL - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); -#endif // MLN_RENDER_BACKEND_METAL - tweaker->enableOverdrawInspector(overdrawInspector); - layerGroup->setLayerTweaker(tweaker); - } -} - void RenderFillLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, @@ -332,24 +321,22 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, return; } - const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); - if (overdrawInspector != overdraw) { - overdrawInspector = overdraw; - if (tweaker) { - tweaker->enableOverdrawInspector(overdrawInspector); - } - } - // Set up a layer group if (!layerGroup) { if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { - layerGroup_->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); setLayerGroup(std::move(layerGroup_), changes); - updateLayerTweaker(); + } else { + return; } } auto* tileLayerGroup = static_cast(layerGroup.get()); + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); + if (!fillShaderGroup) { fillShaderGroup = shaders.getShaderGroup(std::string(FillShaderName)); } @@ -373,7 +360,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, std::unique_ptr outlinePatternBuilder; const auto layerPrefix = getID() + "/"; - const auto renderPass = RenderPass::Translucent; + constexpr auto renderPass = RenderPass::Translucent; const auto commonInit = [&](gfx::DrawableBuilder& builder) { builder.setCullFaceMode(gfx::CullFaceMode::disabled()); @@ -383,12 +370,10 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, stats.drawablesRemoved += tileLayerGroup->removeDrawablesIf([&](gfx::Drawable& 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 (tileID && !hasRenderTile(*tileID)) { - return true; - } - return false; + return tileID && !hasRenderTile(*tileID); }); + std::unordered_set propertiesAsUniforms; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -519,9 +504,13 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, // `Fill*Program` all use `style::FillPaintProperties` gfx::VertexAttributeArray vertexAttrs; - const auto propertiesAsUniforms_ = - vertexAttrs.readDataDrivenPaintProperties(binders, - evaluated); + propertiesAsUniforms.clear(); + vertexAttrs.readDataDrivenPaintProperties( + binders, evaluated, propertiesAsUniforms); + + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); + } const auto vertexCount = bucket.vertices.elements(); if (const auto& attr = vertexAttrs.add(idPosAttribName)) { @@ -534,6 +523,11 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, // If we already have drawables for this tile, update them. auto updateExisting = [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + // This drawable was produced on a previous style/bucket, and should not be updated. + return; + } + auto& uniforms = drawable.mutableUniformBuffers(); if (uniforms.get(FillLayerTweaker::idFillInterpolateUBOName)) { uniforms.createOrUpdate(FillLayerTweaker::idFillInterpolateUBOName, &getFillInterpolateUBO(), context); @@ -566,19 +560,12 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, continue; } const auto fillShader = std::static_pointer_cast( - fillShaderGroup->getOrCreateShader(context, propertiesAsUniforms_)); + fillShaderGroup->getOrCreateShader(context, propertiesAsUniforms)); const auto outlineShader = doOutline ? std::static_pointer_cast( - outlineShaderGroup->getOrCreateShader(context, propertiesAsUniforms_)) + outlineShaderGroup->getOrCreateShader(context, propertiesAsUniforms)) : nullptr; -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); - } -#endif // MLN_RENDER_BACKEND_METAL - if (!fillBuilder && fillShader) { if (auto builder = context.createDrawableBuilder(layerPrefix + "fill")) { commonInit(*builder); @@ -610,6 +597,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder.clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); + auto& uniforms = drawable->mutableUniformBuffers(); uniforms.createOrUpdate(interpolateUBONameId, &interpolateUBO, context); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); @@ -653,19 +642,12 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } const auto fillShader = std::static_pointer_cast( - patternShaderGroup->getOrCreateShader(context, propertiesAsUniforms_)); + patternShaderGroup->getOrCreateShader(context, propertiesAsUniforms)); const auto outlineShader = doOutline ? std::static_pointer_cast( outlinePatternShaderGroup->getOrCreateShader( - context, propertiesAsUniforms_)) + context, propertiesAsUniforms)) : nullptr; -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); - } -#endif // MLN_RENDER_BACKEND_METAL - if (!patternBuilder) { if (auto builder = context.createDrawableBuilder(layerPrefix + "fill-pattern")) { commonInit(*builder); @@ -708,6 +690,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder.clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); + auto& uniforms = drawable->mutableUniformBuffers(); uniforms.createOrUpdate(interpolateNameId, &interpolateUBO, context); uniforms.createOrUpdate(tileUBONameId, &tileUBO, context); diff --git a/src/mbgl/renderer/layers/render_fill_layer.hpp b/src/mbgl/renderer/layers/render_fill_layer.hpp index c077d926f..9ba69f8e3 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.hpp +++ b/src/mbgl/renderer/layers/render_fill_layer.hpp @@ -46,10 +46,6 @@ private: void render(PaintParameters&) override; #endif -#if MLN_DRAWABLE_RENDERER - void updateLayerTweaker(); -#endif // MLN_DRAWABLE_RENDERER - bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, float, @@ -73,13 +69,6 @@ private: gfx::ShaderGroupPtr outlineShaderGroup; gfx::ShaderGroupPtr patternShaderGroup; gfx::ShaderGroupPtr outlinePatternShaderGroup; - - FillLayerTweakerPtr tweaker; -#if MLN_RENDER_BACKEND_METAL - std::vector propertiesAsUniforms; -#endif // MLN_RENDER_BACKEND_METAL - bool overdrawInspector = false; - #endif }; diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index e980da01e..9e7bc96cf 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -70,8 +70,17 @@ void RenderHeatmapLayer::evaluate(const PropertyEvaluationParameters& parameters evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - updateLayerTweaker(); - updateLayerTextureTweaker(); + if (layerGroup) { + auto newTextureTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(textureTweaker, std::move(newTextureTweaker), {layerGroup}); + } + + if (renderTarget) { + if (auto tileLayerGroup = renderTarget->getLayerGroup(0)) { + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {std::move(tileLayerGroup)}); + } + } #endif } @@ -247,17 +256,24 @@ void RenderHeatmapLayer::markLayerRenderable(bool willRender, UniqueChangeReques activateRenderTarget(renderTarget, willRender, changes); } -void RenderHeatmapLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { - auto* tileLayerGroup = static_cast(renderTarget->getLayerGroup(0).get()); - stats.drawablesRemoved += tileLayerGroup->removeDrawables(renderPass, tileID).size(); +std::size_t RenderHeatmapLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { + if (auto* tileLayerGroup = static_cast(renderTarget->getLayerGroup(0).get())) { + const auto count = tileLayerGroup->removeDrawables(renderPass, tileID).size(); + stats.drawablesRemoved += count; + return count; + } + return 0; } -void RenderHeatmapLayer::removeAllDrawables() { - RenderLayer::removeAllDrawables(); +std::size_t RenderHeatmapLayer::removeAllDrawables() { + auto removed = RenderLayer::removeAllDrawables(); if (renderTarget) { - stats.drawablesRemoved += renderTarget->getLayerGroup(0)->getDrawableCount(); + const auto count = renderTarget->getLayerGroup(0)->getDrawableCount(); + removed += count; + stats.drawablesRemoved += count; renderTarget->getLayerGroup(0)->clearDrawables(); } + return removed; } namespace { @@ -273,27 +289,6 @@ static const StringIdentity idTexColorRampName = StringIndexer::get("u_color_ram using namespace shaders; -#if MLN_DRAWABLE_RENDERER -void RenderHeatmapLayer::updateLayerTweaker() { - if (renderTarget) { - tweaker = std::make_shared(getID(), evaluatedProperties); -#if MLN_RENDER_BACKEND_METAL - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); -#endif // MLN_RENDER_BACKEND_METAL - tweaker->enableOverdrawInspector(overdrawInspector); - renderTarget->getLayerGroup(0)->setLayerTweaker(tweaker); - } -} - -void RenderHeatmapLayer::updateLayerTextureTweaker() { - if (layerGroup) { - textureTweaker = std::make_shared(getID(), evaluatedProperties); - textureTweaker->enableOverdrawInspector(overdrawInspector); - layerGroup->setLayerTweaker(textureTweaker); - } -} -#endif // MLN_DRAWABLE_RENDERER - void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, @@ -324,7 +319,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, return; } renderTarget->addLayerGroup(tileLayerGroup, /*replace=*/true); - updateLayerTweaker(); + textureTweaker.reset(); } if (renderTarget->getTexture()->getSize() != size) { @@ -341,14 +336,11 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, return; } - const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); - if (overdrawInspector != overdraw) { - overdrawInspector = overdraw; - if (tweaker) { - tweaker->enableOverdrawInspector(overdrawInspector); - textureTweaker->enableOverdrawInspector(overdrawInspector); - } + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + tileLayerGroup->addLayerTweaker(layerTweaker); } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); std::unique_ptr heatmapBuilder; constexpr auto renderPass = RenderPass::Translucent; @@ -361,6 +353,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, [&](gfx::Drawable& drawable) { return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); }); const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + std::unordered_set propertiesAsUniforms; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -389,6 +382,10 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, /* .padding = */ {0}}; tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + // This drawable was produced on a previous style/bucket, and should not be updated. + return; + } drawable.mutableUniformBuffers().createOrUpdate(idHeatmapInterpolateUBOName, &interpolateUBO, context); }); @@ -397,25 +394,18 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, } gfx::VertexAttributeArray heatmapVertexAttrs; + propertiesAsUniforms.clear(); + heatmapVertexAttrs.readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); - const auto propertiesAsUniforms_ = - heatmapVertexAttrs.readDataDrivenPaintProperties(paintPropertyBinders, - evaluated); - - if (!heatmapShaderGroup) { - continue; - } - const auto heatmapShader = heatmapShaderGroup->getOrCreateShader(context, propertiesAsUniforms_); + const auto heatmapShader = heatmapShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!heatmapShader) { continue; } -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL if (const auto& attr = heatmapVertexAttrs.add(idVertexAttribName)) { attr->setSharedRawData(bucket.sharedVertices, @@ -441,6 +431,8 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : heatmapBuilder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); + drawable->mutableUniformBuffers().createOrUpdate(idHeatmapInterpolateUBOName, &interpolateUBO, context); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); @@ -450,13 +442,20 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, // Set up texture layer group if (!layerGroup) { - auto layerGroup_ = context.createLayerGroup(layerIndex, /*initialCapacity=*/1, getID()); - if (!layerGroup_) { + if (auto layerGroup_ = context.createLayerGroup(layerIndex, /*initialCapacity=*/1, getID())) { + if (textureTweaker) { + layerGroup_->addLayerTweaker(textureTweaker); + } + setLayerGroup(std::move(layerGroup_), changes); + } else { return; } - setLayerGroup(std::move(layerGroup_), changes); - updateLayerTextureTweaker(); } + if (!textureTweaker) { + textureTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(textureTweaker); + } + textureTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); if (!heatmapTextureShader) { heatmapTextureShader = context.getGenericShader(shaders, HeatmapTextureShaderGroupName); @@ -467,6 +466,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, } auto* textureLayerGroup = static_cast(layerGroup.get()); + // TODO: Don't rebuild drawables every time textureLayerGroup->clearDrawables(); std::unique_ptr heatmapTextureBuilder; @@ -516,6 +516,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, heatmapTextureBuilder->flush(); for (auto& drawable : heatmapTextureBuilder->clearDrawables()) { + drawable->setLayerTweaker(textureTweaker); textureLayerGroup->addDrawable(std::move(drawable)); ++stats.drawablesAdded; } diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.hpp b/src/mbgl/renderer/layers/render_heatmap_layer.hpp index 4d259fc06..d5c499f11 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.hpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.hpp @@ -47,11 +47,6 @@ private: void render(PaintParameters&) override; #endif -#if MLN_DRAWABLE_RENDERER - void updateLayerTweaker(); - void updateLayerTextureTweaker(); -#endif // MLN_DRAWABLE_RENDERER - bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, float, @@ -63,10 +58,12 @@ private: #if MLN_DRAWABLE_RENDERER /// Remove all drawables for the tile from the layer group - void removeTile(RenderPass, const OverscaledTileID&) override; + /// @return The number of drawables actually removed. + std::size_t removeTile(RenderPass, const OverscaledTileID&) override; /// Remove all the drawables for tiles - void removeAllDrawables() override; + /// @return The number of drawables actually removed. + std::size_t removeAllDrawables() override; #endif // Paint properties @@ -90,13 +87,9 @@ private: using TextureVertexVector = gfx::VertexVector; std::shared_ptr sharedTextureVertices; - HeatmapLayerTweakerPtr tweaker; - HeatmapTextureLayerTweakerPtr textureTweaker; -#if MLN_RENDER_BACKEND_METAL - std::vector propertiesAsUniforms; -#endif // MLN_RENDER_BACKEND_METAL - - bool overdrawInspector = false; + // This is the layer tweaker for applying the off-screen texture to the framebuffer. + // The inherited layer tweaker is for applying tiles to the off-screen texture. + LayerTweakerPtr textureTweaker; #endif }; diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp index 04297439c..fbbefb52c 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp @@ -73,7 +73,26 @@ void RenderHillshadeLayer::evaluate(const PropertyEvaluationParameters& paramete properties->renderPasses = mbgl::underlying_type(passes); evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - updateLayerTweaker(); + if (layerGroup) { + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); + } + + if (!activatedRenderTargets.empty()) { + auto newTweaker2 = std::make_shared(getID(), evaluatedProperties); + + std::vector groups; + for (const auto& target : activatedRenderTargets) { + if (const auto& group = target->getLayerGroup(0)) { + groups.push_back(group); + } + } + if (groups.empty()) { + prepareLayerTweaker = newTweaker2; + } else { + replaceTweaker(prepareLayerTweaker, std::move(newTweaker2), groups); + } + } #endif } @@ -284,16 +303,6 @@ static const StringIdentity idPosAttribName = StringIndexer::get("a_pos"); static const StringIdentity idTexturePosAttribName = StringIndexer::get("a_texture_pos"); static const StringIdentity idTexImageName = StringIndexer::get("u_image"); -#if MLN_DRAWABLE_RENDERER -void RenderHillshadeLayer::updateLayerTweaker() { - if (layerGroup) { - tweaker = std::make_shared(getID(), evaluatedProperties); - tweaker->enableOverdrawInspector(overdrawInspector); - layerGroup->setLayerTweaker(tweaker); - } -} -#endif // MLN_DRAWABLE_RENDERER - void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, [[maybe_unused]] const TransformState& state, @@ -309,16 +318,21 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, // Set up a layer group if (!layerGroup) { - auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID()); - if (!layerGroup_) { + if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { + setLayerGroup(std::move(layerGroup_), changes); + } else { return; } - setLayerGroup(std::move(layerGroup_), changes); - updateLayerTweaker(); } auto* tileLayerGroup = static_cast(layerGroup.get()); + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); + if (!hillshadePrepareShader) { hillshadePrepareShader = context.getGenericShader(shaders, HillshadePrepareShaderGroupName); } @@ -330,14 +344,6 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, return; } - const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); - if (overdrawInspector != overdraw) { - overdrawInspector = overdraw; - if (tweaker) { - tweaker->enableOverdrawInspector(overdrawInspector); - } - } - auto renderPass = RenderPass::Translucent; if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) { return; @@ -389,11 +395,13 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, if (!singleTileLayerGroup) { return; } - const auto prepareTweaker = std::make_shared(getID(), evaluatedProperties); - prepareTweaker->enableOverdrawInspector(overdrawInspector); - singleTileLayerGroup->setLayerTweaker(prepareTweaker); renderTarget->addLayerGroup(singleTileLayerGroup, /*replace=*/true); + if (!prepareLayerTweaker) { + prepareLayerTweaker = std::make_shared(getID(), evaluatedProperties); + } + singleTileLayerGroup->addLayerTweaker(prepareLayerTweaker); + gfx::VertexAttributeArray hillshadePrepareVertexAttrs; if (const auto& attr = hillshadePrepareVertexAttrs.add(idPosAttribName)) { @@ -437,6 +445,7 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : hillshadePrepareBuilder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(prepareLayerTweaker); drawable->setData(std::make_unique( bucket.getDEMData().stride, bucket.getDEMData().encoding, maxzoom)); singleTileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); @@ -474,31 +483,34 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, hillshadeBuilder = context.createDrawableBuilder("hillshade"); - if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) { - tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { - drawable.setVertexAttributes(std::move(hillshadeVertexAttrs)); - drawable.setVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); + const auto updateExisting = [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + return; + } + drawable.setVertexAttributes(std::move(hillshadeVertexAttrs)); + drawable.setVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); - std::vector> drawSegments; - for (std::size_t i = 0; i < segments->size(); ++i) { - const auto& seg = segments->data()[i]; - auto segCopy = SegmentBase{ - // no copy constructor - seg.vertexOffset, - seg.indexOffset, - seg.vertexLength, - seg.indexLength, - seg.sortKey, - }; - drawSegments.emplace_back(hillshadeBuilder->createSegment(gfx::Triangles(), std::move(segCopy))); - } - drawable.setIndexData(indices->vector(), std::move(drawSegments)); + std::vector> drawSegments; + for (std::size_t i = 0; i < segments->size(); ++i) { + const auto& seg = segments->data()[i]; + auto segCopy = SegmentBase{ + // no copy constructor + seg.vertexOffset, + seg.indexOffset, + seg.vertexLength, + seg.indexLength, + seg.sortKey, + }; + drawSegments.emplace_back(hillshadeBuilder->createSegment(gfx::Triangles(), std::move(segCopy))); + } + drawable.setIndexData(indices->vector(), std::move(drawSegments)); - auto imageLocation = hillshadeShader->getSamplerLocation(idTexImageName); - if (imageLocation.has_value()) { - drawable.setTexture(bucket.renderTarget->getTexture(), imageLocation.value()); - } - }); + auto imageLocation = hillshadeShader->getSamplerLocation(idTexImageName); + if (imageLocation.has_value()) { + drawable.setTexture(bucket.renderTarget->getTexture(), imageLocation.value()); + } + }; + if (0 < tileLayerGroup->visitDrawables(renderPass, tileID, updateExisting)) { continue; } @@ -521,6 +533,8 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : hillshadeBuilder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); + tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.drawablesAdded; } diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.hpp b/src/mbgl/renderer/layers/render_hillshade_layer.hpp index 050ce023a..97a74b25d 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.hpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.hpp @@ -75,8 +75,7 @@ private: using HillshadeVertexVector = gfx::VertexVector; std::shared_ptr staticDataSharedVertices; - HillshadeLayerTweakerPtr tweaker; - bool overdrawInspector = false; + LayerTweakerPtr prepareLayerTweaker; #endif }; diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index 2f79b0f76..9da26fd14 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -21,16 +21,6 @@ #include #include -#if MLN_DRAWABLE_RENDERER -#include -#include -#include -#include -#include -#include -#include -#endif - #if MLN_DRAWABLE_RENDERER #include #include @@ -40,6 +30,7 @@ #include #include #include +#include #endif namespace mbgl { @@ -90,7 +81,10 @@ void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) { evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - updateLayerTweaker(); + if (layerGroup) { + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup}); + } #endif } @@ -364,16 +358,6 @@ static const StringIdentity idLineSDFInterpolationUBOName = StringIndexer::get(" /// Evaluated properties that depend on the tile static const StringIdentity idLinePatternTilePropertiesUBOName = StringIndexer::get("LinePatternTilePropertiesUBO"); -void RenderLineLayer::updateLayerTweaker() { - if (layerGroup) { - tweaker = std::make_shared(getID(), evaluatedProperties); -#if MLN_RENDER_BACKEND_METAL - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); -#endif // MLN_RENDER_BACKEND_METAL - tweaker->enableOverdrawInspector(overdrawInspector); - layerGroup->setLayerTweaker(tweaker); - } -} static const StringIdentity idLineImageUniformName = StringIndexer::get("u_image"); @@ -390,23 +374,22 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, return; } - const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); - if (overdrawInspector != overdraw) { - overdrawInspector = overdraw; - if (tweaker) { - tweaker->enableOverdrawInspector(overdrawInspector); - } - } - // Set up a layer group if (!layerGroup) { if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { setLayerGroup(std::move(layerGroup_), changes); - updateLayerTweaker(); + } else { + return; } } auto* tileLayerGroup = static_cast(layerGroup.get()); + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); + if (!lineShaderGroup) { lineShaderGroup = shaders.getShaderGroup("LineShader"); } @@ -476,6 +459,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, builder->setSegments(gfx::Triangles(), bucket.sharedTriangles, bucket.segments.data(), bucket.segments.size()); }; + std::unordered_set propertiesAsUniforms; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -546,6 +530,11 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, // update existing drawables tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + // This drawable was produced on a previous style/bucket, and should not be updated. + return; + } + const auto& shader = drawable.getShader(); const auto& shaderUniforms = shader->getUniformBlocks(); auto& drawableUniforms = drawable.mutableUniformBuffers(); @@ -579,31 +568,30 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, } if (!evaluated.get().from.empty()) { - // dash array line (SDF) - gfx::VertexAttributeArray vertexAttrs; - auto propertiesAsUniforms_ = vertexAttrs.readDataDrivenPaintProperties(paintPropertyBinders, - evaluated); - if (!lineSDFShaderGroup) { continue; } - auto shader = lineSDFShaderGroup->getOrCreateShader(context, propertiesAsUniforms_); + + // dash array line (SDF) + propertiesAsUniforms.clear(); + gfx::VertexAttributeArray vertexAttrs; + vertexAttrs.readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); + + auto shader = lineSDFShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!shader) { continue; } -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL auto builder = createLineBuilder("lineSDF", std::move(shader)); @@ -618,6 +606,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder->clearDrawables()) { drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::SDF)); drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); drawable->setData(std::make_unique(cap)); drawable->mutableUniformBuffers().createOrUpdate( idLineSDFInterpolationUBOName, &lineSDFInterpolationUBO, context); @@ -626,31 +615,27 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, ++stats.drawablesAdded; } } else if (!unevaluated.get().isUndefined()) { - // pattern line - gfx::VertexAttributeArray vertexAttrs; - paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade); - auto propertiesAsUniforms_ = vertexAttrs.readDataDrivenPaintProperties(paintPropertyBinders, - evaluated); - if (!linePatternShaderGroup) { continue; } - auto shader = linePatternShaderGroup->getOrCreateShader(context, propertiesAsUniforms_); + + // pattern line + paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade); + + propertiesAsUniforms.clear(); + gfx::VertexAttributeArray vertexAttrs; + vertexAttrs + .readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); + + auto shader = linePatternShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!shader) { continue; } -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL auto builder = createLineBuilder("linePattern", std::move(shader)); @@ -679,6 +664,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder->clearDrawables()) { drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::Pattern)); drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); drawable->mutableUniformBuffers().createOrUpdate( idLinePatternInterpolationUBOName, &linePatternInterpolationUBO, context); drawable->mutableUniformBuffers().createOrUpdate( @@ -689,26 +675,24 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, } } } else if (!unevaluated.get().getValue().isUndefined()) { - // gradient line - gfx::VertexAttributeArray vertexAttrs; - auto propertiesAsUniforms_ = - vertexAttrs.readDataDrivenPaintProperties( - paintPropertyBinders, evaluated); - if (!lineGradientShaderGroup) { continue; } - auto shader = lineGradientShaderGroup->getOrCreateShader(context, propertiesAsUniforms_); + + // gradient line + propertiesAsUniforms.clear(); + gfx::VertexAttributeArray vertexAttrs; + vertexAttrs.readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); + + auto shader = lineGradientShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!shader) { continue; } -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL auto builder = createLineBuilder("lineGradient", std::move(shader)); @@ -736,6 +720,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder->clearDrawables()) { drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::Gradient)); drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); drawable->mutableUniformBuffers().createOrUpdate( idLineGradientInterpolationUBOName, &lineGradientInterpolationUBO, context); @@ -744,37 +729,26 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, } } } - } else { - // simple line - gfx::VertexAttributeArray vertexAttrs; - const auto propertiesAsUniforms_ = vertexAttrs.readDataDrivenPaintProperties( - paintPropertyBinders, evaluated); - - assert(6 == propertiesAsUniforms_.size()); - assert(vertexAttrs.size() == (size_t)std::count_if(propertiesAsUniforms_.begin(), - propertiesAsUniforms_.end(), - [](const auto& s) { return s.empty(); })); - if (!lineShaderGroup) { continue; } - auto shader = lineShaderGroup->getOrCreateShader(context, propertiesAsUniforms_); + + // simple line + propertiesAsUniforms.clear(); + gfx::VertexAttributeArray vertexAttrs; + vertexAttrs + .readDataDrivenPaintProperties( + paintPropertyBinders, evaluated, propertiesAsUniforms); + + auto shader = lineShaderGroup->getOrCreateShader(context, propertiesAsUniforms); if (!shader) { continue; } -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = std::move(propertiesAsUniforms_); - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL auto builder = createLineBuilder("line", std::move(shader)); @@ -787,6 +761,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder->clearDrawables()) { drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::Simple)); drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); drawable->mutableUniformBuffers().createOrUpdate( idLineInterpolationUBOName, &lineInterpolationUBO, context); diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp index 78424ff52..7b147bdc1 100644 --- a/src/mbgl/renderer/layers/render_line_layer.hpp +++ b/src/mbgl/renderer/layers/render_line_layer.hpp @@ -58,9 +58,6 @@ private: #if MLN_LEGACY_RENDERER void render(PaintParameters&) override; #endif -#if MLN_DRAWABLE_RENDERER - void updateLayerTweaker(); -#endif bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, @@ -97,13 +94,6 @@ private: gfx::ShaderGroupPtr linePatternShaderGroup; gfx::DrawableTweakerPtr iconTweaker; - LineLayerTweakerPtr tweaker; - -#if MLN_RENDER_BACKEND_METAL - std::vector propertiesAsUniforms; -#endif // MLN_RENDER_BACKEND_METAL - - bool overdrawInspector = false; #endif }; diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index a3022b59c..a32240fc1 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -53,7 +53,10 @@ void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters) evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - updateLayerTweaker(); + if (layerGroup) { + auto newTweaker = std::make_shared(getID(), evaluatedProperties); + replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup, imageLayerGroup}); + } #endif } @@ -247,19 +250,6 @@ static const StringIdentity idTexturePosAttribName = StringIndexer::get("a_textu static const StringIdentity idTexImage0Name = StringIndexer::get("u_image0"); static const StringIdentity idTexImage1Name = StringIndexer::get("u_image1"); -void RenderRasterLayer::updateLayerTweaker() { - if (layerGroup || imageLayerGroup) { - tweaker = std::make_shared(getID(), evaluatedProperties); - tweaker->enableOverdrawInspector(overdrawInspector); - if (layerGroup) { - layerGroup->setLayerTweaker(tweaker); - } - if (imageLayerGroup) { - imageLayerGroup->setLayerTweaker(tweaker); - } - } -} - void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& /*state*/, @@ -278,22 +268,28 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, return; } - auto renderPass = RenderPass::Translucent; + constexpr auto renderPass = RenderPass::Translucent; if (!rasterShader) { rasterShader = context.getGenericShader(shaders, "RasterShader"); if (!rasterShader) { return; } + rasterSampler0 = rasterShader->getSamplerLocation(idTexImage0Name); + rasterSampler1 = rasterShader->getSamplerLocation(idTexImage1Name); } - const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw); - if (overdrawInspector != overdraw) { - overdrawInspector = overdraw; - if (tweaker) { - tweaker->enableOverdrawInspector(overdrawInspector); + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + + if (layerGroup) { + layerGroup->addLayerTweaker(layerTweaker); + } + if (imageLayerGroup) { + imageLayerGroup->addLayerTweaker(layerTweaker); } } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); if (!staticDataVertices) { staticDataVertices = std::make_shared(RenderStaticData::rasterVertices()); @@ -305,61 +301,47 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, staticDataSegments = std::make_shared(RenderStaticData::rasterSegments()); } - const auto& evaluated = static_cast(*evaluatedProperties).evaluated; - RasterProgram::Binders paintAttributeData{evaluated, 0}; - - const gfx::TextureFilterType filter = evaluated.get() == RasterResamplingType::Nearest - ? gfx::TextureFilterType::Nearest - : gfx::TextureFilterType::Linear; - - auto createBuilder = [&context, &renderPass, this]() -> std::unique_ptr { - std::unique_ptr builder{context.createDrawableBuilder("raster")}; + const auto createBuilder = [&] { + auto builder = context.createDrawableBuilder("raster"); builder->setShader(rasterShader); builder->setRenderPass(renderPass); builder->setSubLayerIndex(0); - builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite - : gfx::DepthMaskType::ReadOnly); + builder->setDepthType(gfx::DepthMaskType::ReadOnly); builder->setColorMode(gfx::ColorMode::alphaBlended()); builder->setCullFaceMode(gfx::CullFaceMode::disabled()); builder->setVertexAttrNameId(idPosAttribName); - return builder; }; - auto setTextures = [&context, &filter, this](std::unique_ptr& builder, - const RasterBucket& bucket) { - // textures - auto location0 = rasterShader->getSamplerLocation(idTexImage0Name); - if (location0.has_value()) { - std::shared_ptr tex0 = context.createTexture2D(); - tex0->setImage(bucket.image); - tex0->setSamplerConfiguration({filter, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); - builder->setTexture(tex0, location0.value()); - } - auto location1 = rasterShader->getSamplerLocation(idTexImage1Name); - if (location1.has_value()) { - std::shared_ptr tex1 = context.createTexture2D(); - tex1->setImage(bucket.image); - tex1->setSamplerConfiguration({filter, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); - builder->setTexture(tex1, location1.value()); + const auto setTextures = [&](gfx::UniqueDrawableBuilder& builder, const RasterBucket& bucket) { + if (bucket.image && (rasterSampler0 || rasterSampler1)) { + if (auto tex = context.createTexture2D()) { + const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + const bool nearest = evaluated.get() == RasterResamplingType::Nearest; + const auto filter = nearest ? gfx::TextureFilterType::Nearest : gfx::TextureFilterType::Linear; + + tex->setImage(bucket.image); + tex->setSamplerConfiguration({filter, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); + + if (rasterSampler0) { + builder->setTexture(tex, *rasterSampler0); + } + if (rasterSampler1) { + builder->setTexture(std::move(tex), *rasterSampler1); + } + } } }; - auto buildVertexData = [this](std::unique_ptr& builder, const RasterBucket& bucket) { - RasterVertexVectorPtr vertices = staticDataVertices; - TriangleIndexVectorPtr indices = staticDataIndices; - const RasterSegmentVector* segments = staticDataSegments.get(); + // Build vertex attributes and apply them to a drawable or a builder + const auto buildVertexData = + [this](const gfx::UniqueDrawableBuilder& builder, gfx::Drawable* drawable, const RasterBucket& bucket) { + const bool shared = (!bucket.vertices.empty() && !bucket.indices.empty() && !bucket.segments.empty()); + const auto& vertices = shared ? bucket.sharedVertices : staticDataVertices; + const auto& indices = shared ? bucket.sharedTriangles : staticDataIndices; + const auto* segments = shared ? &bucket.segments : staticDataSegments.get(); - if (!bucket.vertices.empty() && !bucket.indices.empty() && !bucket.segments.empty()) { - vertices = bucket.sharedVertices; - indices = bucket.sharedTriangles; - segments = &bucket.segments; - } - - // attributes - { gfx::VertexAttributeArray vertexAttrs; - if (auto& attr = vertexAttrs.add(idPosAttribName)) { attr->setSharedRawData(vertices, offsetof(RasterLayoutVertex, a1), @@ -376,76 +358,74 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, gfx::AttributeDataType::Short2); } - builder->setVertexAttributes(std::move(vertexAttrs)); + if (drawable) { + drawable->setVertexAttributes(std::move(vertexAttrs)); + } else if (builder) { + builder->setVertexAttributes(std::move(vertexAttrs)); + builder->setRawVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); + builder->setSegments(gfx::Triangles(), indices, segments->data(), segments->size()); + } + }; + + gfx::UniqueDrawableBuilder builder; + if (imageData) { + // TODO: Can we avoid rebuilding drawables each time in this case as well? + if (imageLayerGroup) { + stats.drawablesRemoved += imageLayerGroup->clearDrawables(); } - builder->setRawVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); - builder->setSegments(gfx::Triangles(), indices, segments->data(), segments->size()); - }; - - auto buildDrawables = [&setTextures, &buildVertexData](std::unique_ptr& builder, - const RasterBucket& bucket) { - buildVertexData(builder, bucket); - setTextures(builder, bucket); - }; - - auto updateTileDrawables = [&](std::unique_ptr& builder, - auto* tileLayerGroup, - const auto& tileID, - const RasterBucket& bucket) { - // TODO: check for oportunity to skip - - buildVertexData(builder, bucket); - tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { - for (auto& tex : drawable.getTextures()) { - builder->setTexture(tex.second, tex.first); - } - }); - }; - - if (imageData) { RasterBucket& bucket = *imageData->bucket; if (!bucket.vertices.empty()) { - if (imageLayerGroup) { - stats.drawablesRemoved += imageLayerGroup->clearDrawables(); - } else { + if (!imageLayerGroup) { // Set up a layer group imageLayerGroup = context.createLayerGroup(layerIndex, /*initialCapacity=*/64, getID()); + imageLayerGroup->addLayerTweaker(layerTweaker); activateLayerGroup(imageLayerGroup, isRenderable, changes); - updateLayerTweaker(); } - auto builder = createBuilder(); + // Create a drawable for each transformation + // TODO: Share textures + builder = createBuilder(); for (const auto& matrix_ : imageData->matrices) { - buildDrawables(builder, bucket); + buildVertexData(builder, /*drawable=*/nullptr, bucket); + setTextures(builder, bucket); // finish builder->flush(); for (auto& drawable : builder->clearDrawables()) { drawable->setData(std::make_unique(matrix_)); + drawable->setLayerTweaker(layerTweaker); imageLayerGroup->addDrawable(std::move(drawable)); ++stats.drawablesAdded; } } } } else if (renderTiles) { - if (layerGroup) { - stats.drawablesRemoved += layerGroup->removeDrawablesIf([&](gfx::Drawable& drawable) { - // Has this tile dropped out of the cover set? - return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); + // Update existing drawables, returns the number of drawables found for the tile + const auto updateTileDrawables = [&](auto* tileLayerGroup, const auto& tileID, const RasterBucket& bucket) { + return tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() == layerTweaker) { + gfx::UniqueDrawableBuilder none; + buildVertexData(none, &drawable, bucket); + } }); + }; + + // Remove existing drawables that are no longer in the cover set + if (layerGroup) { + stats.drawablesRemoved += layerGroup->removeDrawablesIf( + [&](gfx::Drawable& drawable) { return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); }); } else { // Set up a tile layer group if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { + layerGroup_->addLayerTweaker(layerTweaker); setLayerGroup(std::move(layerGroup_), changes); - updateLayerTweaker(); } } auto* tileLayerGroup = static_cast(layerGroup.get()); - auto builder = createBuilder(); for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -455,30 +435,44 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, continue; } + bool cleared = false; const auto& bucket = static_cast(*bucket_); - const auto prevBucketID = getRenderTileBucketID(tileID); - if (prevBucketID != util::SimpleIdentity::Empty && prevBucketID != bucket.getID()) { - // This tile was previously set up from a different bucket, drop and re-create any drawables for it. + // If the bucket data has changed, rebuild the drawables. + const bool bucketSharedData = (!bucket.vertices.empty() && !bucket.indices.empty() && + !bucket.segments.empty()); + const bool bucketDirty = bucketSharedData && (bucket.vertices.getDirty() || bucket.indices.getDirty()); + if (bucketDirty) { + // Note, vertex/index dirty flags will be reset when those buffers are uploaded. removeTile(renderPass, tileID); + cleared = true; + } else if (setRenderTileBucketID(tileID, bucket.getID())) { + // Bucket ID changed, we need to rebuild the drawables + removeTile(renderPass, tileID); + cleared = true; } - setRenderTileBucketID(tileID, bucket.getID()); - if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) { - // re-create drawable geometry and pass texture - updateTileDrawables(builder, tileLayerGroup, tileID, bucket); + // If there are any drawables left for this tile, update them. + if (!cleared && 0 < updateTileDrawables(tileLayerGroup, tileID, bucket)) { + continue; + } - // erase current drawable - removeTile(renderPass, tileID); - } else if (bucket.image) { - // build new drawable for this tile - buildDrawables(builder, bucket); + // Otherwise, create new ones. + if (!builder) { + builder = createBuilder(); + } + + if (bucket.image && builder->getTextures().size() == 0) { + setTextures(builder, bucket); }; + buildVertexData(builder, /*drawable=*/nullptr, bucket); + // finish builder->flush(); for (auto& drawable : builder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.drawablesAdded; } diff --git a/src/mbgl/renderer/layers/render_raster_layer.hpp b/src/mbgl/renderer/layers/render_raster_layer.hpp index 849a3dbc1..361392d82 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.hpp +++ b/src/mbgl/renderer/layers/render_raster_layer.hpp @@ -8,11 +8,6 @@ namespace mbgl { -#if MLN_DRAWABLE_RENDERER -class RasterLayerTweaker; -using RasterLayerTweakerPtr = std::shared_ptr; -#endif // MLN_DRAWABLE_RENDERER - class ImageSourceRenderData; class RasterProgram; @@ -60,10 +55,6 @@ private: void render(PaintParameters&) override; #endif -#if MLN_DRAWABLE_RENDERER - void updateLayerTweaker(); -#endif // MLN_DRAWABLE_RENDERER - // Paint properties style::RasterPaintProperties::Unevaluated unevaluated; const ImageSourceRenderData* imageData = nullptr; @@ -75,6 +66,8 @@ private: #if MLN_DRAWABLE_RENDERER gfx::ShaderProgramBasePtr rasterShader; + std::optional rasterSampler0; + std::optional rasterSampler1; LayerGroupPtr imageLayerGroup; using RasterVertexVector = gfx::VertexVector; @@ -88,9 +81,6 @@ private: using RasterSegmentVector = SegmentVector; using RasterSegmentVectorPtr = std::shared_ptr; std::shared_ptr staticDataSegments; - - RasterLayerTweakerPtr tweaker; - bool overdrawInspector = false; #endif }; diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 3a06160ef..bc8437218 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -379,11 +380,10 @@ void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - if (layerGroup && layerGroup->getLayerTweaker()) { -#if MLN_RENDER_BACKEND_METAL - layerGroup->getLayerTweaker()->setPropertiesAsUniforms(propertiesAsUniforms); -#endif // MLN_RENDER_BACKEND_METAL - layerGroup->getLayerTweaker()->updateProperties(evaluatedProperties); + // The symbol tweaker supports updating properties. + // When the style changes, it will be replaced in `RenderLayer::layerChanged` + if (layerTweaker) { + layerTweaker->updateProperties(evaluatedProperties); } #endif // MLN_DRAWABLE_RENDERER } @@ -749,19 +749,21 @@ SymbolDrawableTilePropsUBO buildTileUBO(const SymbolBucket& bucket, }; } -static const StringIdentity idDataAttibName = StringIndexer::get("a_data"); -static const StringIdentity idPosOffsetAttribName = StringIndexer::get("a_pos_offset"); -static const StringIdentity idPixOffsetAttribName = StringIndexer::get("a_pixeloffset"); -static const StringIdentity idProjPosAttribName = StringIndexer::get("a_projected_pos"); -static const StringIdentity idFadeOpacityAttribName = StringIndexer::get("a_fade_opacity"); -static const StringIdentity idTexUniformName = StringIndexer::get("u_texture"); -static const StringIdentity idTexIconUniformName = StringIndexer::get("u_texture_icon"); +static const auto idDataAttibName = StringIndexer::get("a_data"); +static const auto posOffsetAttribName = "a_pos_offset"; +static const auto idPosOffsetAttribName = StringIndexer::get(posOffsetAttribName); +static const auto idPixOffsetAttribName = StringIndexer::get("a_pixeloffset"); +static const auto idProjPosAttribName = StringIndexer::get("a_projected_pos"); +static const auto idFadeOpacityAttribName = StringIndexer::get("a_fade_opacity"); +static const auto idTexUniformName = StringIndexer::get("u_texture"); +static const auto idTexIconUniformName = StringIndexer::get("u_texture_icon"); -std::vector updateTileAttributes(const SymbolBucket::Buffer& buffer, - const bool isText, - const SymbolBucket::PaintProperties& paintProps, - const SymbolPaintProperties::PossiblyEvaluated& evaluated, - gfx::VertexAttributeArray& attribs) { +void updateTileAttributes(const SymbolBucket::Buffer& buffer, + const bool isText, + const SymbolBucket::PaintProperties& paintProps, + const SymbolPaintProperties::PossiblyEvaluated& evaluated, + gfx::VertexAttributeArray& attribs, + std::unordered_set& propertiesAsUniforms) { if (const auto& attr = attribs.getOrAdd(idPosOffsetAttribName)) { attr->setSharedRawData(buffer.sharedVertices, offsetof(SymbolLayoutVertex, a1), @@ -801,13 +803,13 @@ std::vector updateTileAttributes(const SymbolBucket::Buffer& buffer gfx::AttributeDataType::Float); } - return isText - ? attribs - .readDataDrivenPaintProperties( - paintProps.textBinders, evaluated) - : attribs - .readDataDrivenPaintProperties( - paintProps.iconBinders, evaluated); + if (isText) { + attribs.readDataDrivenPaintProperties( + paintProps.textBinders, evaluated, propertiesAsUniforms); + } else { + attribs.readDataDrivenPaintProperties( + paintProps.iconBinders, evaluated, propertiesAsUniforms); + } } void updateTileDrawable(gfx::Drawable& drawable, @@ -817,7 +819,8 @@ void updateTileDrawable(gfx::Drawable& drawable, const SymbolPaintProperties::PossiblyEvaluated& evaluated, const TransformState& state, gfx::UniformBufferPtr& textInterpUBO, - gfx::UniformBufferPtr& iconInterpUBO) { + gfx::UniformBufferPtr& iconInterpUBO, + std::unordered_set& propertiesAsUniforms) { if (!drawable.getData()) { return; } @@ -859,7 +862,7 @@ void updateTileDrawable(gfx::Drawable& drawable, // See `Placement::updateBucketDynamicVertices` gfx::VertexAttributeArray attribs; - updateTileAttributes(buffer, isText, paintProps, evaluated, attribs); + updateTileAttributes(buffer, isText, paintProps, evaluated, attribs, propertiesAsUniforms); drawable.setVertexAttributes(std::move(attribs)); } @@ -970,16 +973,19 @@ void RenderSymbolLayer::layerIndexChanged(int32_t newLayerIndex, UniqueChangeReq changeLayerIndex(collisionTileLayerGroup, newLayerIndex, changes); } -void RenderSymbolLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { +std::size_t RenderSymbolLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { + const auto oldValue = stats.drawablesRemoved; if (const auto tileGroup = static_cast(layerGroup.get())) { stats.drawablesRemoved += tileGroup->removeDrawables(renderPass, tileID).size(); } if (collisionTileLayerGroup) { stats.drawablesRemoved += collisionTileLayerGroup->removeDrawables(renderPass, tileID).size(); } + return stats.drawablesRemoved - oldValue; } -void RenderSymbolLayer::removeAllDrawables() { +std::size_t RenderSymbolLayer::removeAllDrawables() { + const auto oldValue = stats.drawablesRemoved; if (layerGroup) { stats.drawablesRemoved += layerGroup->getDrawableCount(); layerGroup->clearDrawables(); @@ -988,12 +994,13 @@ void RenderSymbolLayer::removeAllDrawables() { stats.drawablesRemoved += collisionTileLayerGroup->getDrawableCount(); collisionTileLayerGroup->clearDrawables(); } + return stats.drawablesRemoved - oldValue; } void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, - const std::shared_ptr&, + const std::shared_ptr& updateParameters, const RenderTree& /*renderTree*/, UniqueChangeRequestVec& changes) { if (!renderTiles || renderTiles->empty() || passes == RenderPass::None) { @@ -1004,24 +1011,27 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, // Set up a layer group if (!layerGroup) { if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { - tweaker = std::make_shared(getID(), evaluatedProperties); -#if MLN_RENDER_BACKEND_METAL - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); -#endif // MLN_RENDER_BACKEND_METAL - layerGroup_->setLayerTweaker(tweaker); setLayerGroup(std::move(layerGroup_), changes); } } + if (!layerTweaker) { + layerTweaker = std::make_shared(getID(), evaluatedProperties); + layerGroup->addLayerTweaker(layerTweaker); + } + layerTweaker->enableOverdrawInspector(!!(updateParameters->debugOptions & MapDebugOptions::Overdraw)); + const auto& getCollisionTileLayerGroup = [&] { if (!collisionTileLayerGroup) { if ((collisionTileLayerGroup = context.createTileLayerGroup( layerIndex, /*initialCapacity=*/64, getID() + "-collision"))) { - collisionTileLayerGroup->setLayerTweaker( - std::make_shared(getID(), evaluatedProperties)); activateLayerGroup(collisionTileLayerGroup, true, changes); } } + if (!collisionLayerTweaker) { + collisionLayerTweaker = std::make_shared(getID(), evaluatedProperties); + collisionTileLayerGroup->addLayerTweaker(collisionLayerTweaker); + } return collisionTileLayerGroup; }; @@ -1079,6 +1089,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, collisionBuilder->setColorMode(gfx::ColorMode::alphaBlended()); collisionBuilder->setVertexAttrNameId(idCollisionPosAttribName); + std::unordered_set propertiesAsUniforms; for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -1168,6 +1179,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, // add drawables to layer group for (auto& drawable : collisionBuilder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(collisionLayerTweaker); + auto drawData = std::make_unique(values.translate, values.translateAnchor); drawable->setData(std::move(drawData)); group->addDrawable(passes, tileID, std::move(drawable)); @@ -1181,9 +1194,22 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, // Just update the drawables we already created tileLayerGroup->visitDrawables(passes, tileID, [&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() != layerTweaker) { + // This drawable was produced on a previous style/bucket, and should not be updated. + return; + } + const auto& evaluated = getEvaluated(renderData.layerProperties); - updateTileDrawable( - drawable, context, bucket, bucketPaintProperties, evaluated, state, textInterpUBO, iconInterpUBO); + propertiesAsUniforms.clear(); + updateTileDrawable(drawable, + context, + bucket, + bucketPaintProperties, + evaluated, + state, + textInterpUBO, + iconInterpUBO, + propertiesAsUniforms); }); // re-create collision drawables @@ -1263,15 +1289,12 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, const auto vertexCount = buffer.vertices().elements(); + propertiesAsUniforms.clear(); gfx::VertexAttributeArray attribs; - const auto uniformProps = updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, attribs); - -#if MLN_RENDER_BACKEND_METAL - propertiesAsUniforms = uniformProps; - if (tweaker) { - tweaker->setPropertiesAsUniforms(propertiesAsUniforms); + updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, attribs, propertiesAsUniforms); + if (layerTweaker) { + layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms); } -#endif // MLN_RENDER_BACKEND_METAL const auto textHalo = evaluated.get().constantOr(Color::black()).a > 0.0f && evaluated.get().constantOr(1); @@ -1341,7 +1364,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, return; } const auto shader = std::static_pointer_cast( - shaderGroup->getOrCreateShader(context, uniformProps, StringIndexer::get(idPosOffsetAttribName))); + shaderGroup->getOrCreateShader(context, propertiesAsUniforms, posOffsetAttribName)); if (!shader) { return; } @@ -1359,6 +1382,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : builder->clearDrawables()) { drawable->setTileID(tileID); + drawable->setLayerTweaker(layerTweaker); auto drawData = std::make_unique( /*.isHalo=*/isHalo, diff --git a/src/mbgl/renderer/layers/render_symbol_layer.hpp b/src/mbgl/renderer/layers/render_symbol_layer.hpp index c391d266b..a1e483313 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.hpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.hpp @@ -118,10 +118,10 @@ protected: void layerRemoved(UniqueChangeRequestVec&) override; /// Remove all drawables for the tile from the layer group - void removeTile(RenderPass, const OverscaledTileID&) override; + std::size_t removeTile(RenderPass, const OverscaledTileID&) override; /// Remove all the drawables for tiles - void removeAllDrawables() override; + std::size_t removeAllDrawables() override; #endif // MLN_DRAWABLE_RENDERER private: @@ -151,8 +151,6 @@ private: #endif // MLN_LEGACY_RENDERER #if MLN_DRAWABLE_RENDERER - SymbolLayerTweakerPtr tweaker; - gfx::ShaderGroupPtr symbolIconGroup; gfx::ShaderGroupPtr symbolSDFGroup; gfx::ShaderGroupPtr symbolTextAndIconGroup; @@ -160,11 +158,9 @@ private: gfx::ShaderGroupPtr collisionBoxGroup; gfx::ShaderGroupPtr collisionCircleGroup; std::shared_ptr collisionTileLayerGroup; -#endif // MLN_DRAWABLE_RENDERER -#if MLN_RENDER_BACKEND_METAL - std::vector propertiesAsUniforms; -#endif // MLN_RENDER_BACKEND_METAL + LayerTweakerPtr collisionLayerTweaker; +#endif // MLN_DRAWABLE_RENDERER }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp index a7b7f16bf..204cffe58 100644 --- a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp @@ -19,6 +19,7 @@ #if MLN_RENDER_BACKEND_METAL #include +#include #endif // MLN_RENDER_BACKEND_METAL namespace mbgl { @@ -92,11 +93,11 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, #if MLN_RENDER_BACKEND_METAL if (propertiesChanged) { const SymbolPermutationUBO permutationUBO = { - /* .fill_color = */ {/*.source=*/getAttributeSource("a_fill_color"), /*.expression=*/{}}, - /* .halo_color = */ {/*.source=*/getAttributeSource("a_halo_color"), /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/getAttributeSource("a_opacity"), /*.expression=*/{}}, - /* .halo_width = */ {/*.source=*/getAttributeSource("a_halo_width"), /*.expression=*/{}}, - /* .halo_blur = */ {/*.source=*/getAttributeSource("a_halo_blur"), /*.expression=*/{}}, + /* .fill_color = */ {/*.source=*/getAttributeSource(5), /*.expression=*/{}}, + /* .halo_color = */ {/*.source=*/getAttributeSource(6), /*.expression=*/{}}, + /* .opacity = */ {/*.source=*/getAttributeSource(7), /*.expression=*/{}}, + /* .halo_width = */ {/*.source=*/getAttributeSource(8), /*.expression=*/{}}, + /* .halo_blur = */ {/*.source=*/getAttributeSource(9), /*.expression=*/{}}, /* .overdrawInspector = */ overdrawInspector, /* .pad = */ 0, 0, @@ -116,6 +117,12 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, } #endif + if (propertiesUpdated) { + textPropertiesUpdated = true; + iconPropertiesUpdated = true; + propertiesUpdated = false; + } + layerGroup.visitDrawables([&](gfx::Drawable& drawable) { if (!drawable.getTileID() || !drawable.getData()) { return; @@ -125,14 +132,15 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, const auto& symbolData = static_cast(*drawable.getData()); const auto isText = (symbolData.symbolType == SymbolType::Text); - if (isText && (!textPaintBuffer || propertiesUpdated)) { + if (isText && (textPaintBuffer || textPropertiesUpdated)) { const auto props = buildPaintUBO(true, evaluated); textPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props)); - } else if (!isText && (!iconPaintBuffer || propertiesUpdated)) { + textPropertiesUpdated = false; + } else if (!isText && (!iconPaintBuffer || iconPropertiesUpdated)) { const auto props = buildPaintUBO(false, evaluated); iconPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props)); + iconPropertiesUpdated = false; } - propertiesUpdated = false; // from RenderTile::translatedMatrix const auto translate = isText ? evaluated.get() : evaluated.get(); diff --git a/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp b/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp index 97098d99f..a632da3ff 100644 --- a/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp @@ -30,6 +30,9 @@ private: gfx::UniformBufferPtr textPaintBuffer; gfx::UniformBufferPtr iconPaintBuffer; + bool textPropertiesUpdated = false; + bool iconPropertiesUpdated = false; + #if MLN_RENDER_BACKEND_METAL gfx::UniformBufferPtr permutationUniformBuffer; gfx::UniformBufferPtr expressionUniformBuffer; diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp index ea974117b..4311bcb11 100644 --- a/src/mbgl/renderer/render_layer.cpp +++ b/src/mbgl/renderer/render_layer.cpp @@ -70,11 +70,41 @@ std::optional RenderLayer::getSolidBackground() const { } #if MLN_DRAWABLE_RENDERER +void RenderLayer::replaceTweaker(LayerTweakerPtr& curTweaker, + LayerTweakerPtr newTweaker, + const std::vector& layerGroups) { + const auto prevTweaker = curTweaker; + + // We need to re-create the tweaker because it doesn't yet support modifying evaluated + // properties, but we don't want to stop updating drawables (as in the `layerChanged` case) + // so we need to update the tweaker reference on the outstanding drawables so that they + // pass the check in `updateExisting`. + // TODO: Once the tweaker doesn't need to be re-created on each property evaluation, this won't be needed. + for (const auto& group : layerGroups) { + if (group) { + group->addLayerTweaker(newTweaker); + + group->visitDrawables([&](gfx::Drawable& drawable) { + if (drawable.getLayerTweaker() == prevTweaker) { + drawable.setLayerTweaker(curTweaker); + } + }); + } + } + + curTweaker = std::move(newTweaker); +} + void RenderLayer::layerChanged(const TransitionParameters&, const Immutable&, UniqueChangeRequestVec&) { // When a layer changes, the bucket won't be replaced until the new source(s) load. // If we remove the drawables here, they will just be re-created based on the current data. + + // Detach the layer tweaker, if any. This keeps the existing tiles up-to-date with the + // most recent evaluated properties, while a new one will be created along with new drawables + // when tiles are loaded and new buckets are available. + layerTweaker.reset(); } void RenderLayer::layerRemoved(UniqueChangeRequestVec& changes) { @@ -136,17 +166,23 @@ const LayerRenderData* RenderLayer::getRenderDataForPass(const RenderTile& tile, } #if MLN_DRAWABLE_RENDERER -void RenderLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { +std::size_t RenderLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { if (const auto tileGroup = static_cast(layerGroup.get())) { - stats.drawablesRemoved += tileGroup->removeDrawables(renderPass, tileID).size(); + const auto n = tileGroup->removeDrawables(renderPass, tileID).size(); + stats.drawablesRemoved += n; + return n; } + return 0; } -void RenderLayer::removeAllDrawables() { +std::size_t RenderLayer::removeAllDrawables() { if (layerGroup) { - stats.drawablesRemoved += layerGroup->getDrawableCount(); + const auto count = layerGroup->getDrawableCount(); + stats.drawablesRemoved += count; layerGroup->clearDrawables(); + return count; } + return 0; } void RenderLayer::updateRenderTileIDs() { diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index 020576462..6ad7b0b02 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -211,10 +211,11 @@ protected: void changeLayerIndex(const LayerGroupBasePtr&, int32_t newLayerIndex, UniqueChangeRequestVec&); /// Remove all drawables for the tile from the layer group - virtual void removeTile(RenderPass, const OverscaledTileID&); + /// @return The number of drawables actually removed. + virtual std::size_t removeTile(RenderPass, const OverscaledTileID&); /// Remove all the drawables for tiles - virtual void removeAllDrawables(); + virtual std::size_t removeAllDrawables(); /// Update `renderTileIDs` from `renderTiles` void updateRenderTileIDs(); @@ -233,6 +234,12 @@ protected: /// @return true if updated, false if the tile ID is not present in the set of tiles to be rendered or the ID is /// unchanged bool setRenderTileBucketID(const OverscaledTileID&, util::SimpleIdentity bucketID); + + /// Update the layer tweaker and drawables which reference it + static void replaceTweaker(LayerTweakerPtr& toReplace, + LayerTweakerPtr newTweaker, + const std::vector&); + #endif // MLN_DRAWABLE_RENDERER static bool applyColorRamp(const style::ColorRampPropertyValue&, PremultipliedImage&); @@ -251,6 +258,9 @@ protected: // will need to be overriden to handle their activation. LayerGroupBasePtr layerGroup; + // An optional tweaker that will update drawables + LayerTweakerPtr layerTweaker; + // The set of Tile IDs in `renderTiles`, along with the // identity of the bucket from which they were built. std::unordered_map renderTileIDs; diff --git a/src/mbgl/renderer/render_target.cpp b/src/mbgl/renderer/render_target.cpp index 924dae958..4d707d13e 100644 --- a/src/mbgl/renderer/render_target.cpp +++ b/src/mbgl/renderer/render_target.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace mbgl { @@ -84,11 +85,7 @@ void RenderTarget::render(RenderOrchestrator& orchestrator, const RenderTree& re "render target", {*offscreenTexture, Color{0.0f, 0.0f, 0.0f, 1.0f}, {}, {}}); // Run layer tweakers to update any dynamic elements - visitLayerGroups([&](LayerGroupBase& layerGroup) { - if (layerGroup.getLayerTweaker()) { - layerGroup.getLayerTweaker()->execute(layerGroup, renderTree, parameters); - } - }); + visitLayerGroups([&](LayerGroupBase& layerGroup) { layerGroup.runTweakers(renderTree, parameters); }); // draw layer groups, opaque pass parameters.pass = RenderPass::Opaque; diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index bf6c2df29..c917bdf69 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -152,11 +152,8 @@ void Renderer::Impl::render(const RenderTree& renderTree, #endif // Tweakers are run in the upload pass so they can set up uniforms. - orchestrator.visitLayerGroups([&](LayerGroupBase& layerGroup) { - if (layerGroup.getLayerTweaker()) { - layerGroup.getLayerTweaker()->execute(layerGroup, renderTree, parameters); - } - }); + orchestrator.visitLayerGroups( + [&](LayerGroupBase& layerGroup) { layerGroup.runTweakers(renderTree, parameters); }); } // Update the debug layer groups diff --git a/src/mbgl/shaders/mtl/background.cpp b/src/mbgl/shaders/mtl/background.cpp new file mode 100644 index 000000000..9eec3d3c1 --- /dev/null +++ b/src/mbgl/shaders/mtl/background.cpp @@ -0,0 +1,17 @@ +#include +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Float3, 1, "a_pos"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{1, true, true, sizeof(BackgroundLayerUBO), "BackgroundLayerUBO"}, + UniformBlockInfo{2, true, false, sizeof(BackgroundDrawableUBO), "BackgroundDrawableUBO"}, +}; +const std::array ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/background_pattern.cpp b/src/mbgl/shaders/mtl/background_pattern.cpp new file mode 100644 index 000000000..fa173422d --- /dev/null +++ b/src/mbgl/shaders/mtl/background_pattern.cpp @@ -0,0 +1,14 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array + ShaderSource::uniforms = { + UniformBlockInfo{1, sizeof(BackgroundLayerUBO), true, false, "BackgroundLayerUBO"}, + UniformBlockInfo{2, sizeof(BackgroundDrawableUBO), true, false, "BackgroundDrawableUBO"}, + UniformBlockInfo{3, sizeof(BackgroundPatternLayerUBO), true, false, "BackgroundPatternLayerUBO"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/circle.cpp b/src/mbgl/shaders/mtl/circle.cpp new file mode 100644 index 000000000..cdf6c06cf --- /dev/null +++ b/src/mbgl/shaders/mtl/circle.cpp @@ -0,0 +1,27 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Float2, 1, "a_color"}, + AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_radius"}, + AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_blur"}, + AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_opacity"}, + AttributeInfo{5, gfx::AttributeDataType::Float4, 1, "a_stroke_color"}, + AttributeInfo{6, gfx::AttributeDataType::Float2, 1, "a_stroke_width"}, + AttributeInfo{7, gfx::AttributeDataType::Float2, 1, "a_stroke_opacity"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{8, true, false, sizeof(CircleDrawableUBO), "CircleDrawableUBO"}, + UniformBlockInfo{9, true, true, sizeof(CirclePaintParamsUBO), "CirclePaintParamsUBO"}, + UniformBlockInfo{10, true, true, sizeof(CircleEvaluatedPropsUBO), "CircleEvaluatedPropsUBO"}, + UniformBlockInfo{11, true, false, sizeof(CircleInterpolateUBO), "CircleInterpolateUBO"}, + UniformBlockInfo{12, true, true, sizeof(CirclePermutationUBO), "CirclePermutationUBO"}, + UniformBlockInfo{13, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/clipping_mask.cpp b/src/mbgl/shaders/mtl/clipping_mask.cpp new file mode 100644 index 000000000..9cd391a1e --- /dev/null +++ b/src/mbgl/shaders/mtl/clipping_mask.cpp @@ -0,0 +1,16 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Float3, 1, "a_pos"}, +}; +const std::array ShaderSource::uniforms = + { + UniformBlockInfo{1, true, false, sizeof(ClipUBO), "ClipUBO"}, +}; +const std::array ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/fill.cpp b/src/mbgl/shaders/mtl/fill.cpp new file mode 100644 index 000000000..448a8786d --- /dev/null +++ b/src/mbgl/shaders/mtl/fill.cpp @@ -0,0 +1,82 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Float2, 1, "a_color"}, + AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_opacity"}, + + // This shader doesn't use it, but we need this so that the layer can assign the same + // attributes to all the drawables. If/When `VertexAttributeArray::resolve` allows it, + // this can be removed. + AttributeInfo{8, gfx::AttributeDataType::Float2, 1, "a_outline_color"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{3, true, false, sizeof(FillDrawableUBO), "FillDrawableUBO"}, + UniformBlockInfo{4, true, true, sizeof(FillEvaluatedPropsUBO), "FillEvaluatedPropsUBO"}, + UniformBlockInfo{5, true, false, sizeof(FillInterpolateUBO), "FillInterpolateUBO"}, + UniformBlockInfo{6, true, true, sizeof(FillPermutationUBO), "FillPermutationUBO"}, + UniformBlockInfo{7, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = {}; + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Float2, 1, "a_outline_color"}, + AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_opacity"}, + + // See `a_outline_color` in FillShader + AttributeInfo{8, gfx::AttributeDataType::Float2, 1, "a_color"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{3, true, false, sizeof(FillOutlineDrawableUBO), "FillOutlineDrawableUBO"}, + UniformBlockInfo{4, true, true, sizeof(FillOutlineEvaluatedPropsUBO), "FillOutlineEvaluatedPropsUBO"}, + UniformBlockInfo{5, true, false, sizeof(FillOutlineInterpolateUBO), "FillOutlineInterpolateUBO"}, + UniformBlockInfo{6, true, true, sizeof(FillOutlinePermutationUBO), "FillOutlinePermutationUBO"}, + UniformBlockInfo{7, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = {}; + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"}, + AttributeInfo{2, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"}, + AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{4, true, true, sizeof(FillPatternDrawableUBO), "FillPatternDrawableUBO"}, + UniformBlockInfo{5, true, false, sizeof(FillPatternTilePropsUBO), "FillPatternTilePropsUBO"}, + UniformBlockInfo{6, true, true, sizeof(FillPatternEvaluatedPropsUBO), "FillPatternEvaluatedPropsUBO"}, + UniformBlockInfo{7, true, false, sizeof(FillPatternInterpolateUBO), "FillPatternInterpolateUBO"}, + UniformBlockInfo{8, true, true, sizeof(FillPatternPermutationUBO), "FillPatternPermutationUBO"}, + UniformBlockInfo{9, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image"}, +}; + +const std::array + ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"}, + AttributeInfo{2, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"}, + AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{4, true, true, sizeof(FillOutlinePatternDrawableUBO), "FillOutlinePatternDrawableUBO"}, + UniformBlockInfo{5, true, false, sizeof(FillOutlinePatternTilePropsUBO), "FillOutlinePatternTilePropsUBO"}, + UniformBlockInfo{6, true, true, sizeof(FillOutlinePatternEvaluatedPropsUBO), "FillOutlinePatternEvaluatedPropsUBO"}, + UniformBlockInfo{7, true, false, sizeof(FillOutlinePatternInterpolateUBO), "FillOutlinePatternInterpolateUBO"}, + UniformBlockInfo{8, true, true, sizeof(FillOutlinePatternPermutationUBO), "FillOutlinePatternPermutationUBO"}, + UniformBlockInfo{9, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = + { + TextureInfo{0, "u_image"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/fill_extrusion.cpp b/src/mbgl/shaders/mtl/fill_extrusion.cpp new file mode 100644 index 000000000..a320f95e8 --- /dev/null +++ b/src/mbgl/shaders/mtl/fill_extrusion.cpp @@ -0,0 +1,24 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Short4, 1, "a_normal_ed"}, + AttributeInfo{2, gfx::AttributeDataType::Float4, 1, "a_color"}, + AttributeInfo{3, gfx::AttributeDataType::Float, 1, "a_base"}, + AttributeInfo{4, gfx::AttributeDataType::Float, 1, "a_height"}, +}; +const std::array ShaderSource::uniforms = + { + UniformBlockInfo{5, true, false, sizeof(FillExtrusionDrawableUBO), "FillExtrusionDrawableUBO"}, + UniformBlockInfo{6, true, false, sizeof(FillExtrusionDrawablePropsUBO), "FillExtrusionDrawablePropsUBO"}, + UniformBlockInfo{7, true, false, sizeof(FillExtrusionInterpolateUBO), "FillExtrusionInterpolateUBO"}, + UniformBlockInfo{8, true, false, sizeof(FillExtrusionPermutationUBO), "FillExtrusionPermutationUBO"}, + UniformBlockInfo{9, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp b/src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp new file mode 100644 index 000000000..70e90f5f9 --- /dev/null +++ b/src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp @@ -0,0 +1,14 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array + ShaderSource::attributes = {}; +const std::array + ShaderSource::uniforms = {}; +const std::array + ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/heatmap.cpp b/src/mbgl/shaders/mtl/heatmap.cpp new file mode 100644 index 000000000..b6a42f3f4 --- /dev/null +++ b/src/mbgl/shaders/mtl/heatmap.cpp @@ -0,0 +1,21 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Float2, 1, "a_weight"}, + AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_radius"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{3, true, false, sizeof(HeatmapDrawableUBO), "HeatmapDrawableUBO"}, + UniformBlockInfo{4, true, true, sizeof(HeatmapEvaluatedPropsUBO), "HeatmapEvaluatedPropsUBO"}, + UniformBlockInfo{5, true, false, sizeof(HeatmapInterpolateUBO), "HeatmapInterpolateUBO"}, + UniformBlockInfo{6, true, true, sizeof(HeatmapPermutationUBO), "HeatmapPermutationUBO"}, + UniformBlockInfo{7, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = {}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/heatmap_texture.cpp b/src/mbgl/shaders/mtl/heatmap_texture.cpp new file mode 100644 index 000000000..6d9546363 --- /dev/null +++ b/src/mbgl/shaders/mtl/heatmap_texture.cpp @@ -0,0 +1,20 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = + { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, +}; +const std::array ShaderSource::uniforms = + { + UniformBlockInfo{1, true, true, sizeof(HeatmapTextureDrawableUBO), "HeatmapTextureDrawableUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image"}, + TextureInfo{1, "u_color_ramp"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/hillshade.cpp b/src/mbgl/shaders/mtl/hillshade.cpp new file mode 100644 index 000000000..a7b0f32a5 --- /dev/null +++ b/src/mbgl/shaders/mtl/hillshade.cpp @@ -0,0 +1,19 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{2, true, true, sizeof(HillshadeDrawableUBO), "HillshadeDrawableUBO"}, + UniformBlockInfo{3, false, true, sizeof(HillshadeEvaluatedPropsUBO), "HillshadeEvaluatedPropsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/hillshade_prepare.cpp b/src/mbgl/shaders/mtl/hillshade_prepare.cpp new file mode 100644 index 000000000..6ae470498 --- /dev/null +++ b/src/mbgl/shaders/mtl/hillshade_prepare.cpp @@ -0,0 +1,20 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array + ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, +}; +const std::array + ShaderSource::uniforms = { + UniformBlockInfo{2, true, true, sizeof(HillshadePrepareDrawableUBO), "HillshadePrepareDrawableUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/line.cpp b/src/mbgl/shaders/mtl/line.cpp new file mode 100644 index 000000000..514cf2f55 --- /dev/null +++ b/src/mbgl/shaders/mtl/line.cpp @@ -0,0 +1,49 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"}, + AttributeInfo{1, gfx::AttributeDataType::UByte4, 1, "a_data"}, + AttributeInfo{2, gfx::AttributeDataType::Float4, 1, "a_color"}, + AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_blur"}, + AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_opacity"}, + AttributeInfo{5, gfx::AttributeDataType::Float2, 1, "a_gapwidth"}, + AttributeInfo{6, gfx::AttributeDataType::Float2, 1, "a_offset"}, + AttributeInfo{7, gfx::AttributeDataType::Float2, 1, "a_width"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{8, true, true, sizeof(LineUBO), "LineUBO"}, + UniformBlockInfo{9, true, false, sizeof(LinePropertiesUBO), "LinePropertiesUBO"}, + UniformBlockInfo{10, true, false, sizeof(LineInterpolationUBO), "LineInterpolationUBO"}, + UniformBlockInfo{11, true, true, sizeof(LinePermutationUBO), "LinePermutationUBO"}, + UniformBlockInfo{12, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = {}; + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"}, + AttributeInfo{1, gfx::AttributeDataType::UByte4, 1, "a_data"}, + AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_blur"}, + AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, + AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_gapwidth"}, + AttributeInfo{5, gfx::AttributeDataType::Float2, 1, "a_offset"}, + AttributeInfo{6, gfx::AttributeDataType::Float2, 1, "a_width"}, + AttributeInfo{7, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"}, + AttributeInfo{8, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{9, true, true, sizeof(LinePatternUBO), "LinePatternUBO"}, + UniformBlockInfo{10, true, false, sizeof(LinePatternPropertiesUBO), "LinePatternPropertiesUBO"}, + UniformBlockInfo{11, true, false, sizeof(LinePatternInterpolationUBO), "LinePatternInterpolationUBO"}, + UniformBlockInfo{12, true, false, sizeof(LinePatternTilePropertiesUBO), "LinePatternTilePropertiesUBO"}, + UniformBlockInfo{13, true, true, sizeof(LinePermutationUBO), "LinePermutationUBO"}, + UniformBlockInfo{14, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/line_gradient.cpp b/src/mbgl/shaders/mtl/line_gradient.cpp new file mode 100644 index 000000000..fc980003e --- /dev/null +++ b/src/mbgl/shaders/mtl/line_gradient.cpp @@ -0,0 +1,27 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"}, + AttributeInfo{1, gfx::AttributeDataType::UByte4, 1, "a_data"}, + AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_blur"}, + AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_opacity"}, + AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_gapwidth"}, + AttributeInfo{5, gfx::AttributeDataType::Float2, 1, "a_offset"}, + AttributeInfo{6, gfx::AttributeDataType::Float2, 1, "a_width"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{7, true, true, sizeof(LineGradientUBO), "LineGradientUBO"}, + UniformBlockInfo{8, true, false, sizeof(LineGradientPropertiesUBO), "LineGradientPropertiesUBO"}, + UniformBlockInfo{9, true, false, sizeof(LineGradientInterpolationUBO), "LineGradientInterpolationUBO"}, + UniformBlockInfo{10, true, true, sizeof(LinePermutationUBO), "LinePermutationUBO"}, + UniformBlockInfo{11, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/raster.cpp b/src/mbgl/shaders/mtl/raster.cpp new file mode 100644 index 000000000..c0ba80422 --- /dev/null +++ b/src/mbgl/shaders/mtl/raster.cpp @@ -0,0 +1,19 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{2, true, true, sizeof(RasterDrawableUBO), "RasterDrawableUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_image0"}, + TextureInfo{1, "u_image1"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/shader_program.cpp b/src/mbgl/shaders/mtl/shader_program.cpp index bb07378ae..545b9c75e 100644 --- a/src/mbgl/shaders/mtl/shader_program.cpp +++ b/src/mbgl/shaders/mtl/shader_program.cpp @@ -22,8 +22,32 @@ using namespace std::string_literals; namespace mbgl { -namespace mtl { +shaders::AttributeInfo::AttributeInfo(std::size_t index_, + gfx::AttributeDataType dataType_, + std::size_t count_, + std::string_view name_) + : index(index_), + dataType(dataType_), + count(count_), + name(name_), + nameID(StringIndexer::get(name_)) {} + +shaders::UniformBlockInfo::UniformBlockInfo( + std::size_t index_, bool vertex_, bool fragment_, std::size_t size_, std::string_view name_) + : index(index_), + vertex(vertex_), + fragment(fragment_), + size(size_), + name(name_), + nameID(StringIndexer::get(name_)) {} + +shaders::TextureInfo::TextureInfo(std::size_t index_, std::string_view name_) + : index(index_), + name(name_), + nameID(StringIndexer::get(name_)) {} + +namespace mtl { namespace { MTL::BlendOperation metalBlendOperation(const gfx::ColorBlendEquationType& colorBlend) { switch (colorBlend) { diff --git a/src/mbgl/shaders/mtl/symbol_icon.cpp b/src/mbgl/shaders/mtl/symbol_icon.cpp new file mode 100644 index 000000000..7a2b8242e --- /dev/null +++ b/src/mbgl/shaders/mtl/symbol_icon.cpp @@ -0,0 +1,30 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = { + // always attributes + AttributeInfo{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"}, + AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_data"}, + AttributeInfo{2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"}, + AttributeInfo{3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"}, + AttributeInfo{4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"}, + + // sometimes uniforms + AttributeInfo{5, gfx::AttributeDataType::Float, 1, "a_opacity"}, +}; +const std::array ShaderSource::uniforms = { + UniformBlockInfo{8, true, true, sizeof(SymbolDrawableUBO), "SymbolDrawableUBO"}, + UniformBlockInfo{9, true, true, sizeof(SymbolDrawablePaintUBO), "SymbolDrawablePaintUBO"}, + UniformBlockInfo{10, true, false, sizeof(SymbolDrawableTilePropsUBO), "SymbolDrawableTilePropsUBO"}, + UniformBlockInfo{11, true, false, sizeof(SymbolDrawableInterpolateUBO), "SymbolDrawableInterpolateUBO"}, + UniformBlockInfo{12, true, true, sizeof(SymbolPermutationUBO), "SymbolPermutationUBO"}, + UniformBlockInfo{13, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_texture"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/symbol_sdf.cpp b/src/mbgl/shaders/mtl/symbol_sdf.cpp new file mode 100644 index 000000000..b1cf6d428 --- /dev/null +++ b/src/mbgl/shaders/mtl/symbol_sdf.cpp @@ -0,0 +1,36 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array ShaderSource::attributes = + { + // always attributes + AttributeInfo{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"}, + AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_data"}, + AttributeInfo{2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"}, + AttributeInfo{3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"}, + AttributeInfo{4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"}, + + // sometimes uniforms + AttributeInfo{5, gfx::AttributeDataType::Float4, 1, "a_fill_color"}, + AttributeInfo{6, gfx::AttributeDataType::Float4, 1, "a_halo_color"}, + AttributeInfo{7, gfx::AttributeDataType::Float, 1, "a_opacity"}, + AttributeInfo{8, gfx::AttributeDataType::Float, 1, "a_halo_width"}, + AttributeInfo{9, gfx::AttributeDataType::Float, 1, "a_halo_blur"}, +}; +const std::array ShaderSource::uniforms = + { + UniformBlockInfo{10, true, true, sizeof(SymbolDrawableUBO), "SymbolDrawableUBO"}, + UniformBlockInfo{11, true, false, sizeof(SymbolDrawablePaintUBO), "SymbolDrawablePaintUBO"}, + UniformBlockInfo{12, true, true, sizeof(SymbolDrawableTilePropsUBO), "SymbolDrawableTilePropsUBO"}, + UniformBlockInfo{13, true, false, sizeof(SymbolDrawableInterpolateUBO), "SymbolDrawableInterpolateUBO"}, + UniformBlockInfo{14, true, true, sizeof(SymbolPermutationUBO), "SymbolPermutationUBO"}, + UniformBlockInfo{15, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_texture"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/shaders/mtl/symbol_text_and_icon.cpp b/src/mbgl/shaders/mtl/symbol_text_and_icon.cpp new file mode 100644 index 000000000..d735e1862 --- /dev/null +++ b/src/mbgl/shaders/mtl/symbol_text_and_icon.cpp @@ -0,0 +1,36 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array + ShaderSource::attributes = { + // always attributes + AttributeInfo{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"}, + AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_data"}, + AttributeInfo{2, gfx::AttributeDataType::Float3, 1, "a_projected_pos"}, + AttributeInfo{3, gfx::AttributeDataType::Float, 1, "a_fade_opacity"}, + + // sometimes uniforms + AttributeInfo{4, gfx::AttributeDataType::Float4, 1, "a_fill_color"}, + AttributeInfo{5, gfx::AttributeDataType::Float4, 1, "a_halo_color"}, + AttributeInfo{6, gfx::AttributeDataType::Float, 1, "a_opacity"}, + AttributeInfo{7, gfx::AttributeDataType::Float, 1, "a_halo_width"}, + AttributeInfo{8, gfx::AttributeDataType::Float, 1, "a_halo_blur"}, +}; +const std::array + ShaderSource::uniforms = { + UniformBlockInfo{9, true, true, sizeof(SymbolDrawableUBO), "SymbolDrawableUBO"}, + UniformBlockInfo{10, true, false, sizeof(SymbolDrawablePaintUBO), "SymbolDrawablePaintUBO"}, + UniformBlockInfo{11, true, true, sizeof(SymbolDrawableTilePropsUBO), "SymbolDrawableTilePropsUBO"}, + UniformBlockInfo{12, true, false, sizeof(SymbolDrawableInterpolateUBO), "SymbolDrawableInterpolateUBO"}, + UniformBlockInfo{13, true, true, sizeof(SymbolPermutationUBO), "SymbolPermutationUBO"}, + UniformBlockInfo{14, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, "u_texture"}, + TextureInfo{1, "u_texture_icon"}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/util/hash.hpp b/src/mbgl/util/hash.hpp index cb92fe9be..299d018dd 100644 --- a/src/mbgl/util/hash.hpp +++ b/src/mbgl/util/hash.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace mbgl { namespace util { @@ -19,5 +20,24 @@ std::size_t hash(Args&&... args) { return seed; } +namespace detail { +template +using TIterVal = std::enable_if_t::value, typename TIter::value_type>; +} // namespace detail + +/// Generate a hash key from a collection of integer values which doesn't depend on their order. +/// Adapted from https://stackoverflow.com/a/76993810/135138 +/// Default factor prime value from 64-bit FNV hash. +template , TKey factor = 1099511628211LL> +TKey order_independent_hash(TIter cur, const TIter end) { + detail::TIterVal sum = 0, product = 1; + for (; cur != end; ++cur) { + const auto& value = *cur; + sum += value; + product *= (1 + value) * factor; + } + return sum ^ product; +} + } // namespace util } // namespace mbgl diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c12e11f13..bad61b04c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -88,6 +88,7 @@ add_library( ${PROJECT_SOURCE_DIR}/test/util/dtoa.test.cpp ${PROJECT_SOURCE_DIR}/test/util/geo.test.cpp ${PROJECT_SOURCE_DIR}/test/util/grid_index.test.cpp + ${PROJECT_SOURCE_DIR}/test/util/hash.test.cpp ${PROJECT_SOURCE_DIR}/test/util/http_timeout.test.cpp ${PROJECT_SOURCE_DIR}/test/util/image.test.cpp ${PROJECT_SOURCE_DIR}/test/util/mapbox.test.cpp @@ -236,4 +237,4 @@ if (CMAKE_SYSTEM_NAME STREQUAL Linux) mbgl-test PRIVATE USE_CPP_TEST_SERVER ) -endif() \ No newline at end of file +endif() diff --git a/test/util/hash.test.cpp b/test/util/hash.test.cpp new file mode 100644 index 000000000..203dacd39 --- /dev/null +++ b/test/util/hash.test.cpp @@ -0,0 +1,54 @@ +#include + +#include + +#include +#include +#include +#include +#include +#include + +using namespace mbgl; + +TEST(OrderIndependentHash, Permutations) { + // Try collections of up to this many elements + constexpr int maxSize = 6; + // Try this many different sets of values for each size + constexpr int iterations = 10; + // Use values up to this large + constexpr size_t maxVal = 10; + + std::seed_seq seed{0xf00dLL}; + std::default_random_engine engine(seed); + std::uniform_int_distribution distribution(0, maxVal); + + for (int curSize = 1; curSize <= maxSize; ++curSize) { + for (int ii = 0; ii < iterations; ++ii) { + // Generate `curSize` random values + std::vector values; + for (int jj = 0; jj < curSize; ++jj) { + values.push_back(distribution(engine)); + } + + // Generate the hash for each permutation, comparing subsequent values to the first one. + bool isFirst = true; + size_t initialValue = 0; + do { + const auto curValue = util::order_independent_hash(values.begin(), values.end()); + if (isFirst || curValue != initialValue) { + for (auto v : values) { + std::cout << v << ","; + } + std::cout << " - " << std::hex << curValue << std::endl; + } + if (isFirst) { + initialValue = curValue; + isFirst = false; + } else { + EXPECT_EQ(initialValue, curValue); + } + } while (std::next_permutation(values.begin(), values.end())); + } + } +}