From 76469a0c2227927f03a15fb95b3a20f34becc78c Mon Sep 17 00:00:00 2001 From: Stefan Karschti Date: Fri, 15 Sep 2023 17:30:07 +0300 Subject: [PATCH] Drawable performance fixes (2) (#1610) Co-authored-by: Tim Sylvester Co-authored-by: Bart Louwers --- CMakeLists.txt | 2 + bazel/core.bzl | 2 + include/mbgl/gfx/drawable_atlases_tweaker.hpp | 13 +- include/mbgl/gfx/drawable_builder.hpp | 5 +- include/mbgl/gfx/uniform_block.hpp | 14 +- include/mbgl/gfx/uniform_buffer.hpp | 20 +- include/mbgl/gfx/vertex_attribute.hpp | 57 ++-- include/mbgl/gl/drawable_gl.hpp | 3 +- include/mbgl/gl/uniform_block_gl.hpp | 3 +- include/mbgl/gl/uniform_buffer_gl.hpp | 3 +- include/mbgl/gl/vertex_attribute_gl.hpp | 6 +- include/mbgl/map/map_observer.hpp | 1 + include/mbgl/mtl/context.hpp | 2 + include/mbgl/mtl/drawable.hpp | 2 +- include/mbgl/mtl/uniform_block.hpp | 3 +- include/mbgl/mtl/uniform_buffer.hpp | 3 +- include/mbgl/mtl/vertex_attribute.hpp | 3 +- include/mbgl/renderer/layer_tweaker.hpp | 3 + include/mbgl/renderer/renderer_observer.hpp | 5 + include/mbgl/shaders/gl/shader_program_gl.hpp | 13 +- include/mbgl/shaders/mtl/shader_program.hpp | 6 +- include/mbgl/shaders/shader_program_base.hpp | 7 +- include/mbgl/util/string_indexer.hpp | 46 +++ .../src/cpp/android_renderer_frontend.cpp | 8 +- .../default/src/mbgl/map/map_snapshotter.cpp | 18 +- platform/ios/app/MBXViewController.m | 2 +- .../ios/benchmark/MBXBenchViewController.mm | 47 +++- platform/ios/benchmark/locations.cpp | 1 + platform/ios/src/MLNMapView+Impl.mm | 2 +- platform/ios/src/MLNMapView.mm | 9 +- platform/ios/src/MLNMapViewDelegate.h | 16 ++ platform/ios/src/MLNMapView_Private.h | 3 +- .../MLNMapViewDelegateIntegrationTests.swift | 2 + platform/macos/src/MLNMapViewDelegate.h | 16 ++ .../MLNMapViewDelegateIntegrationTests.swift | 2 + platform/qt/src/utils/renderer_observer.hpp | 9 +- src/mbgl/gfx/context.hpp | 12 + src/mbgl/gfx/drawable_atlases_tweaker.cpp | 4 +- src/mbgl/gfx/drawable_builder.cpp | 3 +- src/mbgl/gfx/uniform_block.cpp | 11 +- src/mbgl/gfx/uniform_buffer.cpp | 25 +- src/mbgl/gfx/vertex_attribute.cpp | 20 +- src/mbgl/gl/context.cpp | 10 + src/mbgl/gl/context.hpp | 2 + src/mbgl/gl/drawable_gl.cpp | 10 +- src/mbgl/gl/drawable_gl_builder.cpp | 2 +- src/mbgl/gl/drawable_gl_impl.hpp | 3 +- src/mbgl/gl/upload_pass.cpp | 17 +- src/mbgl/gl/vertex_attribute_gl.cpp | 13 + src/mbgl/map/map_impl.cpp | 8 +- src/mbgl/map/map_impl.hpp | 2 +- src/mbgl/mtl/context.cpp | 10 + src/mbgl/mtl/drawable.cpp | 15 +- src/mbgl/mtl/drawable_builder.cpp | 2 +- src/mbgl/mtl/drawable_impl.hpp | 3 +- src/mbgl/mtl/upload_pass.cpp | 2 +- src/mbgl/renderer/layer_tweaker.cpp | 5 + .../layers/background_layer_tweaker.cpp | 17 +- .../renderer/layers/circle_layer_tweaker.cpp | 19 +- .../layers/collision_layer_tweaker.cpp | 11 +- .../layers/collision_layer_tweaker.hpp | 7 +- .../layers/fill_extrusion_layer_tweaker.cpp | 16 +- .../layers/fill_extrusion_layer_tweaker.hpp | 5 +- .../renderer/layers/fill_layer_tweaker.cpp | 72 +++-- .../renderer/layers/fill_layer_tweaker.hpp | 5 + .../renderer/layers/heatmap_layer_tweaker.cpp | 9 +- .../layers/heatmap_texture_layer_tweaker.cpp | 5 +- .../layers/hillshade_layer_tweaker.cpp | 9 +- .../hillshade_prepare_layer_tweaker.cpp | 5 +- .../renderer/layers/line_layer_tweaker.cpp | 45 ++- .../renderer/layers/raster_layer_tweaker.cpp | 8 +- .../renderer/layers/render_circle_layer.cpp | 11 +- .../layers/render_fill_extrusion_layer.cpp | 22 +- .../renderer/layers/render_fill_layer.cpp | 82 +++--- .../renderer/layers/render_heatmap_layer.cpp | 19 +- .../layers/render_hillshade_layer.cpp | 19 +- .../renderer/layers/render_line_layer.cpp | 56 ++-- .../renderer/layers/render_raster_layer.cpp | 18 +- .../renderer/layers/render_symbol_layer.cpp | 261 ++++++++++-------- .../renderer/layers/symbol_layer_tweaker.cpp | 32 ++- .../renderer/layers/symbol_layer_tweaker.hpp | 11 +- src/mbgl/renderer/render_orchestrator.cpp | 10 +- src/mbgl/renderer/render_tree.hpp | 10 +- src/mbgl/renderer/renderer_impl.cpp | 3 +- .../renderer/sources/render_tile_source.cpp | 15 +- src/mbgl/renderer/tile_layer_group.cpp | 3 +- src/mbgl/shaders/gl/shader_program_gl.cpp | 52 +++- src/mbgl/shaders/mtl/shader_program.cpp | 20 +- src/mbgl/style/paint_property.hpp | 14 + src/mbgl/util/string_indexer.cpp | 70 +++++ test/CMakeLists.txt | 1 + test/util/string_indexer.test.cpp | 49 ++++ 92 files changed, 1051 insertions(+), 496 deletions(-) create mode 100644 include/mbgl/util/string_indexer.hpp create mode 100644 src/mbgl/util/string_indexer.cpp create mode 100644 test/util/string_indexer.test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7114ef413..4e624f3fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -407,6 +407,7 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/util/run_loop.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/size.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/string.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/util/string_indexer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/tile_server_options.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/thread.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/util/tileset.hpp @@ -949,6 +950,7 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/util/stopwatch.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/stopwatch.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/string.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/util/string_indexer.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/thread.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/thread_local.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/thread_pool.cpp diff --git a/bazel/core.bzl b/bazel/core.bzl index e05ec0354..c26bf12a4 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -620,6 +620,7 @@ MLN_CORE_SOURCE = [ "src/mbgl/util/stopwatch.cpp", "src/mbgl/util/stopwatch.hpp", "src/mbgl/util/string.cpp", + "src/mbgl/util/string_indexer.cpp", "src/mbgl/util/thread.cpp", "src/mbgl/util/thread_local.hpp", "src/mbgl/util/thread_pool.cpp", @@ -824,6 +825,7 @@ MLN_CORE_HEADERS = [ "include/mbgl/util/run_loop.hpp", "include/mbgl/util/size.hpp", "include/mbgl/util/string.hpp", + "include/mbgl/util/string_indexer.hpp", "include/mbgl/util/tile_server_options.hpp", "include/mbgl/util/thread.hpp", "include/mbgl/util/tileset.hpp", diff --git a/include/mbgl/gfx/drawable_atlases_tweaker.hpp b/include/mbgl/gfx/drawable_atlases_tweaker.hpp index 1f9f991aa..277622b4e 100644 --- a/include/mbgl/gfx/drawable_atlases_tweaker.hpp +++ b/include/mbgl/gfx/drawable_atlases_tweaker.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -22,16 +23,16 @@ class Drawable; class DrawableAtlasesTweaker : public gfx::DrawableTweaker { public: DrawableAtlasesTweaker(TileAtlasTexturesPtr atlases_, - std::string iconName_, - std::string glyphName_, + const StringIdentity iconNameId_, + const StringIdentity glyphNameId_, bool isText_, const bool sdfIcons_, const style::AlignmentType rotationAlignment_, const bool iconScaled_, const bool textSizeIsZoomConstant_) : atlases(std::move(atlases_)), - iconName(std::move(iconName_)), - glyphName(std::move(glyphName_)), + iconNameId(iconNameId_), + glyphNameId(glyphNameId_), isText(isText_), sdfIcons(sdfIcons_), rotationAlignment(rotationAlignment_), @@ -47,8 +48,8 @@ protected: void setupTextures(Drawable&, const bool); TileAtlasTexturesPtr atlases; - std::string iconName; - std::string glyphName; + StringIdentity iconNameId; + StringIdentity glyphNameId; bool isText; const bool sdfIcons; diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index 51111a649..b13249425 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -137,7 +138,7 @@ public: void setDrawableName(std::string value) { drawableName = std::move(value); } /// The attribute names for vertex/position attributes - void setVertexAttrName(std::string value) { vertexAttrName = std::move(value); } + void setVertexAttrNameId(const StringIdentity id) { vertexAttrNameId = id; } /// @brief Attach the given texture at the given sampler location. /// @param texture Texture2D instance @@ -203,7 +204,7 @@ protected: protected: std::string name; std::string drawableName; - std::string vertexAttrName; + StringIdentity vertexAttrNameId; mbgl::RenderPass renderPass; bool enabled = true; bool enableColor = true; diff --git a/include/mbgl/gfx/uniform_block.hpp b/include/mbgl/gfx/uniform_block.hpp index 256b8e311..e96941a04 100644 --- a/include/mbgl/gfx/uniform_block.hpp +++ b/include/mbgl/gfx/uniform_block.hpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace mbgl { namespace gfx { @@ -58,11 +59,10 @@ protected: /// Stores a collection of uniform blocks by name class UniformBlockArray { public: - using UniformBlockMap = std::unordered_map>; + using UniformBlockMap = std::unordered_map>; /// @brief Constructor - /// @param initCapacity initial collection capacity - UniformBlockArray(int initCapacity = 10); + UniformBlockArray() = default; /// @brief Move constructor UniformBlockArray(UniformBlockArray&&); @@ -81,14 +81,14 @@ public: /// @brief Get an uniform block element. /// @return Pointer to the element on success, or null if the uniform block doesn't exists. - const std::unique_ptr& get(const std::string& name) const; + const std::unique_ptr& get(const StringIdentity id) const; /// @brief Add a new uniform block element. /// @param name /// @param index /// @param size /// @return Pointer to the new element on success, or null if the uniform block already exists. - const std::unique_ptr& add(std::string name, int index, std::size_t size); + const std::unique_ptr& add(const StringIdentity id, int index, std::size_t size); /// @brief Move assignment operator UniformBlockArray& operator=(UniformBlockArray&&); @@ -97,8 +97,8 @@ public: UniformBlockArray& operator=(const UniformBlockArray&); protected: - const std::unique_ptr& add(std::string name, std::unique_ptr&& uniformBlock) { - const auto result = uniformBlockMap.insert(std::make_pair(std::move(name), std::unique_ptr())); + const std::unique_ptr& add(const StringIdentity id, std::unique_ptr&& uniformBlock) { + const auto result = uniformBlockMap.insert(std::make_pair(id, std::unique_ptr())); if (result.second) { result.first->second = std::move(uniformBlock); return result.first->second; diff --git a/include/mbgl/gfx/uniform_buffer.hpp b/include/mbgl/gfx/uniform_buffer.hpp index 38556a188..5f29dd5ca 100644 --- a/include/mbgl/gfx/uniform_buffer.hpp +++ b/include/mbgl/gfx/uniform_buffer.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include #include @@ -44,9 +46,9 @@ protected: /// Stores a collection of uniform buffers by name class UniformBufferArray { public: - using UniformBufferMap = std::unordered_map>; + using UniformBufferMap = std::unordered_map>; - UniformBufferArray(int initCapacity = 10); + UniformBufferArray() = default; UniformBufferArray(UniformBufferArray&&); // Would need to use the virtual assignment operator UniformBufferArray(const UniformBufferArray&) = delete; @@ -57,27 +59,27 @@ public: /// Get an uniform buffer element. /// Returns a pointer to the element on success, or null if the uniform buffer doesn't exists. - const std::shared_ptr& get(std::string_view name) const; + const std::shared_ptr& get(const StringIdentity id) const; /// Add a new uniform buffer element or replace the existing one. - const std::shared_ptr& addOrReplace(std::string_view name, + const std::shared_ptr& addOrReplace(const StringIdentity id, std::shared_ptr uniformBuffer); /// Create and add a new buffer or update an existing one - void createOrUpdate(std::string_view name, const std::vector& data, gfx::Context&); - void createOrUpdate(std::string_view name, const void* data, std::size_t size, gfx::Context&); + void createOrUpdate(const StringIdentity id, const std::vector& data, gfx::Context&); + void createOrUpdate(const StringIdentity id, const void* data, std::size_t size, gfx::Context&); template - std::enable_if_t> createOrUpdate(std::string_view name, + std::enable_if_t> createOrUpdate(const StringIdentity id, const T* data, gfx::Context& context) { - createOrUpdate(name, data, sizeof(T), context); + createOrUpdate(id, data, sizeof(T), context); } UniformBufferArray& operator=(UniformBufferArray&&); UniformBufferArray& operator=(const UniformBufferArray&); protected: - const std::shared_ptr& add(const std::string_view name, std::shared_ptr&&); + const std::shared_ptr& add(const StringIdentity id, std::shared_ptr&&); virtual std::unique_ptr copy(const UniformBuffer&) = 0; diff --git a/include/mbgl/gfx/vertex_attribute.hpp b/include/mbgl/gfx/vertex_attribute.hpp index 34eb4bb77..17c0c53e4 100644 --- a/include/mbgl/gfx/vertex_attribute.hpp +++ b/include/mbgl/gfx/vertex_attribute.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -271,9 +272,9 @@ protected: /// Stores a collection of vertex attributes by name class VertexAttributeArray { public: - using AttributeMap = std::unordered_map>; + using AttributeMap = std::unordered_map>; - VertexAttributeArray(int initCapacity = 10); + VertexAttributeArray() = default; VertexAttributeArray(VertexAttributeArray&&); VertexAttributeArray(const VertexAttributeArray&) = delete; // Would need to use the virtual assignment operator virtual ~VertexAttributeArray() = default; @@ -290,15 +291,15 @@ public: /// Add a new attribute element. /// Returns a pointer to the new element on success, or null if the attribute already exists. /// The result is valid only until the next non-const method call on this class. - const UniqueVertexAttribute& get(const std::string& name) const; + const std::unique_ptr& get(const StringIdentity id) const; /// Add a new attribute element. /// Returns a pointer to the new element on success, or null if the attribute already exists. /// The result is valid only until the next non-const method call on this class. - const UniqueVertexAttribute& add(std::string name, - int index = -1, - AttributeDataType = AttributeDataType::Invalid, - std::size_t count = 1); + const std::unique_ptr& add(const StringIdentity id, + int index = -1, + AttributeDataType = AttributeDataType::Invalid, + std::size_t count = 1); /// Add a new attribute element if it doesn't already exist. /// Returns a pointer to the new element on success, or null if the type or count conflict with an existing entry. @@ -306,22 +307,22 @@ public: /// @param index index to match, or -1 for any /// @param type type to match, or `Invalid` for any /// @param count type to match, or 0 for any - const UniqueVertexAttribute& getOrAdd(std::string name, - int index = -1, - AttributeDataType type = AttributeDataType::Invalid, - std::size_t count = 0); + const std::unique_ptr& getOrAdd(const StringIdentity id, + int index = -1, + AttributeDataType type = AttributeDataType::Invalid, + std::size_t count = 0); // Set a value if the element is present template - bool set(const std::string& name, std::size_t i, T value) { - if (const auto& item = get(name)) { + bool set(const StringIdentity id, std::size_t i, T value) { + if (const auto& item = get(id)) { return item->set(i, value); } return false; } /// Indicates whether any values have changed - bool isDirty() const { + virtual bool isDirty() const { return std::any_of( attrs.begin(), attrs.end(), [](const auto& kv) { return kv.second && kv.second->isDirty(); }); } @@ -330,7 +331,7 @@ public: void clear(); /// Do something with each attribute - void visitAttributes(const std::function& f) { + void visitAttributes(const std::function& f) { std::for_each(attrs.begin(), attrs.end(), [&](const auto& kv) { if (kv.second) { f(kv.first, *kv.second); @@ -339,7 +340,7 @@ public: } /// Do something with each attribute - void visitAttributes(const std::function& f) const { + void visitAttributes(const std::function& f) const { std::for_each(attrs.begin(), attrs.end(), [&](const auto& kv) { if (kv.second) { f(kv.first, *kv.second); @@ -347,7 +348,8 @@ public: }); } - using ResolveDelegate = std::function; + using ResolveDelegate = + std::function&)>; /// Call the provided delegate with each value, providing the override if one exists. void resolve(const VertexAttributeArray& overrides, ResolveDelegate) const; @@ -369,26 +371,29 @@ public: ( [&](const auto& attributeNames) { for (std::size_t attrIndex = 0; attrIndex < attributeNames.size(); ++attrIndex) { - const auto& attributeName = std::string(attributeNames[attrIndex]); + const auto& attributeName = attributeNames[attrIndex]; if (auto& binder = binders.template get()) { using Attribute = typename DataDrivenPaintProperty::Attribute; using Type = typename Attribute::Type; // ::mbgl::gfx::AttributeType using InterpType = ZoomInterpolatedAttributeType; -#if !defined(NDEBUG) - using Value = typename Type::Value; // std::array - using InterpValue = typename InterpType::Value; // std::array -#endif const auto vertexCount = binder->getVertexCount(); const auto isConstant = evaluated.template get().isConstant(); if (vertexCount > 0 && !isConstant) { - if (auto& attr = getOrAdd("a_" + attributeName)) { + 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()); const bool isInterpolated = binder->isInterpolated(); const auto dataType = isInterpolated ? InterpType::DataType : Type::DataType; - assert(rawSize == - static_cast(isInterpolated ? sizeof(InterpValue) : sizeof(Value))); + assert(rawSize == static_cast(isInterpolated + ? sizeof(typename InterpType::Value) + : sizeof(typename Type::Value))); assert(sharedVector->getRawCount() == vertexCount); attr->setSharedRawData(std::move(sharedVector), 0, 0, rawSize, dataType); } else { @@ -418,7 +423,7 @@ public: } protected: - const UniqueVertexAttribute& add(std::string name, std::unique_ptr&&); + const UniqueVertexAttribute& add(const StringIdentity id, std::unique_ptr&&); virtual UniqueVertexAttribute create(int index, AttributeDataType dataType, std::size_t count) const { return std::make_unique(index, dataType, count, count); diff --git a/include/mbgl/gl/drawable_gl.hpp b/include/mbgl/gl/drawable_gl.hpp index bf7a97fe5..fb90877bc 100644 --- a/include/mbgl/gl/drawable_gl.hpp +++ b/include/mbgl/gl/drawable_gl.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -49,7 +50,7 @@ public: const gfx::UniformBufferArray& getUniformBuffers() const override; gfx::UniformBufferArray& mutableUniformBuffers() override; - void setVertexAttrName(std::string); + void setVertexAttrNameId(const StringIdentity id); void upload(gfx::UploadPass&); diff --git a/include/mbgl/gl/uniform_block_gl.hpp b/include/mbgl/gl/uniform_block_gl.hpp index f8dc39a4a..7776461dc 100644 --- a/include/mbgl/gl/uniform_block_gl.hpp +++ b/include/mbgl/gl/uniform_block_gl.hpp @@ -28,8 +28,7 @@ public: /// Stores a collection of uniform blocks by name class UniformBlockArrayGL final : public gfx::UniformBlockArray { public: - UniformBlockArrayGL(int initCapacity = 10) - : UniformBlockArray(initCapacity) {} + UniformBlockArrayGL() = default; UniformBlockArrayGL(UniformBlockArrayGL&& other) : UniformBlockArray(std::move(other)) {} UniformBlockArrayGL(const UniformBlockArrayGL&) = delete; diff --git a/include/mbgl/gl/uniform_buffer_gl.hpp b/include/mbgl/gl/uniform_buffer_gl.hpp index a97487892..5edfaa2f3 100644 --- a/include/mbgl/gl/uniform_buffer_gl.hpp +++ b/include/mbgl/gl/uniform_buffer_gl.hpp @@ -26,8 +26,7 @@ protected: /// Stores a collection of uniform buffers by name class UniformBufferArrayGL final : public gfx::UniformBufferArray { public: - UniformBufferArrayGL(int initCapacity = 10) - : UniformBufferArray(initCapacity) {} + UniformBufferArrayGL() = default; UniformBufferArrayGL(UniformBufferArrayGL&& other) : UniformBufferArray(std::move(other)) {} UniformBufferArrayGL(const UniformBufferArrayGL&) = delete; diff --git a/include/mbgl/gl/vertex_attribute_gl.hpp b/include/mbgl/gl/vertex_attribute_gl.hpp index 581e6e2cb..e0b9b2a00 100644 --- a/include/mbgl/gl/vertex_attribute_gl.hpp +++ b/include/mbgl/gl/vertex_attribute_gl.hpp @@ -53,8 +53,7 @@ private: /// Stores a collection of vertex attributes by name class VertexAttributeArrayGL final : public gfx::VertexAttributeArray { public: - VertexAttributeArrayGL(int initCapacity = 10) - : VertexAttributeArray(initCapacity) {} + VertexAttributeArrayGL() = default; VertexAttributeArrayGL(VertexAttributeArrayGL&& other) : VertexAttributeArray(std::move(other)) {} @@ -73,6 +72,9 @@ public: return newAttrs; } + /// Indicates whether any values have changed + bool isDirty() const override; + private: std::unique_ptr create(int index, gfx::AttributeDataType dataType, diff --git a/include/mbgl/map/map_observer.hpp b/include/mbgl/map/map_observer.hpp index 675b86c05..0ebed53d1 100644 --- a/include/mbgl/map/map_observer.hpp +++ b/include/mbgl/map/map_observer.hpp @@ -42,6 +42,7 @@ public: RenderMode mode; bool needsRepaint; // In continous mode, shows that there are ongoig transitions. bool placementChanged; + double frameTime; }; virtual void onCameraWillChange(CameraChangeMode) {} diff --git a/include/mbgl/mtl/context.hpp b/include/mbgl/mtl/context.hpp index 5e923338b..a310ab003 100644 --- a/include/mbgl/mtl/context.hpp +++ b/include/mbgl/mtl/context.hpp @@ -113,6 +113,8 @@ public: void clearStencilBuffer(int32_t) override; + virtual bool emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr&, const void* data, std::size_t size); + private: RendererBackend& backend; bool cleanupOnDestruction = true; diff --git a/include/mbgl/mtl/drawable.hpp b/include/mbgl/mtl/drawable.hpp index 00fea875f..0d2c7f64c 100644 --- a/include/mbgl/mtl/drawable.hpp +++ b/include/mbgl/mtl/drawable.hpp @@ -49,7 +49,7 @@ public: const gfx::UniformBufferArray& getUniformBuffers() const override; gfx::UniformBufferArray& mutableUniformBuffers() override; - void setVertexAttrName(std::string); + void setVertexAttrNameId(const StringIdentity); void upload(gfx::UploadPass&); diff --git a/include/mbgl/mtl/uniform_block.hpp b/include/mbgl/mtl/uniform_block.hpp index 22f312497..50f43113d 100644 --- a/include/mbgl/mtl/uniform_block.hpp +++ b/include/mbgl/mtl/uniform_block.hpp @@ -38,8 +38,7 @@ protected: /// Stores a collection of uniform blocks by name class UniformBlockArray final : public gfx::UniformBlockArray { public: - UniformBlockArray(int initCapacity = 10) - : gfx::UniformBlockArray(initCapacity) {} + UniformBlockArray() = default; UniformBlockArray(UniformBlockArray&& other) : gfx::UniformBlockArray(std::move(other)) {} UniformBlockArray(const UniformBlockArray&) = delete; diff --git a/include/mbgl/mtl/uniform_buffer.hpp b/include/mbgl/mtl/uniform_buffer.hpp index 78331ce4d..1e9fea93d 100644 --- a/include/mbgl/mtl/uniform_buffer.hpp +++ b/include/mbgl/mtl/uniform_buffer.hpp @@ -24,8 +24,7 @@ protected: /// Stores a collection of uniform buffers by name class UniformBufferArray final : public gfx::UniformBufferArray { public: - UniformBufferArray(int initCapacity = 10) - : gfx::UniformBufferArray(initCapacity) {} + UniformBufferArray() = default; UniformBufferArray(UniformBufferArray&& other) : gfx::UniformBufferArray(std::move(other)) {} UniformBufferArray(const UniformBufferArray&) = delete; diff --git a/include/mbgl/mtl/vertex_attribute.hpp b/include/mbgl/mtl/vertex_attribute.hpp index 37c125b78..84eb12fea 100644 --- a/include/mbgl/mtl/vertex_attribute.hpp +++ b/include/mbgl/mtl/vertex_attribute.hpp @@ -39,8 +39,7 @@ public: /// Stores a collection of vertex attributes by name class VertexAttributeArray final : public gfx::VertexAttributeArray { public: - VertexAttributeArray(int initCapacity = 10) - : gfx::VertexAttributeArray(initCapacity) {} + VertexAttributeArray() = default; VertexAttributeArray(VertexAttributeArray&& other) : gfx::VertexAttributeArray(std::move(other)) {} diff --git a/include/mbgl/renderer/layer_tweaker.hpp b/include/mbgl/renderer/layer_tweaker.hpp index 170d0c86e..5e3429fba 100644 --- a/include/mbgl/renderer/layer_tweaker.hpp +++ b/include/mbgl/renderer/layer_tweaker.hpp @@ -58,6 +58,8 @@ public: virtual void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) = 0; + void updateProperties(Immutable); + protected: /// Calculate matrices for this tile. /// @param nearClipped If true, the near plane is moved further to enhance depth buffer precision. @@ -74,6 +76,7 @@ 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 diff --git a/include/mbgl/renderer/renderer_observer.hpp b/include/mbgl/renderer/renderer_observer.hpp index 58889fa35..990c03081 100644 --- a/include/mbgl/renderer/renderer_observer.hpp +++ b/include/mbgl/renderer/renderer_observer.hpp @@ -35,6 +35,11 @@ public: /// End of frame, booleans flags that a repaint is required and that placement changed. virtual void onDidFinishRenderingFrame(RenderMode, bool /*repaint*/, bool /*placementChanged*/) {} + /// End of frame, booleans flags that a repaint is required and that placement changed. + virtual void onDidFinishRenderingFrame(RenderMode mode, bool repaint, bool placementChanged, double /*frameTime*/) { + onDidFinishRenderingFrame(mode, repaint, placementChanged); + } + /// Final frame virtual void onDidFinishRenderingMap() {} diff --git a/include/mbgl/shaders/gl/shader_program_gl.hpp b/include/mbgl/shaders/gl/shader_program_gl.hpp index fd89e4f9d..fd7221a1d 100644 --- a/include/mbgl/shaders/gl/shader_program_gl.hpp +++ b/include/mbgl/shaders/gl/shader_program_gl.hpp @@ -4,6 +4,9 @@ #include #include #include +#include + +#include namespace mbgl { @@ -13,8 +16,13 @@ namespace gl { class ShaderProgramGL final : public gfx::ShaderProgramBase { public: + using SamplerLocationMap = std::unordered_map; + ShaderProgramGL(UniqueProgram&& glProgram_); - ShaderProgramGL(UniqueProgram&&, UniformBlockArrayGL&& uniformBlocks, VertexAttributeArrayGL&& attributes); + ShaderProgramGL(UniqueProgram&&, + UniformBlockArrayGL&& uniformBlocks, + VertexAttributeArrayGL&& attributes, + SamplerLocationMap&& samplerLocations); ShaderProgramGL(ShaderProgramGL&& other); ~ShaderProgramGL() noexcept override = default; @@ -29,7 +37,7 @@ public: const std::string& fragmentSource, const std::string& additionalDefines = "") noexcept(false); - std::optional getSamplerLocation(std::string_view name) const override; + std::optional getSamplerLocation(const StringIdentity id) const override; const gfx::UniformBlockArray& getUniformBlocks() const override { return uniformBlocks; } @@ -47,6 +55,7 @@ protected: UniformBlockArrayGL uniformBlocks; VertexAttributeArrayGL vertexAttributes; + SamplerLocationMap samplerLocations; }; } // namespace gl diff --git a/include/mbgl/shaders/mtl/shader_program.hpp b/include/mbgl/shaders/mtl/shader_program.hpp index 656b7ead3..11ea96bc4 100644 --- a/include/mbgl/shaders/mtl/shader_program.hpp +++ b/include/mbgl/shaders/mtl/shader_program.hpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mbgl { namespace shaders { @@ -53,7 +53,7 @@ public: const MTLVertexDescriptorPtr&, const gfx::ColorMode& colorMode) const; - std::optional getSamplerLocation(std::string_view name) const override; + std::optional getSamplerLocation(const StringIdentity id) const override; const gfx::VertexAttributeArray& getVertexAttributes() const override { return vertexAttributes; } gfx::VertexAttributeArray& mutableVertexAttributes() override { return vertexAttributes; } @@ -72,7 +72,7 @@ protected: MTLFunctionPtr fragmentFunction; UniformBlockArray uniformBlocks; VertexAttributeArray vertexAttributes; - std::vector textureBindings; + std::unordered_map textureBindings; }; } // namespace mtl diff --git a/include/mbgl/shaders/shader_program_base.hpp b/include/mbgl/shaders/shader_program_base.hpp index 22762342e..ad7084a89 100644 --- a/include/mbgl/shaders/shader_program_base.hpp +++ b/include/mbgl/shaders/shader_program_base.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -18,8 +19,8 @@ protected: ~ShaderProgramBase() noexcept override = default; template - bool set(gfx::VertexAttributeArray& attrs, const std::string& name, std::size_t i, T value) { - const auto& item = attrs.get(name); + bool set(gfx::VertexAttributeArray& attrs, const StringIdentity id, std::size_t i, T value) { + const auto& item = attrs.get(id); if (item && i < item->getCount()) { item->set(i, value); return true; @@ -32,7 +33,7 @@ public: /// @brief Gets the sampler location /// @param name uniform name - virtual std::optional getSamplerLocation(std::string_view name) const = 0; + virtual std::optional getSamplerLocation(const StringIdentity) const = 0; /// Get the available uniform blocks attached to this shader virtual const gfx::UniformBlockArray& getUniformBlocks() const = 0; diff --git a/include/mbgl/util/string_indexer.hpp b/include/mbgl/util/string_indexer.hpp new file mode 100644 index 000000000..461ee14ed --- /dev/null +++ b/include/mbgl/util/string_indexer.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using StringIdentity = size_t; + +class StringIndexer { +public: + StringIndexer(StringIndexer const&) = delete; + StringIndexer(StringIndexer&&) = delete; + void operator=(StringIndexer const&) = delete; + + static StringIdentity get(const std::string& string); + + static const std::string& get(const StringIdentity id); + + static void clear(); + + static size_t size(); + +protected: + StringIndexer() = default; + ~StringIndexer() = default; + + using MapType = std::unordered_map; + using VectorType = std::vector; + + static StringIndexer& instance() { + static StringIndexer inst; + return inst; + } + + MapType stringToIdentity; + VectorType identityToString; + std::shared_mutex sharedMutex; +}; + +} // namespace mbgl diff --git a/platform/android/MapboxGLAndroidSDK/src/cpp/android_renderer_frontend.cpp b/platform/android/MapboxGLAndroidSDK/src/cpp/android_renderer_frontend.cpp index 5a7256cf7..840e4404a 100644 --- a/platform/android/MapboxGLAndroidSDK/src/cpp/android_renderer_frontend.cpp +++ b/platform/android/MapboxGLAndroidSDK/src/cpp/android_renderer_frontend.cpp @@ -31,8 +31,12 @@ public: void onWillStartRenderingFrame() override { delegate.invoke(&RendererObserver::onWillStartRenderingFrame); } - void onDidFinishRenderingFrame(RenderMode mode, bool repaintNeeded, bool placementChanged) override { - delegate.invoke(&RendererObserver::onDidFinishRenderingFrame, mode, repaintNeeded, placementChanged); + void onDidFinishRenderingFrame(RenderMode mode, + bool repaintNeeded, + bool placementChanged, + double frameTime) override { + void (RendererObserver::*f)(RenderMode, bool, bool, double) = &RendererObserver::onDidFinishRenderingFrame; + delegate.invoke(f, mode, repaintNeeded, placementChanged, frameTime); } void onDidFinishRenderingMap() override { delegate.invoke(&RendererObserver::onDidFinishRenderingMap); } diff --git a/platform/default/src/mbgl/map/map_snapshotter.cpp b/platform/default/src/mbgl/map/map_snapshotter.cpp index 12be320da..eab4baa1e 100644 --- a/platform/default/src/mbgl/map/map_snapshotter.cpp +++ b/platform/default/src/mbgl/map/map_snapshotter.cpp @@ -36,8 +36,12 @@ public: void onResourceError(std::exception_ptr err) override { delegate.invoke(&RendererObserver::onResourceError, err); } - void onDidFinishRenderingFrame(RenderMode mode, bool repaintNeeded, bool placementChanged) override { - delegate.invoke(&RendererObserver::onDidFinishRenderingFrame, mode, repaintNeeded, placementChanged); + void onDidFinishRenderingFrame(RenderMode mode, + bool repaintNeeded, + bool placementChanged, + double frameTime) override { + void (RendererObserver::*f)(RenderMode, bool, bool, double) = &RendererObserver::onDidFinishRenderingFrame; + delegate.invoke(f, mode, repaintNeeded, placementChanged, frameTime); } void onStyleImageMissing(const std::string& image, const StyleImageMissingCallback& cb) override { @@ -77,6 +81,16 @@ public: rendererObserver->onDidFinishRenderingFrame(mode, repaintNeeded, placementChanged); } + void onDidFinishRenderingFrame(RenderMode mode, + bool repaintNeeded, + bool placementChanged, + double frameTime) override { + if (mode == RenderMode::Full && hasPendingStillImageRequest) { + stillImage = frontend.readStillImage(); + } + rendererObserver->onDidFinishRenderingFrame(mode, repaintNeeded, placementChanged, frameTime); + } + void onStyleImageMissing(const std::string& id, const StyleImageMissingCallback& done) override { rendererObserver->onStyleImageMissing(id, done); } diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index 0b57ed0de..508067ae9 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -2043,7 +2043,7 @@ CLLocationCoordinate2D randomWorldCoordinate(void) { } }); } - + NSAssert(self.styleNames.count == self.styleURLs.count, @"Style names and URLs don’t match."); } diff --git a/platform/ios/benchmark/MBXBenchViewController.mm b/platform/ios/benchmark/MBXBenchViewController.mm index 9dc298c48..a3b3727d6 100644 --- a/platform/ios/benchmark/MBXBenchViewController.mm +++ b/platform/ios/benchmark/MBXBenchViewController.mm @@ -36,7 +36,13 @@ // Use a local style and local assets if they’ve been downloaded. NSURL *tile = [[NSBundle mainBundle] URLForResource:@"11" withExtension:@"pbf" subdirectory:@"tiles/tiles/v3/5/7"]; NSURL *tileSourceURL = [[NSBundle mainBundle] URLForResource:@"openmaptiles" withExtension:@"json" subdirectory:@"tiles"]; - NSURL *url = [NSURL URLWithString:tile ? @"asset://styles/streets.json" : @"maptiler://maps/streets"]; + const std::vector styles = { + "maptiler://maps/streets", + }; + constexpr auto styleIndex = 0; + NSURL *url = [NSURL URLWithString:tile ? @"asset://styles/streets.json" : [NSString stringWithCString:styles[styleIndex].c_str() encoding:NSUTF8StringEncoding]]; + NSLog(@"Using style URL: \"%@\"", [url absoluteString]); + self.mapView = [[MLNMapView alloc] initWithFrame:self.view.bounds styleURL:url]; self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.mapView.delegate = self; @@ -103,12 +109,17 @@ NSDate* const currentDate = [NSDate date]; size_t idx = 0; enum class State { None, WaitingForAssets, WarmingUp, Benchmarking } state = State::None; int frames = 0; +double totalFrameTime = 0; std::chrono::steady_clock::time_point started; -std::vector> result; +std::vector > result; static const int warmupDuration = 20; // frames static const int benchmarkDuration = 200; // frames +namespace mbgl { + extern std::size_t uploadCount, uploadBuildCount, uploadVertextAttrsDirty, uploadInvalidSegments; +} + - (void)startBenchmarkIteration { if (mbgl::bench::locations.size() > idx) { @@ -122,17 +133,23 @@ static const int benchmarkDuration = 200; // frames // Do nothing. The benchmark is completed. NSLog(@"Benchmark completed."); NSLog(@"Result:"); - double totalFPS = 0; + double totalFrameTime = 0; size_t colWidth = 0; for (const auto& row : result) { colWidth = std::max(row.first.size(), colWidth); } for (const auto& row : result) { - NSLog(@"| %-*s | %4.1f fps |", int(colWidth), row.first.c_str(), row.second); - totalFPS += row.second; + NSLog(@"| %-*s | %4.1f ms | %4.1f fps |", int(colWidth), row.first.c_str(), 1e3 * row.second, 1.0 / row.second); + totalFrameTime += row.second; } - NSLog(@"Total FPS: %4.1f", totalFPS); - NSLog(@"Average FPS: %4.1f", totalFPS / result.size()); + + NSLog(@"Average frame time: %4.1f ms", totalFrameTime * 1e3 / result.size()); + NSLog(@"Average FPS: %4.1f", result.size() / totalFrameTime); + + // NSLog(@"Total uploads: %zu", mbgl::uploadCount); + // NSLog(@"Total uploads with dirty vattr: %zu", mbgl::uploadVertextAttrsDirty); + // NSLog(@"Total uploads with invalid segs: %zu", mbgl::uploadInvalidSegments); + // NSLog(@"Total uploads with build: %zu", mbgl::uploadBuildCount); // this does not shut the application down correctly, // and results in an assertion failure in thread-local code @@ -154,20 +171,25 @@ static const int benchmarkDuration = 200; // frames } } -- (void)mapViewDidFinishRenderingFrame:(MLNMapView *)mapView fullyRendered:(__unused BOOL)fullyRendered +- (void)mapViewDidFinishRenderingFrame:(MLNMapView *)mapView + fullyRendered:(__unused BOOL)fullyRendered + frameTime:(double)frameTime { if (state == State::Benchmarking) { frames++; + totalFrameTime += frameTime; if (frames >= benchmarkDuration) { state = State::None; // Report FPS - const auto duration = std::chrono::duration_cast(std::chrono::steady_clock::now() - started).count() ; - const auto fps = double(frames * 1e6) / duration; - result.emplace_back(mbgl::bench::locations[idx].name, fps); - NSLog(@"- FPS: %.1f", fps); + const auto duration = std::chrono::duration_cast(std::chrono::steady_clock::now() - started).count(); + const auto wallClockFPS = double(frames * 1e6) / duration; + const auto frameTime = static_cast(totalFrameTime) / frames; + const auto potentialFPS = 1.0 / frameTime; + result.emplace_back(mbgl::bench::locations[idx].name, frameTime); + NSLog(@"- Frame time: %.1f ms, FPS: %.1f (%.1f sync FPS)", frameTime * 1e3, potentialFPS, wallClockFPS); // Start benchmarking the next location. idx++; @@ -184,6 +206,7 @@ static const int benchmarkDuration = 200; // frames if (frames >= warmupDuration) { frames = 0; + totalFrameTime = 0; state = State::Benchmarking; started = std::chrono::steady_clock::now(); NSLog(@"- Benchmarking for %d frames...", benchmarkDuration); diff --git a/platform/ios/benchmark/locations.cpp b/platform/ios/benchmark/locations.cpp index 9f53877e4..a546bdd7f 100644 --- a/platform/ios/benchmark/locations.cpp +++ b/platform/ios/benchmark/locations.cpp @@ -4,6 +4,7 @@ namespace mbgl { namespace bench { const std::vector locations = { + { "boston", -71.07766, 42.36513, 16, 0.0 }, { "paris", 2.3411, 48.8664, 11, 0.0 }, { "paris2", 2.3516, 48.8356, 13, 273.8 }, { "alps", 10.6107, 46.9599, 6, 0.0 }, diff --git a/platform/ios/src/MLNMapView+Impl.mm b/platform/ios/src/MLNMapView+Impl.mm index c20a5a6cc..21d47a21c 100644 --- a/platform/ios/src/MLNMapView+Impl.mm +++ b/platform/ios/src/MLNMapView+Impl.mm @@ -81,7 +81,7 @@ void MLNMapViewImpl::onWillStartRenderingFrame() { void MLNMapViewImpl::onDidFinishRenderingFrame(mbgl::MapObserver::RenderFrameStatus status) { bool fullyRendered = status.mode == mbgl::MapObserver::RenderMode::Full; - [mapView mapViewDidFinishRenderingFrameFullyRendered:fullyRendered]; + [mapView mapViewDidFinishRenderingFrameFullyRendered:fullyRendered frameTime:status.frameTime]; } void MLNMapViewImpl::onWillStartRenderingMap() { diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index 1271858e3..939c4db6a 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -6812,7 +6812,8 @@ static void *windowScreenContext = &windowScreenContext; } } -- (void)mapViewDidFinishRenderingFrameFullyRendered:(BOOL)fullyRendered { +- (void)mapViewDidFinishRenderingFrameFullyRendered:(BOOL)fullyRendered + frameTime:(double)frameTime { if (!_mbglMap) { return; @@ -6824,7 +6825,11 @@ static void *windowScreenContext = &windowScreenContext; [self.style didChangeValueForKey:@"layers"]; } - if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:)]) + if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:frameTime:)]) + { + [self.delegate mapViewDidFinishRenderingFrame:self fullyRendered:fullyRendered frameTime:frameTime]; + } + else if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:)]) { [self.delegate mapViewDidFinishRenderingFrame:self fullyRendered:fullyRendered]; } diff --git a/platform/ios/src/MLNMapViewDelegate.h b/platform/ios/src/MLNMapViewDelegate.h index bf1a05b71..451cd06cc 100644 --- a/platform/ios/src/MLNMapViewDelegate.h +++ b/platform/ios/src/MLNMapViewDelegate.h @@ -240,6 +240,22 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)mapViewDidFinishRenderingFrame:(MLNMapView *)mapView fullyRendered:(BOOL)fullyRendered; +/** + Tells the delegate that the map view has just redrawn. + + This method is called any time the map view needs to redraw due to a change in + the viewpoint or style property transition. This method may be called very + frequently, even moreso than `-mapViewRegionIsChanging:`. Therefore, your + implementation of this method should be as lightweight as possible to avoid + affecting performance. + + @param mapView The map view that has just redrawn. + @param frameTimeNanos The time taken to render the frame, in nanoseconds + */ +- (void)mapViewDidFinishRenderingFrame:(MLNMapView *)mapView + fullyRendered:(BOOL)fullyRendered + frameTime:(double)frameTime; + /** Tells the delegate that the map view is entering an idle state, and no more drawing will be necessary until new data is loaded or there is some interaction diff --git a/platform/ios/src/MLNMapView_Private.h b/platform/ios/src/MLNMapView_Private.h index c895c8613..90343b6df 100644 --- a/platform/ios/src/MLNMapView_Private.h +++ b/platform/ios/src/MLNMapView_Private.h @@ -37,7 +37,8 @@ FOUNDATION_EXTERN MLN_EXPORT MLNExceptionName const _Nonnull MLNUnderlyingMapUna - (void)mapViewDidFinishLoadingMap; - (void)mapViewDidFailLoadingMapWithError:(nonnull NSError *)error; - (void)mapViewWillStartRenderingFrame; -- (void)mapViewDidFinishRenderingFrameFullyRendered:(BOOL)fullyRendered; +- (void)mapViewDidFinishRenderingFrameFullyRendered:(BOOL)fullyRendered + frameTime:(double)frameTime; - (void)mapViewWillStartRenderingMap; - (void)mapViewDidFinishRenderingMapFullyRendered:(BOOL)fullyRendered; - (void)mapViewDidBecomeIdle; diff --git a/platform/ios/test/MLNMapViewDelegateIntegrationTests.swift b/platform/ios/test/MLNMapViewDelegateIntegrationTests.swift index dd2361116..4192598fb 100644 --- a/platform/ios/test/MLNMapViewDelegateIntegrationTests.swift +++ b/platform/ios/test/MLNMapViewDelegateIntegrationTests.swift @@ -60,6 +60,8 @@ extension MLNMapViewDelegateIntegrationTests: MLNMapViewDelegate { func mapView(_ mapView: MLNMapView, tapOnCalloutFor annotation: MLNAnnotation) {} func mapViewDidFinishRenderingFrame(_ mapView: MLNMapView, fullyRendered: Bool) {} + + func mapViewDidFinishRenderingFrame(_ mapView: MLNMapView, fullyRendered: Bool, frameTime: Double) {} func mapView(_ mapView: MLNMapView, shapeAnnotationIsEnabled annotation: MLNShape) -> Bool { return false } diff --git a/platform/macos/src/MLNMapViewDelegate.h b/platform/macos/src/MLNMapViewDelegate.h index 486abc7ac..c1f1e4061 100644 --- a/platform/macos/src/MLNMapViewDelegate.h +++ b/platform/macos/src/MLNMapViewDelegate.h @@ -151,6 +151,22 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)mapViewDidFinishRenderingFrame:(MLNMapView *)mapView fullyRendered:(BOOL)fullyRendered; +/** + Tells the delegate that the map view has just redrawn. + + This method is called any time the map view needs to redraw due to a change in + the viewpoint or style property transition. This method may be called very + frequently, even moreso than `-mapViewRegionIsChanging:`. Therefore, your + implementation of this method should be as lightweight as possible to avoid + affecting performance. + + @param mapView The map view that has just redrawn. + @param frameTimeNanos The time taken to render the frame, in nanoseconds + */ +- (void)mapViewDidFinishRenderingFrame:(MLNMapView *)mapView + fullyRendered:(BOOL)fullyRendered + frameTime:(double)frameTime; + /** Tells the delegate that the map view is entering an idle state, and no more drawing will be necessary until new data is loaded or there is some interaction diff --git a/platform/macos/test/MLNMapViewDelegateIntegrationTests.swift b/platform/macos/test/MLNMapViewDelegateIntegrationTests.swift index 170159d5e..7ba7b2734 100644 --- a/platform/macos/test/MLNMapViewDelegateIntegrationTests.swift +++ b/platform/macos/test/MLNMapViewDelegateIntegrationTests.swift @@ -23,6 +23,8 @@ extension MLNMapViewDelegateIntegrationTests: MLNMapViewDelegate { func mapViewDidFinishRenderingFrame(_ mapView: MLNMapView, fullyRendered: Bool) {} + func mapViewDidFinishRenderingFrame(_ mapView: MLNMapView, fullyRendered: Bool, frameTime: Double) {} + func mapViewDidFinishRenderingMap(_ mapView: MLNMapView, fullyRendered: Bool) {} func mapViewDidBecomeIdle(_ mapView: MLNMapView) {} diff --git a/platform/qt/src/utils/renderer_observer.hpp b/platform/qt/src/utils/renderer_observer.hpp index 29dc29125..785c3ce8a 100644 --- a/platform/qt/src/utils/renderer_observer.hpp +++ b/platform/qt/src/utils/renderer_observer.hpp @@ -30,8 +30,13 @@ public: void onWillStartRenderingFrame() final { delegate.invoke(&mbgl::RendererObserver::onWillStartRenderingFrame); } - void onDidFinishRenderingFrame(RenderMode mode, bool repaintNeeded, bool placementChanged) final { - delegate.invoke(&mbgl::RendererObserver::onDidFinishRenderingFrame, mode, repaintNeeded, placementChanged); + void onDidFinishRenderingFrame(RenderMode mode, + bool repaintNeeded, + bool placementChanged, + double frameTime) override { + void (mbgl::RendererObserver::*f)( + RenderMode, bool, bool, double) = &mbgl::RendererObserver::onDidFinishRenderingFrame; + delegate.invoke(f, mode, repaintNeeded, placementChanged, frameTime); } void onDidFinishRenderingMap() final { delegate.invoke(&mbgl::RendererObserver::onDidFinishRenderingMap); } diff --git a/src/mbgl/gfx/context.hpp b/src/mbgl/gfx/context.hpp index 7d0fa6c66..16d2ff7f8 100644 --- a/src/mbgl/gfx/context.hpp +++ b/src/mbgl/gfx/context.hpp @@ -143,6 +143,18 @@ public: /// Resets the context state to defaults virtual void resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) = 0; + + /// Update the uniform buffer with the provided data if it already exists, otherwise create it. + /// @return True if the buffer was created, false if it was updated + virtual bool emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr&, const void* data, std::size_t size) = 0; + + /// `emplaceOrUpdateUniformBuffer` with type inference + template + std::enable_if_t, bool> emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& ptr, + const T* data) { + return emplaceOrUpdateUniformBuffer(ptr, data, sizeof(T)); + } + #endif }; diff --git a/src/mbgl/gfx/drawable_atlases_tweaker.cpp b/src/mbgl/gfx/drawable_atlases_tweaker.cpp index ae300e039..1b816afb7 100644 --- a/src/mbgl/gfx/drawable_atlases_tweaker.cpp +++ b/src/mbgl/gfx/drawable_atlases_tweaker.cpp @@ -10,7 +10,7 @@ namespace gfx { void DrawableAtlasesTweaker::setupTextures(gfx::Drawable& drawable, const bool linearFilterForIcons) { if (const auto& shader = drawable.getShader()) { - if (const auto samplerLocation = shader->getSamplerLocation(glyphName)) { + if (const auto samplerLocation = shader->getSamplerLocation(glyphNameId)) { if (atlases) { atlases->glyph->setSamplerConfiguration( {TextureFilterType::Linear, TextureWrapType::Clamp, TextureWrapType::Clamp}); @@ -19,7 +19,7 @@ void DrawableAtlasesTweaker::setupTextures(gfx::Drawable& drawable, const bool l TextureWrapType::Clamp, TextureWrapType::Clamp}); } - if (const auto iconSamplerLocation = shader->getSamplerLocation(iconName)) { + if (const auto iconSamplerLocation = shader->getSamplerLocation(iconNameId)) { assert(*samplerLocation != *iconSamplerLocation); drawable.setTexture(atlases ? atlases->glyph : nullptr, *samplerLocation); drawable.setTexture(atlases ? atlases->icon : nullptr, *iconSamplerLocation); diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index ae9f3fc13..22d34acb5 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -5,13 +5,14 @@ #include #include #include +#include namespace mbgl { namespace gfx { DrawableBuilder::DrawableBuilder(std::string name_) : name(std::move(name_)), - vertexAttrName("a_pos"), + vertexAttrNameId(StringIndexer::get("a_pos")), renderPass(mbgl::RenderPass::Opaque), impl(std::make_unique()) {} diff --git a/src/mbgl/gfx/uniform_block.cpp b/src/mbgl/gfx/uniform_block.cpp index 9958f8324..5710c8e91 100644 --- a/src/mbgl/gfx/uniform_block.cpp +++ b/src/mbgl/gfx/uniform_block.cpp @@ -5,9 +5,6 @@ namespace gfx { std::unique_ptr UniformBlockArray::nullref = nullptr; -UniformBlockArray::UniformBlockArray(int initCapacity) - : uniformBlockMap(initCapacity) {} - UniformBlockArray::UniformBlockArray(UniformBlockArray&& other) : uniformBlockMap(std::move(other.uniformBlockMap)) {} @@ -24,13 +21,13 @@ UniformBlockArray& UniformBlockArray::operator=(const UniformBlockArray& other) return *this; } -const std::unique_ptr& UniformBlockArray::get(const std::string& name) const { - const auto result = uniformBlockMap.find(name); +const std::unique_ptr& UniformBlockArray::get(const StringIdentity id) const { + const auto result = uniformBlockMap.find(id); return (result != uniformBlockMap.end()) ? result->second : nullref; } -const std::unique_ptr& UniformBlockArray::add(std::string name, int index, std::size_t size) { - const auto result = uniformBlockMap.insert(std::make_pair(std::move(name), std::unique_ptr())); +const std::unique_ptr& UniformBlockArray::add(const StringIdentity id, int index, std::size_t size) { + const auto result = uniformBlockMap.insert(std::make_pair(id, std::unique_ptr())); if (result.second) { result.first->second = create(index, size); return result.first->second; diff --git a/src/mbgl/gfx/uniform_buffer.cpp b/src/mbgl/gfx/uniform_buffer.cpp index 3ee4a1998..4a0638ab1 100644 --- a/src/mbgl/gfx/uniform_buffer.cpp +++ b/src/mbgl/gfx/uniform_buffer.cpp @@ -7,9 +7,6 @@ namespace gfx { std::shared_ptr UniformBufferArray::nullref = nullptr; -UniformBufferArray::UniformBufferArray(int initCapacity) - : uniformBufferMap(initCapacity) {} - UniformBufferArray::UniformBufferArray(UniformBufferArray&& other) : uniformBufferMap(std::move(other.uniformBufferMap)) {} @@ -26,38 +23,38 @@ UniformBufferArray& UniformBufferArray::operator=(const UniformBufferArray& othe return *this; } -const std::shared_ptr& UniformBufferArray::get(const std::string_view name) const { - const auto result = uniformBufferMap.find(std::string(name)); +const std::shared_ptr& UniformBufferArray::get(const StringIdentity id) const { + const auto result = uniformBufferMap.find(id); return (result != uniformBufferMap.end()) ? result->second : nullref; } -const std::shared_ptr& UniformBufferArray::addOrReplace(const std::string_view name, +const std::shared_ptr& UniformBufferArray::addOrReplace(const StringIdentity id, std::shared_ptr uniformBuffer) { - const auto result = uniformBufferMap.insert(std::make_pair(name, std::shared_ptr())); + const auto result = uniformBufferMap.insert(std::make_pair(id, std::shared_ptr())); result.first->second = std::move(uniformBuffer); return result.first->second; } -void UniformBufferArray::createOrUpdate(std::string_view name, +void UniformBufferArray::createOrUpdate(const StringIdentity id, const std::vector& data, gfx::Context& context) { - createOrUpdate(name, data.data(), data.size(), context); + createOrUpdate(id, data.data(), data.size(), context); } -void UniformBufferArray::createOrUpdate(const std::string_view name, +void UniformBufferArray::createOrUpdate(const StringIdentity id, const void* data, const std::size_t size, gfx::Context& context) { - if (auto& ubo = get(name); ubo && ubo->getSize() == size) { + if (auto& ubo = get(id); ubo && ubo->getSize() == size) { ubo->update(data, size); } else { - add(name, context.createUniformBuffer(data, size)); + add(id, context.createUniformBuffer(data, size)); } } -const std::shared_ptr& UniformBufferArray::add(const std::string_view name, +const std::shared_ptr& UniformBufferArray::add(const StringIdentity id, std::shared_ptr&& uniformBuffer) { - const auto result = uniformBufferMap.insert(std::make_pair(name, std::shared_ptr())); + const auto result = uniformBufferMap.insert(std::make_pair(id, std::shared_ptr())); if (result.second) { result.first->second = std::move(uniformBuffer); return result.first->second; diff --git a/src/mbgl/gfx/vertex_attribute.cpp b/src/mbgl/gfx/vertex_attribute.cpp index cee7add99..fb62719ea 100644 --- a/src/mbgl/gfx/vertex_attribute.cpp +++ b/src/mbgl/gfx/vertex_attribute.cpp @@ -19,9 +19,6 @@ std::size_t VertexAttribute::getCount() const { std::unique_ptr VertexAttributeArray::nullref = nullptr; -VertexAttributeArray::VertexAttributeArray(int initCapacity) - : attrs(initCapacity) {} - VertexAttributeArray::VertexAttributeArray(VertexAttributeArray&& other) : attrs(std::move(other.attrs)) {} @@ -40,16 +37,16 @@ VertexAttributeArray& VertexAttributeArray::operator=(const VertexAttributeArray return *this; } -const std::unique_ptr& VertexAttributeArray::get(const std::string& name) const { - const auto result = attrs.find(name); +const std::unique_ptr& VertexAttributeArray::get(const StringIdentity id) const { + const auto result = attrs.find(id); return (result != attrs.end()) ? result->second : nullref; } -const std::unique_ptr& VertexAttributeArray::add(std::string name, +const std::unique_ptr& VertexAttributeArray::add(const StringIdentity id, int index, AttributeDataType dataType, std::size_t count) { - const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr())); + const auto result = attrs.insert(std::make_pair(id, std::unique_ptr())); if (result.second) { result.first->second = create(index, dataType, count); return result.first->second; @@ -58,11 +55,11 @@ const std::unique_ptr& VertexAttributeArray::add(std::string na } } -const std::unique_ptr& VertexAttributeArray::getOrAdd(std::string name, +const std::unique_ptr& VertexAttributeArray::getOrAdd(const StringIdentity id, int index, AttributeDataType dataType, std::size_t count) { - const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr())); + const auto result = attrs.insert(std::make_pair(id, std::unique_ptr())); if (auto& attr = result.first->second; result.second) { return attr = create(index, dataType, count); } else if ((dataType == AttributeDataType::Invalid || attr->getDataType() == dataType) && @@ -94,8 +91,9 @@ void VertexAttributeArray::resolve(const VertexAttributeArray& overrides, Resolv } } -const UniqueVertexAttribute& VertexAttributeArray::add(std::string name, std::unique_ptr&& attr) { - const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr())); +const UniqueVertexAttribute& VertexAttributeArray::add(const StringIdentity id, + std::unique_ptr&& attr) { + const auto result = attrs.insert(std::make_pair(id, std::unique_ptr())); if (result.second) { result.first->second = std::move(attr); return result.first->second; diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index e0d089a09..ede26f86d 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -432,6 +432,16 @@ void Context::resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) { setColorMode(colorMode); setCullFaceMode(gfx::CullFaceMode::disabled()); } + +bool Context::emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& buffer, const void* data, std::size_t size) { + if (buffer) { + buffer->update(data, size); + return false; + } else { + buffer = createUniformBuffer(data, size); + return true; + } +} #endif void Context::setDirtyState() { diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index e821f2700..87888a60f 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -121,6 +121,8 @@ public: UniqueFramebuffer createFramebuffer(const gfx::Texture2D& color); void resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) override; + + bool emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr&, const void* data, std::size_t size) override; #endif void setDirtyState() override; diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index f74da2e4f..38acb733d 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace mbgl { namespace gl { @@ -110,8 +111,8 @@ gfx::UniformBufferArray& DrawableGL::mutableUniformBuffers() { return impl->uniformBuffers; } -void DrawableGL::setVertexAttrName(std::string value) { - impl->vertexAttrName = std::move(value); +void DrawableGL::setVertexAttrNameId(const StringIdentity id) { + impl->idVertexAttrName = id; } void DrawableGL::bindUniformBuffers() const { @@ -122,7 +123,8 @@ void DrawableGL::bindUniformBuffers() const { if (!uniformBuffer) { using namespace std::string_literals; Log::Error(Event::General, - "DrawableGL::bindUniformBuffers: UBO "s + element.first + " not found. skipping."); + "DrawableGL::bindUniformBuffers: UBO "s + StringIndexer::get(element.first) + + " not found. skipping."); assert(false); continue; } @@ -167,7 +169,7 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { const auto& defaults = shader->getVertexAttributes(); const auto& overrides = impl->vertexAttributes; - const auto& indexAttribute = defaults.get(impl->vertexAttrName); + const auto& indexAttribute = defaults.get(impl->idVertexAttrName); const auto vertexAttributeIndex = static_cast(indexAttribute ? indexAttribute->getIndex() : -1); std::vector> vertexBuffers; diff --git a/src/mbgl/gl/drawable_gl_builder.cpp b/src/mbgl/gl/drawable_gl_builder.cpp index 7a6be9509..6b1a55134 100644 --- a/src/mbgl/gl/drawable_gl_builder.cpp +++ b/src/mbgl/gl/drawable_gl_builder.cpp @@ -22,7 +22,7 @@ std::unique_ptr DrawableGLBuilder::createSegment(gfx void DrawableGLBuilder::init() { auto& drawableGL = static_cast(*currentDrawable); - drawableGL.setVertexAttrName(vertexAttrName); + drawableGL.setVertexAttrNameId(vertexAttrNameId); if (impl->rawVerticesCount) { auto raw = impl->rawVertices; diff --git a/src/mbgl/gl/drawable_gl_impl.hpp b/src/mbgl/gl/drawable_gl_impl.hpp index 2caa19d35..7cab156fc 100644 --- a/src/mbgl/gl/drawable_gl_impl.hpp +++ b/src/mbgl/gl/drawable_gl_impl.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,7 @@ public: gfx::CullFaceMode cullFaceMode; GLfloat pointSize = 0.0f; - std::string vertexAttrName = "a_pos"; + StringIdentity idVertexAttrName = StringIndexer::get("a_pos"); }; struct DrawableGL::DrawSegmentGL final : public gfx::Drawable::DrawSegment { diff --git a/src/mbgl/gl/upload_pass.cpp b/src/mbgl/gl/upload_pass.cpp index 950ac9a7f..ce08a36b2 100644 --- a/src/mbgl/gl/upload_pass.cpp +++ b/src/mbgl/gl/upload_pass.cpp @@ -196,10 +196,11 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( constexpr std::uint8_t padding = 0; std::vector allData; - allData.reserve(vertexData.size() + (defaults.getTotalSize() + align) * vertexCount); uint32_t vertexStride = 0; - if (vertexAttributeIndex != static_cast(-1)) { + if (vertexAttributeIndex != static_cast(-1) && !vertexData.empty()) { + allData.reserve(vertexData.size() + (defaults.getTotalSize() + align) * vertexCount); + // Fill in vertices allData.insert(allData.end(), vertexData.begin(), vertexData.end()); bindings.resize(vertexAttributeIndex + 1); @@ -213,7 +214,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( } // For each attribute in the program, with the corresponding default and optional override... - const auto resolveAttr = [&](const std::string& name, auto& defaultAttr, auto& overrideAttr) -> void { + const auto resolveAttr = [&](const StringIdentity id, auto& defaultAttr, auto& overrideAttr) -> void { auto& effectiveAttr = overrideAttr ? *overrideAttr : defaultAttr; const auto& defaultGL = static_cast(defaultAttr); const auto stride = defaultAttr.getStride(); @@ -237,6 +238,10 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( return; } + if (allData.empty()) { + allData.reserve(vertexData.size() + (defaults.getTotalSize() + align) * vertexCount); + } + // Get the raw data for the values in the desired format const auto& rawData = VertexAttributeGL::getRaw(effectiveAttr, defaultGL.getGLType()); if (rawData.empty()) { @@ -255,9 +260,9 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( // something else, the binding is invalid // TODO: throw? Log::Warning(Event::General, - "Got " + util::toString(rawData.size()) + " bytes for attribute '" + name + "' (" + - util::toString(defaultGL.getIndex()) + "), expected " + util::toString(stride) + " or " + - util::toString(stride * vertexCount)); + "Got " + util::toString(rawData.size()) + " bytes for attribute '" + StringIndexer::get(id) + + "' (" + util::toString(defaultGL.getIndex()) + "), expected " + util::toString(stride) + + " or " + util::toString(stride * vertexCount)); return; } diff --git a/src/mbgl/gl/vertex_attribute_gl.cpp b/src/mbgl/gl/vertex_attribute_gl.cpp index 3cd403951..dc8a5eb1e 100644 --- a/src/mbgl/gl/vertex_attribute_gl.cpp +++ b/src/mbgl/gl/vertex_attribute_gl.cpp @@ -182,5 +182,18 @@ const std::vector& VertexAttributeGL::getRaw(gfx::VertexAttribute& return rawData; } +bool VertexAttributeArrayGL::isDirty() const { + return std::any_of(attrs.begin(), attrs.end(), [](const auto& kv) { + if (kv.second) { + // If we have shared data, the dirty flag from that overrides ours + const auto& glAttrib = static_cast(*kv.second); + if (const auto& shared = glAttrib.getSharedRawData()) { + return shared->getDirty(); + } + } + return kv.second && kv.second->isDirty(); + }); +} + } // namespace gl } // namespace mbgl diff --git a/src/mbgl/map/map_impl.cpp b/src/mbgl/map/map_impl.cpp index 4fd9ba63a..9f901c3a5 100644 --- a/src/mbgl/map/map_impl.cpp +++ b/src/mbgl/map/map_impl.cpp @@ -128,11 +128,15 @@ void Map::Impl::onWillStartRenderingFrame() { } } -void Map::Impl::onDidFinishRenderingFrame(RenderMode renderMode, bool needsRepaint, bool placemenChanged) { +void Map::Impl::onDidFinishRenderingFrame(RenderMode renderMode, + bool needsRepaint, + bool placemenChanged, + double frameTime) { rendererFullyLoaded = renderMode == RenderMode::Full; if (mode == MapMode::Continuous) { - observer.onDidFinishRenderingFrame({MapObserver::RenderMode(renderMode), needsRepaint, placemenChanged}); + observer.onDidFinishRenderingFrame( + {MapObserver::RenderMode(renderMode), needsRepaint, placemenChanged, frameTime}); if (needsRepaint || transform.inTransition()) { onUpdate(); diff --git a/src/mbgl/map/map_impl.hpp b/src/mbgl/map/map_impl.hpp index 6a8043616..025d0f9d6 100644 --- a/src/mbgl/map/map_impl.hpp +++ b/src/mbgl/map/map_impl.hpp @@ -45,7 +45,7 @@ public: void onInvalidate() final; void onResourceError(std::exception_ptr) final; void onWillStartRenderingFrame() final; - void onDidFinishRenderingFrame(RenderMode, bool, bool) final; + void onDidFinishRenderingFrame(RenderMode, bool, bool, double) final; void onWillStartRenderingMap() final; void onDidFinishRenderingMap() final; void onStyleImageMissing(const std::string&, const std::function&) final; diff --git a/src/mbgl/mtl/context.cpp b/src/mbgl/mtl/context.cpp index be3c3510f..5166af988 100644 --- a/src/mbgl/mtl/context.cpp +++ b/src/mbgl/mtl/context.cpp @@ -175,6 +175,16 @@ RenderTargetPtr Context::createRenderTarget(const Size size, const gfx::TextureC void Context::resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) {} +bool Context::emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& buffer, const void* data, std::size_t size) { + if (buffer) { + buffer->update(data, size); + return false; + } else { + buffer = createUniformBuffer(data, size); + return true; + } +} + void Context::setDirtyState() {} std::unique_ptr Context::createOffscreenTexture(Size, gfx::TextureChannelDataType) { diff --git a/src/mbgl/mtl/drawable.cpp b/src/mbgl/mtl/drawable.cpp index 4b071ae48..4eaa4e480 100644 --- a/src/mbgl/mtl/drawable.cpp +++ b/src/mbgl/mtl/drawable.cpp @@ -206,12 +206,14 @@ void Drawable::setVertices(std::vector&& data, std::size_t count, gfx:: impl->vertexCount = count; impl->vertexType = type; - if (count && type != gfx::AttributeDataType::Invalid && !data.empty() && !impl->vertexAttrName.empty()) { - if (auto& attrib = impl->vertexAttributes.getOrAdd(impl->vertexAttrName, /*index=*/-1, type)) { + if (count && type != gfx::AttributeDataType::Invalid && !data.empty()) { + if (auto& attrib = impl->vertexAttributes.getOrAdd(impl->idVertexAttrName, /*index=*/-1, type)) { attrib->setRawData(std::move(data)); attrib->setStride(VertexAttribute::getStrideOf(type)); } else { - Log::Warning(Event::General, "Vertex attribute type mismatch: " + name + " / " + impl->vertexAttrName); + Log::Warning( + Event::General, + "Vertex attribute type mismatch: " + name + " / " + StringIndexer::get(impl->idVertexAttrName)); assert(false); } } @@ -240,8 +242,8 @@ gfx::UniformBufferArray& Drawable::mutableUniformBuffers() { return impl->uniformBuffers; } -void Drawable::setVertexAttrName(std::string value) { - impl->vertexAttrName = std::move(value); +void Drawable::setVertexAttrNameId(const StringIdentity value) { + impl->idVertexAttrName = value; } void Drawable::bindAttributes(const RenderPass& renderPass) const { @@ -278,7 +280,8 @@ void Drawable::bindUniformBuffers(const RenderPass& renderPass) const { if (!uniformBuffer) { using namespace std::string_literals; Log::Error(Event::General, - "Drawable::bindUniformBuffers: UBO "s + element.first + " not found. skipping."); + "Drawable::bindUniformBuffers: UBO "s + StringIndexer::get(element.first) + + " not found. skipping."); assert(false); continue; } diff --git a/src/mbgl/mtl/drawable_builder.cpp b/src/mbgl/mtl/drawable_builder.cpp index 3abde66af..ec436fbc7 100644 --- a/src/mbgl/mtl/drawable_builder.cpp +++ b/src/mbgl/mtl/drawable_builder.cpp @@ -22,7 +22,7 @@ std::unique_ptr DrawableBuilder::createSegment(gfx:: void DrawableBuilder::init() { auto& drawable = static_cast(*currentDrawable); - drawable.setVertexAttrName(vertexAttrName); + drawable.setVertexAttrNameId(vertexAttrNameId); if (impl->rawVerticesCount) { auto raw = impl->rawVertices; diff --git a/src/mbgl/mtl/drawable_impl.hpp b/src/mbgl/mtl/drawable_impl.hpp index faa51ad8e..ef386fe44 100644 --- a/src/mbgl/mtl/drawable_impl.hpp +++ b/src/mbgl/mtl/drawable_impl.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -51,7 +52,7 @@ public: gfx::StencilMode stencilMode; gfx::CullFaceMode cullFaceMode; // GLfloat pointSize = 0.0f; - std::string vertexAttrName = "a_pos"; + StringIdentity idVertexAttrName = StringIndexer::get("a_pos"); gfx::UniqueVertexBufferResource noBindingBuffer; }; diff --git a/src/mbgl/mtl/upload_pass.cpp b/src/mbgl/mtl/upload_pass.cpp index 3a81c4630..c82599a85 100644 --- a/src/mbgl/mtl/upload_pass.cpp +++ b/src/mbgl/mtl/upload_pass.cpp @@ -167,7 +167,7 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings( uint32_t vertexStride = 0; // For each attribute in the program, with the corresponding default and optional override... - const auto resolveAttr = [&](const std::string& name, auto& default_, auto& override_) -> void { + const auto resolveAttr = [&](const StringIdentity id, auto& default_, auto& override_) -> void { auto& effectiveAttr = override_ ? *override_ : default_; const auto& defaultAttr = static_cast(default_); const auto stride = defaultAttr.getStride(); diff --git a/src/mbgl/renderer/layer_tweaker.cpp b/src/mbgl/renderer/layer_tweaker.cpp index 42991269b..3474eb134 100644 --- a/src/mbgl/renderer/layer_tweaker.cpp +++ b/src/mbgl/renderer/layer_tweaker.cpp @@ -40,6 +40,11 @@ mat4 LayerTweaker::getTileMatrix(const UnwrappedTileID& tileID, return RenderTile::translateVtxMatrix(tileID, tileMatrix, translation, anchor, state, inViewportPixelUnits); } +void LayerTweaker::updateProperties(Immutable newProps) { + evaluatedProperties = std::move(newProps); + propertiesUpdated = true; +} + #if MLN_RENDER_BACKEND_METAL shaders::ExpressionInputsUBO LayerTweaker::buildExpressionUBO(double zoom, uint64_t frameCount) { const auto time = util::MonotonicTimer::now(); diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.cpp b/src/mbgl/renderer/layers/background_layer_tweaker.cpp index bb2f97ed2..ceb875b3f 100644 --- a/src/mbgl/renderer/layers/background_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/background_layer_tweaker.cpp @@ -9,14 +9,19 @@ #include #include #include +#include namespace mbgl { using namespace style; using namespace shaders; -static constexpr auto BackgroundPatternShaderName = "BackgroundPatternShader"; -static constexpr auto texUniformName = "u_image"; +#if !defined(NDEBUG) +constexpr auto BackgroundPatternShaderName = "BackgroundPatternShader"; +#endif +static const StringIdentity idBackgroundDrawableUBOName = StringIndexer::get("BackgroundDrawableUBO"); +static const StringIdentity idBackgroundLayerUBOName = StringIndexer::get("BackgroundLayerUBO"); +static const StringIdentity idTexUniformName = StringIndexer::get("u_image"); void BackgroundLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree&, const PaintParameters& parameters) { const auto& state = parameters.state; @@ -61,11 +66,11 @@ void BackgroundLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTre const BackgroundDrawableUBO drawableUBO = {/* .matrix = */ util::cast(matrix)}; auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.createOrUpdate("BackgroundDrawableUBO", &drawableUBO, context); + uniforms.createOrUpdate(idBackgroundDrawableUBOName, &drawableUBO, context); if (hasPattern) { if (!samplerLocation.has_value()) { - samplerLocation = shader->getSamplerLocation(texUniformName); + samplerLocation = shader->getSamplerLocation(idTexUniformName); if (const auto& tex = parameters.patternAtlas.texture()) { tex->setSamplerConfiguration( {gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); @@ -103,7 +108,7 @@ void BackgroundLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTre /* .opacity = */ evaluated.get(), /* .pad = */ 0, }; - uniforms.createOrUpdate("BackgroundLayerUBO", &layerUBO, context); + uniforms.createOrUpdate(idBackgroundLayerUBOName, &layerUBO, context); } else { // UBOs can be shared if (!backgroundLayerBuffer) { @@ -114,7 +119,7 @@ void BackgroundLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTre 0}; backgroundLayerBuffer = context.createUniformBuffer(&layerUBO, sizeof(layerUBO)); } - uniforms.addOrReplace("BackgroundLayerUBO", backgroundLayerBuffer); + uniforms.addOrReplace(idBackgroundLayerUBOName, backgroundLayerBuffer); } }); } diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp index bee44691d..9d1500127 100644 --- a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #if MLN_RENDER_BACKEND_METAL #include @@ -19,9 +20,15 @@ namespace mbgl { using namespace style; - using namespace shaders; +static const StringIdentity idCircleDrawableUBOName = StringIndexer::get("CircleDrawableUBO"); +static const StringIdentity idCirclePaintParamsUBOName = StringIndexer::get("CirclePaintParamsUBO"); +static const StringIdentity idCircleEvaluatedPropsUBOName = StringIndexer::get("CircleEvaluatedPropsUBO"); + +static const StringIdentity idExpressionInputsUBOName = StringIndexer::get("ExpressionInputsUBO"); +static const StringIdentity idCirclePermutationUBOName = StringIndexer::get("CirclePermutationUBO"); + void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { @@ -108,8 +115,8 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, layerGroup.visitDrawables([&](gfx::Drawable& drawable) { auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.addOrReplace("CirclePaintParamsUBO", paintParamsUniformBuffer); - uniforms.addOrReplace("CircleEvaluatedPropsUBO", evaluatedPropsUniformBuffer); + uniforms.addOrReplace(idCirclePaintParamsUBOName, paintParamsUniformBuffer); + uniforms.addOrReplace(idCircleEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); if (!drawable.getTileID()) { assert(!"Circles only render with tiles"); @@ -132,11 +139,11 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const CircleDrawableUBO drawableUBO = {/* .matrix = */ util::cast(matrix), /* .extrude_scale = */ extrudeScale, /* .padding = */ 0}; - uniforms.createOrUpdate("CircleDrawableUBO", &drawableUBO, context); + uniforms.createOrUpdate(idCircleDrawableUBOName, &drawableUBO, context); #if MLN_RENDER_BACKEND_METAL - uniforms.addOrReplace("ExpressionInputsUBO", expressionUniformBuffer); - uniforms.addOrReplace("CirclePermutationUBO", permutationUniformBuffer); + uniforms.addOrReplace(idExpressionInputsUBOName, expressionUniformBuffer); + uniforms.addOrReplace(idCirclePermutationUBOName, permutationUniformBuffer); #endif // MLN_RENDER_BACKEND_METAL }); } diff --git a/src/mbgl/renderer/layers/collision_layer_tweaker.cpp b/src/mbgl/renderer/layers/collision_layer_tweaker.cpp index 2e0facf30..5e8d0bd9a 100644 --- a/src/mbgl/renderer/layers/collision_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/collision_layer_tweaker.cpp @@ -31,6 +31,9 @@ static_assert(sizeof(CollisionUBO) == 20 * 4); } // namespace +const StringIdentity CollisionLayerTweaker::idCollisionCircleUBOName = StringIndexer::get(CollisionCircleUBOName); +const StringIdentity CollisionLayerTweaker::idCollisionBoxUBOName = StringIndexer::get(CollisionBoxUBOName); + void CollisionLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { @@ -79,12 +82,12 @@ void CollisionLayerTweaker::execute(LayerGroupBase& layerGroup, const auto& shaderUniforms = shader->getUniformBlocks(); auto& uniforms = drawable.mutableUniformBuffers(); - if (shaderUniforms.get(std::string(CollisionBoxUBOName))) { + if (shaderUniforms.get(idCollisionBoxUBOName)) { // collision box - uniforms.createOrUpdate(CollisionBoxUBOName, &drawableUBO, context); - } else if (shaderUniforms.get(std::string(CollisionCircleUBOName))) { + uniforms.createOrUpdate(idCollisionBoxUBOName, &drawableUBO, context); + } else if (shaderUniforms.get(idCollisionCircleUBOName)) { // collision circle - uniforms.createOrUpdate(CollisionCircleUBOName, &drawableUBO, context); + uniforms.createOrUpdate(idCollisionCircleUBOName, &drawableUBO, context); } else { Log::Error(Event::General, "Collision shader uniform name unknown."); } diff --git a/src/mbgl/renderer/layers/collision_layer_tweaker.hpp b/src/mbgl/renderer/layers/collision_layer_tweaker.hpp index dc915ddc8..6a47bf7a1 100644 --- a/src/mbgl/renderer/layers/collision_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/collision_layer_tweaker.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -19,8 +20,10 @@ public: void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; - static constexpr std::string_view CollisionCircleUBOName = "CollisionCircleUBO"; - static constexpr std::string_view CollisionBoxUBOName = "CollisionBoxUBO"; + static constexpr auto CollisionCircleUBOName = "CollisionCircleUBO"; + static const StringIdentity idCollisionCircleUBOName; + static constexpr auto CollisionBoxUBOName = "CollisionBoxUBO"; + static const StringIdentity idCollisionBoxUBOName; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp index e94fbe808..01dd0968b 100644 --- a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace mbgl { @@ -50,10 +51,17 @@ struct alignas(16) FillExtrusionDrawablePropsUBO { }; static_assert(sizeof(FillExtrusionDrawablePropsUBO) == 5 * 16); -constexpr auto texUniformName = "u_image"; +static const StringIdentity idFillExtrusionDrawableUBOName = StringIndexer::get("FillExtrusionDrawableUBO"); +static const StringIdentity idFillExtrusionDrawablePropsUBOName = StringIndexer::get("FillExtrusionDrawablePropsUBO"); +static const StringIdentity idTexImageName = StringIndexer::get("u_image"); } // namespace +const StringIdentity FillExtrusionLayerTweaker::idFillExtrusionTilePropsUBOName = StringIndexer::get( + "FillExtrusionDrawableTilePropsUBO"); +const StringIdentity FillExtrusionLayerTweaker::idFillExtrusionInterpolateUBOName = StringIndexer::get( + "FillExtrusionInterpolateUBO"); + void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { @@ -96,7 +104,7 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, layerGroup.visitDrawables([&](gfx::Drawable& drawable) { auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.addOrReplace("FillExtrusionDrawablePropsUBO", propsBuffer); + uniforms.addOrReplace(idFillExtrusionDrawablePropsUBOName, propsBuffer); if (!drawable.getTileID()) { return; @@ -124,7 +132,7 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, Size textureSize = {0, 0}; if (const auto shader = drawable.getShader()) { - if (const auto index = shader->getSamplerLocation(texUniformName)) { + if (const auto index = shader->getSamplerLocation(idTexImageName)) { if (const auto& tex = drawable.getTexture(*index)) { textureSize = tex->getSize(); } @@ -140,7 +148,7 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, /* .height_factor = */ heightFactor, /* .pad = */ 0}; - uniforms.createOrUpdate("FillExtrusionDrawableUBO", &drawableUBO, context); + uniforms.createOrUpdate(idFillExtrusionDrawableUBOName, &drawableUBO, context); }); } diff --git a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.hpp b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.hpp index 7d1a775ee..7e08ae9a3 100644 --- a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -19,8 +20,8 @@ public: void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; - static constexpr std::string_view FillExtrusionTilePropsUBOName = "FillExtrusionDrawableTilePropsUBO"; - static constexpr std::string_view FillExtrusionInterpolateUBOName = "FillExtrusionInterpolateUBO"; + static const StringIdentity idFillExtrusionTilePropsUBOName; + static const StringIdentity idFillExtrusionInterpolateUBOName; private: gfx::UniformBufferPtr propsBuffer; diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp index 9880b369a..f5d5004d6 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #if MLN_RENDER_BACKEND_METAL #include @@ -22,6 +23,41 @@ namespace mbgl { using namespace style; + +static const StringIdentity idFillDrawableUBOName = StringIndexer::get("FillDrawableUBO"); +static const StringIdentity idFillDrawablePropsUBOName = StringIndexer::get("FillDrawablePropsUBO"); +static const StringIdentity idFillEvaluatedPropsUBOName = StringIndexer::get("FillEvaluatedPropsUBO"); +static const StringIdentity idFillPermutationUBOName = StringIndexer::get("FillPermutationUBO"); + +const StringIdentity FillLayerTweaker::idFillTilePropsUBOName = StringIndexer::get("FillDrawableTilePropsUBO"); +const StringIdentity FillLayerTweaker::idFillInterpolateUBOName = StringIndexer::get("FillInterpolateUBO"); +const StringIdentity FillLayerTweaker::idFillOutlineInterpolateUBOName = StringIndexer::get( + "FillOutlineInterpolateUBO"); + +static const StringIdentity idFillOutlineDrawableUBOName = StringIndexer::get("FillOutlineDrawableUBO"); +static const StringIdentity idFillOutlineEvaluatedPropsUBOName = StringIndexer::get("FillOutlineEvaluatedPropsUBO"); +static const StringIdentity idFillOutlinePermutationUBOName = StringIndexer::get("FillOutlinePermutationUBO"); + +static const StringIdentity idFillOutlineInterpolateUBOName = StringIndexer::get("FillOutlineInterpolateUBO"); + +static const StringIdentity idFillPatternDrawableUBOName = StringIndexer::get("FillPatternDrawableUBO"); +static const StringIdentity idFillPatternPermutationUBOName = StringIndexer::get("FillPatternPermutationUBO"); +static const StringIdentity idFillPatternInterpolateUBOName = StringIndexer::get("FillPatternInterpolateUBO"); +static const StringIdentity idFillPatternEvaluatedPropsUBOName = StringIndexer::get("FillPatternEvaluatedPropsUBO"); +static const StringIdentity idFillPatternTilePropsUBOName = StringIndexer::get("FillPatternTilePropsUBO"); + +static const StringIdentity idFillOutlinePatternDrawableUBOName = StringIndexer::get("FillOutlinePatternDrawableUBO"); +static const StringIdentity idFillOutlinePatternPermutationUBOName = StringIndexer::get( + "FillOutlinePatternPermutationUBO"); +static const StringIdentity idFillOutlinePatternInterpolateUBOName = StringIndexer::get( + "FillOutlinePatternInterpolateUBO"); +static const StringIdentity idFillOutlinePatternEvaluatedPropsUBOName = StringIndexer::get( + "FillOutlinePatternEvaluatedPropsUBO"); +static const StringIdentity idFillOutlinePatternTilePropsUBOName = StringIndexer::get("FillOutlinePatternTilePropsUBO"); + +static const StringIdentity idExpressionInputsUBOName = StringIndexer::get("ExpressionInputsUBO"); + +static const StringIdentity idTexImageName = StringIndexer::get("u_image"); using namespace shaders; void FillLayerTweaker::execute(LayerGroupBase& layerGroup, @@ -245,7 +281,7 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, Size textureSize = {0, 0}; if (const auto shader = drawable.getShader()) { - if (const auto index = shader->getSamplerLocation("u_image")) { + if (const auto index = shader->getSamplerLocation(idTexImageName)) { if (const auto& tex = drawable.getTexture(*index)) { textureSize = tex->getSize(); } @@ -255,35 +291,35 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, return; } - if (uniforms.get("FillInterpolateUBO")) { + if (uniforms.get(idFillInterpolateUBOName)) { UpdateFillUniformBuffers(); - uniforms.addOrReplace("FillEvaluatedPropsUBO", fillPropsUniformBuffer); + uniforms.addOrReplace(idFillEvaluatedPropsUBOName, fillPropsUniformBuffer); const FillDrawableUBO drawableUBO = {/*.matrix=*/util::cast(matrix)}; - uniforms.createOrUpdate("FillDrawableUBO", &drawableUBO, context); + uniforms.createOrUpdate(idFillDrawableUBOName, &drawableUBO, context); #if MLN_RENDER_BACKEND_METAL - uniforms.addOrReplace("FillPermutationUBO", fillPermutationUniformBuffer); + uniforms.addOrReplace(idFillPermutationUBOName, fillPermutationUniformBuffer); #endif // MLN_RENDER_BACKEND_METAL - } else if (uniforms.get("FillOutlineInterpolateUBO")) { + } else if (uniforms.get(idFillOutlineInterpolateUBOName)) { UpdateFillOutlineUniformBuffers(); - uniforms.addOrReplace("FillOutlineEvaluatedPropsUBO", fillOutlinePropsUniformBuffer); + uniforms.addOrReplace(idFillOutlineEvaluatedPropsUBOName, fillOutlinePropsUniformBuffer); const FillOutlineDrawableUBO drawableUBO = { /*.matrix=*/util::cast(matrix), /*.world=*/{(float)renderableSize.width, (float)renderableSize.height}, }; - uniforms.createOrUpdate("FillOutlineDrawableUBO", &drawableUBO, context); + uniforms.createOrUpdate(idFillOutlineDrawableUBOName, &drawableUBO, context); #if MLN_RENDER_BACKEND_METAL - uniforms.addOrReplace("FillOutlinePermutationUBO", fillOutlinePermutationUniformBuffer); + uniforms.addOrReplace(idFillOutlinePermutationUBOName, fillOutlinePermutationUniformBuffer); #endif // MLN_RENDER_BACKEND_METAL - } else if (uniforms.get("FillPatternInterpolateUBO")) { + } else if (uniforms.get(idFillPatternInterpolateUBOName)) { UpdateFillPatternUniformBuffers(); - uniforms.addOrReplace("FillPatternEvaluatedPropsUBO", fillPatternPropsUniformBuffer); + uniforms.addOrReplace(idFillPatternEvaluatedPropsUBOName, fillPatternPropsUniformBuffer); const FillPatternDrawableUBO drawableUBO = { /*.matrix=*/util::cast(matrix), /*.scale=*/{pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale}, @@ -294,15 +330,15 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, 0, }; - uniforms.createOrUpdate("FillPatternDrawableUBO", &drawableUBO, context); + uniforms.createOrUpdate(idFillPatternDrawableUBOName, &drawableUBO, context); #if MLN_RENDER_BACKEND_METAL - uniforms.addOrReplace("FillPatternPermutationUBO", fillPatternPermutationUniformBuffer); + uniforms.addOrReplace(idFillPatternPermutationUBOName, fillPatternPermutationUniformBuffer); #endif // MLN_RENDER_BACKEND_METAL - } else if (uniforms.get("FillOutlinePatternInterpolateUBO")) { + } else if (uniforms.get(idFillOutlinePatternInterpolateUBOName)) { UpdateFillOutlinePatternUniformBuffers(); - uniforms.addOrReplace("FillOutlinePatternEvaluatedPropsUBO", fillOutlinePatternPropsUniformBuffer); + uniforms.addOrReplace(idFillOutlinePatternEvaluatedPropsUBOName, fillOutlinePatternPropsUniformBuffer); const FillOutlinePatternDrawableUBO drawableUBO = { /*.matrix=*/util::cast(matrix), /*.scale=*/{pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale}, @@ -312,15 +348,15 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, /*.texsize=*/{static_cast(textureSize.width), static_cast(textureSize.height)}, }; - uniforms.createOrUpdate("FillOutlinePatternDrawableUBO", &drawableUBO, context); + uniforms.createOrUpdate(idFillOutlinePatternDrawableUBOName, &drawableUBO, context); #if MLN_RENDER_BACKEND_METAL - uniforms.addOrReplace("FillOutlinePatternPermutationUBO", fillOutlinePatternPermutationUniformBuffer); + uniforms.addOrReplace(idFillOutlinePatternPermutationUBOName, fillOutlinePatternPermutationUniformBuffer); #endif // MLN_RENDER_BACKEND_METAL } #if MLN_RENDER_BACKEND_METAL - uniforms.addOrReplace("ExpressionInputsUBO", expressionUniformBuffer); + uniforms.addOrReplace(idExpressionInputsUBOName, expressionUniformBuffer); #endif // MLN_RENDER_BACKEND_METAL }); diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.hpp b/src/mbgl/renderer/layers/fill_layer_tweaker.hpp index 7dd2bf73b..e0495507b 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -19,6 +20,10 @@ public: void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; + static const StringIdentity idFillTilePropsUBOName; + static const StringIdentity idFillInterpolateUBOName; + static const StringIdentity idFillOutlineInterpolateUBOName; + private: gfx::UniformBufferPtr fillPropsUniformBuffer; gfx::UniformBufferPtr fillOutlinePropsUniformBuffer; diff --git a/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp b/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp index e9f88abc4..b70109eae 100644 --- a/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace mbgl { @@ -28,8 +29,8 @@ struct alignas(16) HeatmapEvaluatedPropsUBO { }; static_assert(sizeof(HeatmapEvaluatedPropsUBO) % 16 == 0); -static constexpr std::string_view HeatmapDrawableUBOName = "HeatmapDrawableUBO"; -static constexpr std::string_view HeatmapEvaluatedPropsUBOName = "HeatmapEvaluatedPropsUBO"; +static const StringIdentity idHeatmapDrawableUBOName = StringIndexer::get("HeatmapDrawableUBO"); +static const StringIdentity idHeatmapEvaluatedPropsUBOName = StringIndexer::get("HeatmapEvaluatedPropsUBO"); void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, @@ -58,7 +59,7 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, layerGroup.visitDrawables([&](gfx::Drawable& drawable) { auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.addOrReplace(HeatmapEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); + uniforms.addOrReplace(idHeatmapEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); if (!drawable.getTileID()) { return; @@ -78,7 +79,7 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, /* .extrude_scale = */ tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())), /* .padding = */ {0}}; - uniforms.createOrUpdate(HeatmapDrawableUBOName, &drawableUBO, context); + uniforms.createOrUpdate(idHeatmapDrawableUBOName, &drawableUBO, context); }); } diff --git a/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp b/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp index 68b6ef82b..c12e1e5eb 100644 --- a/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace mbgl { @@ -21,7 +22,7 @@ struct alignas(16) HeatmapTextureDrawableUBO { }; static_assert(sizeof(HeatmapTextureDrawableUBO) % 16 == 0); -static constexpr std::string_view HeatmapTextureDrawableUBOName = "HeatmapTextureDrawableUBO"; +static const StringIdentity idHeatmapTextureDrawableUBOName = StringIndexer::get("HeatmapTextureDrawableUBO"); void HeatmapTextureLayerTweaker::execute(LayerGroupBase& layerGroup, [[maybe_unused]] const RenderTree& renderTree, @@ -48,7 +49,7 @@ void HeatmapTextureLayerTweaker::execute(LayerGroupBase& layerGroup, /* .padding = */ 0}; drawable.mutableUniformBuffers().createOrUpdate( - HeatmapTextureDrawableUBOName, &drawableUBO, parameters.context); + idHeatmapTextureDrawableUBOName, &drawableUBO, parameters.context); }); } diff --git a/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp b/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp index 8bdb09771..d2c4cbbbd 100644 --- a/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace mbgl { @@ -26,8 +27,8 @@ struct alignas(16) HillshadeEvaluatedPropsUBO { }; static_assert(sizeof(HillshadeEvaluatedPropsUBO) % 16 == 0); -static constexpr std::string_view HillshadeDrawableUBOName = "HillshadeDrawableUBO"; -static constexpr std::string_view HillshadeEvaluatedPropsUBOName = "HillshadeEvaluatedPropsUBO"; +static const StringIdentity idHillshadeDrawableUBOName = StringIndexer::get("HillshadeDrawableUBO"); +static const StringIdentity idHillshadeEvaluatedPropsUBOName = StringIndexer::get("HillshadeEvaluatedPropsUBO"); std::array getLatRange(const UnwrappedTileID& id) { const LatLng latlng0 = LatLng(id); @@ -66,7 +67,7 @@ void HillshadeLayerTweaker::execute(LayerGroupBase& layerGroup, } layerGroup.visitDrawables([&](gfx::Drawable& drawable) { - drawable.mutableUniformBuffers().addOrReplace(HillshadeEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); + drawable.mutableUniformBuffers().addOrReplace(idHillshadeEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); if (!drawable.getTileID()) { return; @@ -78,7 +79,7 @@ void HillshadeLayerTweaker::execute(LayerGroupBase& layerGroup, /* .latrange = */ getLatRange(tileID), /* .light = */ getLight(parameters, evaluated)}; - drawable.mutableUniformBuffers().createOrUpdate(HillshadeDrawableUBOName, &drawableUBO, parameters.context); + drawable.mutableUniformBuffers().createOrUpdate(idHillshadeDrawableUBOName, &drawableUBO, parameters.context); }); } diff --git a/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp b/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp index a20c80763..131402ef6 100644 --- a/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace mbgl { @@ -22,7 +23,7 @@ struct alignas(16) HillshadePrepareDrawableUBO { }; static_assert(sizeof(HillshadePrepareDrawableUBO) % 16 == 0); -static constexpr std::string_view HillshadePrepareDrawableUBOName = "HillshadePrepareDrawableUBO"; +static const StringIdentity idHillshadePrepareDrawableUBOName = StringIndexer::get("HillshadePrepareDrawableUBO"); const std::array& getUnpackVector(Tileset::DEMEncoding encoding) { // https://www.mapbox.com/help/access-elevation-data/#mapbox-terrain-rgb @@ -66,7 +67,7 @@ void HillshadePrepareLayerTweaker::execute(LayerGroupBase& layerGroup, /* .maxzoom = */ static_cast(drawableData.maxzoom)}; drawable.mutableUniformBuffers().createOrUpdate( - HillshadePrepareDrawableUBOName, &drawableUBO, parameters.context); + idHillshadePrepareDrawableUBOName, &drawableUBO, parameters.context); }); } diff --git a/src/mbgl/renderer/layers/line_layer_tweaker.cpp b/src/mbgl/renderer/layers/line_layer_tweaker.cpp index de80f9b09..a0275e54b 100644 --- a/src/mbgl/renderer/layers/line_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/line_layer_tweaker.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -21,9 +22,21 @@ namespace mbgl { using namespace style; - using namespace shaders; +static const StringIdentity idLineUBOName = StringIndexer::get("LineUBO"); +static const StringIdentity idLinePropertiesUBOName = StringIndexer::get("LinePropertiesUBO"); +static const StringIdentity idLineGradientUBOName = StringIndexer::get("LineGradientUBO"); +static const StringIdentity idLineGradientPropertiesUBOName = StringIndexer::get("LineGradientPropertiesUBO"); +static const StringIdentity idLinePatternUBOName = StringIndexer::get("LinePatternUBO"); +static const StringIdentity idLinePatternPropertiesUBOName = StringIndexer::get("LinePatternPropertiesUBO"); +static const StringIdentity idLineSDFUBOName = StringIndexer::get("LineSDFUBO"); +static const StringIdentity idLineSDFPropertiesUBOName = StringIndexer::get("LineSDFPropertiesUBO"); +static const StringIdentity idTexImageName = StringIndexer::get("u_image"); + +static const StringIdentity idExpressionInputsUBOName = StringIndexer::get("ExpressionInputsUBO"); +static const StringIdentity idLinePermutationUBOName = StringIndexer::get("LinePermutationUBO"); + void LineLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { @@ -159,9 +172,10 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]}, /*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, static_cast(zoom)), /*device_pixel_ratio = */ parameters.pixelRatio}; + uniforms.createOrUpdate(idLineUBOName, &lineUBO, context); - uniforms.createOrUpdate("LineUBO", &lineUBO, context); - uniforms.addOrReplace("LinePropertiesUBO", getLinePropsBuffer()); + // properties UBO + uniforms.addOrReplace(idLinePropertiesUBOName, getLinePropsBuffer()); } break; case LineType::Gradient: { @@ -170,13 +184,15 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]}, /*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, static_cast(zoom)), /*device_pixel_ratio = */ parameters.pixelRatio}; - uniforms.createOrUpdate("LineGradientUBO", &lineGradientUBO, context); - uniforms.addOrReplace("LineGradientPropertiesUBO", getLineGradientPropsBuffer()); + uniforms.createOrUpdate(idLineGradientUBOName, &lineGradientUBO, context); + + // properties UBO + uniforms.addOrReplace(idLineGradientPropertiesUBOName, getLineGradientPropsBuffer()); } break; case LineType::Pattern: { Size textureSize{0, 0}; - if (const auto index = shader->getSamplerLocation("u_image")) { + if (const auto index = shader->getSamplerLocation(idTexImageName)) { if (const auto& texture = drawable.getTexture(index.value())) { textureSize = texture->getSize(); } @@ -193,9 +209,10 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /*device_pixel_ratio =*/parameters.pixelRatio, /*fade =*/crossfade.t, 0}; - uniforms.createOrUpdate("LinePatternUBO", &linePatternUBO, context); + uniforms.createOrUpdate(idLinePatternUBOName, &linePatternUBO, context); - uniforms.addOrReplace("LinePatternPropertiesUBO", getLinePatternPropsBuffer()); + // properties UBO + uniforms.addOrReplace(idLinePatternPropertiesUBOName, getLinePatternPropsBuffer()); } break; case LineType::SDF: { @@ -206,7 +223,8 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, evaluated.get().to, lineData.linePatternCap); - if (const auto index = shader->getSamplerLocation("u_image")) { + // texture + if (const auto index = shader->getSamplerLocation(idTexImageName)) { if (!drawable.getTexture(index.value())) { const auto& texture = dashPatternTexture.getTexture(); drawable.setEnabled(!!texture); @@ -236,9 +254,10 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /* sdfgamma = */ static_cast(dashPatternTexture.getSize().width) / (std::min(widthA, widthB) * 256.0f * parameters.pixelRatio) / 2.0f, /* mix = */ crossfade.t}; - uniforms.createOrUpdate("LineSDFUBO", &lineSDFUBO, context); + uniforms.createOrUpdate(idLineSDFUBOName, &lineSDFUBO, context); - uniforms.addOrReplace("LineSDFPropertiesUBO", getLineSDFPropsBuffer()); + // properties UBO + uniforms.addOrReplace(idLineSDFPropertiesUBOName, getLineSDFPropsBuffer()); } } break; @@ -250,8 +269,8 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, } #if MLN_RENDER_BACKEND_METAL - uniforms.addOrReplace("ExpressionInputsUBO", expressionUniformBuffer); - uniforms.addOrReplace("LinePermutationUBO", permutationUniformBuffer); + uniforms.addOrReplace(idExpressionInputsUBOName, expressionUniformBuffer); + uniforms.addOrReplace(idLinePermutationUBOName, permutationUniformBuffer); #endif // MLN_RENDER_BACKEND_METAL }); } diff --git a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp index 1c9ae47e9..945309f8c 100644 --- a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp @@ -10,13 +10,15 @@ #include #include #include +#include namespace mbgl { using namespace style; - using namespace shaders; +static const StringIdentity idRasterDrawableUBOName = StringIndexer::get("RasterDrawableUBO"); + void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup, [[maybe_unused]] const RenderTree& renderTree, [[maybe_unused]] const PaintParameters& parameters) { @@ -75,13 +77,13 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup, /*.brightness_high = */ evaluated.get(), /*.saturation_factor = */ saturationFactor(evaluated.get()), /*.contrast_factor = */ contrastFactor(evaluated.get()), - /* .overdrawInspector = */ overdrawInspector, + /*.overdrawInspector = */ overdrawInspector, 0, 0, 0, 0}; auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.createOrUpdate("RasterDrawableUBO", &drawableUBO, parameters.context); + uniforms.createOrUpdate(idRasterDrawableUBOName, &drawableUBO, parameters.context); }); } diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index 37b093170..b3c704d95 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #endif namespace mbgl { @@ -267,7 +269,8 @@ bool RenderCircleLayer::queryIntersectsFeature(const GeometryCoordinates& queryG namespace { constexpr auto CircleShaderGroupName = "CircleShader"; -constexpr auto VertexAttribName = "a_pos"; +static const StringIdentity idCircleInterpolateUBOName = StringIndexer::get("CircleInterpolateUBO"); +static const StringIdentity idVertexAttribName = StringIndexer::get("a_pos"); } // namespace @@ -373,7 +376,7 @@ 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) { auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.createOrUpdate("CircleInterpolateUBO", &interpolateUBO, context); + uniforms.createOrUpdate(idCircleInterpolateUBOName, &interpolateUBO, context); }; if (0 < tileLayerGroup->visitDrawables(renderPass, tileID, std::move(updateExisting))) { continue; @@ -406,7 +409,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, } #endif // MLN_RENDER_BACKEND_METAL - if (const auto& attr = circleVertexAttrs.add(VertexAttribName)) { + if (const auto& attr = circleVertexAttrs.add(idVertexAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(CircleLayoutVertex, a1), 0, @@ -433,7 +436,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, drawable->setTileID(tileID); auto& uniforms = drawable->mutableUniformBuffers(); - uniforms.addOrReplace("CircleInterpolateUBO", interpBuffer); + uniforms.addOrReplace(idCircleInterpolateUBOName, interpBuffer); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.drawablesAdded; diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index a63fbd967..9e7ceaf26 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -39,10 +39,10 @@ namespace { constexpr std::string_view FillExtrusionShaderName = "FillExtrusionShader"; constexpr std::string_view FillExtrusionPatternShaderName = "FillExtrusionPatternShader"; -constexpr auto PosAttribName = "a_pos"; -constexpr auto NormAttribName = "a_normal_ed"; +static const StringIdentity idPosAttribName = StringIndexer::get("a_pos"); +static const StringIdentity idNormAttribName = StringIndexer::get("a_normal_ed"); -constexpr auto IconTextureName = "u_image"; +static const StringIdentity idIconTextureName = StringIndexer::get("u_image"); #endif // MLN_DRAWABLE_RENDERER @@ -391,9 +391,9 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, tileLayerGroup->visitDrawables(drawPass, tileID, [&](gfx::Drawable& drawable) { auto& uniforms = drawable.mutableUniformBuffers(); uniforms.createOrUpdate( - FillExtrusionLayerTweaker::FillExtrusionTilePropsUBOName, &tilePropsUBO, context); + FillExtrusionLayerTweaker::idFillExtrusionTilePropsUBOName, &tilePropsUBO, context); uniforms.createOrUpdate( - FillExtrusionLayerTweaker::FillExtrusionInterpolateUBOName, &interpUBO, context); + FillExtrusionLayerTweaker::idFillExtrusionInterpolateUBOName, &interpUBO, context); }); continue; } @@ -450,8 +450,8 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, if (hasPattern && !tweaker) { if (const auto& atlases = tile.getAtlasTextures()) { tweaker = std::make_shared(atlases, - std::string(), - std::string(IconTextureName), + 0, + idIconTextureName, /*isText=*/false, false, style::AlignmentType::Auto, @@ -466,14 +466,14 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, } } - if (const auto& attr = vertexAttrs.getOrAdd(PosAttribName)) { + if (const auto& attr = vertexAttrs.getOrAdd(idPosAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(FillExtrusionLayoutVertex, a1), /*vertexOffset=*/0, sizeof(FillExtrusionLayoutVertex), gfx::AttributeDataType::Short2); } - if (const auto& attr = vertexAttrs.getOrAdd(NormAttribName)) { + if (const auto& attr = vertexAttrs.getOrAdd(idNormAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(FillExtrusionLayoutVertex, a2), /*vertexOffset=*/0, @@ -506,9 +506,9 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, auto& uniforms = drawable->mutableUniformBuffers(); uniforms.createOrUpdate( - FillExtrusionLayerTweaker::FillExtrusionTilePropsUBOName, &tilePropsUBO, context); + FillExtrusionLayerTweaker::idFillExtrusionTilePropsUBOName, &tilePropsUBO, context); uniforms.createOrUpdate( - FillExtrusionLayerTweaker::FillExtrusionInterpolateUBOName, &interpUBO, context); + FillExtrusionLayerTweaker::idFillExtrusionInterpolateUBOName, &interpUBO, context); tileLayerGroup->addDrawable(drawPass, tileID, std::move(drawable)); ++stats.drawablesAdded; diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 2903edff6..fcba89c00 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #endif namespace mbgl { @@ -45,8 +46,15 @@ constexpr auto FillOutlineShaderName = "FillOutlineShader"; constexpr auto FillPatternShaderName = "FillPatternShader"; constexpr auto FillOutlinePatternShaderName = "FillOutlinePatternShader"; -constexpr auto PosAttribName = "a_pos"; -constexpr auto IconTextureName = "u_image"; +static const StringIdentity idFillOutlineInterpolateUBOName = StringIndexer::get("FillOutlineInterpolateUBO"); +static const StringIdentity idFillPatternInterpolateUBOName = StringIndexer::get("FillPatternInterpolateUBO"); +static const StringIdentity idFillPatternTilePropsUBOName = StringIndexer::get("FillPatternTilePropsUBO"); +static const StringIdentity idFillOutlinePatternInterpolateUBOName = StringIndexer::get( + "FillOutlinePatternInterpolateUBO"); +static const StringIdentity idFillOutlinePatternTilePropsUBOName = StringIndexer::get("FillOutlinePatternTilePropsUBO"); + +static const StringIdentity idPosAttribName = StringIndexer::get("a_pos"); +static const StringIdentity idIconTextureName = StringIndexer::get("u_image"); #endif // MLN_DRAWABLE_RENDERER inline const FillLayer::Impl& impl_cast(const Immutable& impl) { @@ -497,8 +505,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, if (const auto& atlases = tile.getAtlasTextures(); atlases && atlases->icon) { atlasTweaker = std::make_shared( atlases, - std::string(), - IconTextureName, + 0, + idIconTextureName, /*isText*/ false, /*sdfIcons*/ true, // to force linear filter /*rotationAlignment_*/ AlignmentType::Auto, @@ -516,7 +524,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, evaluated); const auto vertexCount = bucket.vertices.elements(); - if (const auto& attr = vertexAttrs.add(PosAttribName)) { + if (const auto& attr = vertexAttrs.add(idPosAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(FillLayoutVertex, a1), /*vertexOffset=*/0, @@ -527,18 +535,18 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, // If we already have drawables for this tile, update them. auto updateExisting = [&](gfx::Drawable& drawable) { auto& uniforms = drawable.mutableUniformBuffers(); - if (uniforms.get("FillInterpolateUBO")) { - uniforms.createOrUpdate("FillInterpolateUBO", &getFillInterpolateUBO(), context); - } else if (uniforms.get("FillOutlineInterpolateUBO")) { - uniforms.createOrUpdate("FillOutlineInterpolateUBO", &getFillOutlineInterpolateUBO(), context); - } else if (uniforms.get("FillPatternInterpolateUBO")) { - uniforms.createOrUpdate("FillPatternInterpolateUBO", &getFillPatternInterpolateUBO(), context); - uniforms.createOrUpdate("FillPatternTilePropsUBO", &getFillPatternTilePropsUBO(), context); - } else if (uniforms.get("FillOutlinePatternInterpolateUBO")) { + if (uniforms.get(FillLayerTweaker::idFillInterpolateUBOName)) { + uniforms.createOrUpdate(FillLayerTweaker::idFillInterpolateUBOName, &getFillInterpolateUBO(), context); + } else if (uniforms.get(idFillOutlineInterpolateUBOName)) { + uniforms.createOrUpdate(idFillOutlineInterpolateUBOName, &getFillOutlineInterpolateUBO(), context); + } else if (uniforms.get(idFillPatternInterpolateUBOName)) { + uniforms.createOrUpdate(idFillPatternInterpolateUBOName, &getFillPatternInterpolateUBO(), context); + uniforms.createOrUpdate(idFillPatternTilePropsUBOName, &getFillPatternTilePropsUBO(), context); + } else if (uniforms.get(idFillOutlinePatternInterpolateUBOName)) { uniforms.createOrUpdate( - "FillOutlinePatternInterpolateUBO", &getFillOutlinePatternInterpolateUBO(), context); + idFillOutlinePatternInterpolateUBOName, &getFillOutlinePatternInterpolateUBO(), context); uniforms.createOrUpdate( - "FillOutlinePatternTilePropsUBO", &getFillOutlinePatternTilePropsUBO(), context); + idFillOutlinePatternTilePropsUBOName, &getFillOutlinePatternTilePropsUBO(), context); } else { assert(false); } @@ -595,18 +603,19 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } } - const auto finish = - [&](gfx::DrawableBuilder& builder, const std::string& interpolateUBOName, const auto& interpolateUBO) { - builder.flush(); + const auto finish = [&](gfx::DrawableBuilder& builder, + const StringIdentity interpolateUBONameId, + const auto& interpolateUBO) { + builder.flush(); - for (auto& drawable : builder.clearDrawables()) { - drawable->setTileID(tileID); - auto& uniforms = drawable->mutableUniformBuffers(); - uniforms.createOrUpdate(interpolateUBOName, &interpolateUBO, context); - tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); - ++stats.drawablesAdded; - } - }; + for (auto& drawable : builder.clearDrawables()) { + drawable->setTileID(tileID); + auto& uniforms = drawable->mutableUniformBuffers(); + uniforms.createOrUpdate(interpolateUBONameId, &interpolateUBO, context); + tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); + ++stats.drawablesAdded; + } + }; if (fillBuilder && bucket.sharedTriangles->elements()) { fillBuilder->setShader(fillShader); @@ -620,7 +629,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, bucket.sharedTriangles, bucket.triangleSegments.data(), bucket.triangleSegments.size()); - finish(*fillBuilder, "FillInterpolateUBO", getFillInterpolateUBO()); + finish(*fillBuilder, FillLayerTweaker::idFillInterpolateUBOName, getFillInterpolateUBO()); } if (outlineBuilder && bucket.sharedLines->elements()) { outlineBuilder->setShader(outlineShader); @@ -628,7 +637,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, outlineBuilder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short2); outlineBuilder->setSegments( gfx::Lines(2), bucket.sharedLines, bucket.lineSegments.data(), bucket.lineSegments.size()); - finish(*outlineBuilder, "FillOutlineInterpolateUBO", getFillOutlineInterpolateUBO()); + finish( + *outlineBuilder, FillLayerTweaker::idFillOutlineInterpolateUBOName, getFillOutlineInterpolateUBO()); } } else { // FillPattern is defined if ((renderPass & RenderPass::Translucent) == 0) { @@ -690,17 +700,17 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, } const auto finish = [&](gfx::DrawableBuilder& builder, - const std::string& interpolateName, + const StringIdentity interpolateNameId, const auto& interpolateUBO, - const std::string& tileUBOName, + const StringIdentity tileUBONameId, const auto& tileUBO) { builder.flush(); for (auto& drawable : builder.clearDrawables()) { drawable->setTileID(tileID); auto& uniforms = drawable->mutableUniformBuffers(); - uniforms.createOrUpdate(interpolateName, &interpolateUBO, context); - uniforms.createOrUpdate(tileUBOName, &tileUBO, context); + uniforms.createOrUpdate(interpolateNameId, &interpolateUBO, context); + uniforms.createOrUpdate(tileUBONameId, &tileUBO, context); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.drawablesAdded; } @@ -721,9 +731,9 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, bucket.triangleSegments.size()); finish(*patternBuilder, - "FillPatternInterpolateUBO", + idFillPatternInterpolateUBOName, getFillPatternInterpolateUBO(), - "FillPatternTilePropsUBO", + idFillPatternTilePropsUBOName, getFillPatternTilePropsUBO()); } if (outlinePatternBuilder && bucket.sharedLines->elements()) { @@ -735,9 +745,9 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, gfx::Lines(2), bucket.sharedLines, bucket.lineSegments.data(), bucket.lineSegments.size()); finish(*outlinePatternBuilder, - "FillOutlinePatternInterpolateUBO", + idFillOutlinePatternInterpolateUBOName, getFillOutlinePatternInterpolateUBO(), - "FillOutlinePatternTilePropsUBO", + idFillOutlinePatternTilePropsUBOName, getFillOutlinePatternTilePropsUBO()); } } diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index 17a3900b8..bc37572ae 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #endif namespace mbgl { @@ -273,8 +274,10 @@ static_assert(sizeof(HeatmapInterpolateUBO) % 16 == 0); constexpr auto HeatmapShaderGroupName = "HeatmapShader"; constexpr auto HeatmapTextureShaderGroupName = "HeatmapTextureShader"; -constexpr auto HeatmapInterpolateUBOName = "HeatmapInterpolateUBO"; -constexpr auto VertexAttribName = "a_pos"; +static const StringIdentity idHeatmapInterpolateUBOName = StringIndexer::get("HeatmapInterpolateUBO"); +static const StringIdentity idVertexAttribName = StringIndexer::get("a_pos"); +static const StringIdentity idTexImageName = StringIndexer::get("u_image"); +static const StringIdentity idTexColorRampName = StringIndexer::get("u_color_ramp"); } // namespace @@ -364,7 +367,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, /* .padding = */ {0}}; tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { - drawable.mutableUniformBuffers().createOrUpdate(HeatmapInterpolateUBOName, &interpolateUBO, context); + drawable.mutableUniformBuffers().createOrUpdate(idHeatmapInterpolateUBOName, &interpolateUBO, context); }); if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) { @@ -385,7 +388,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, continue; } - if (const auto& attr = heatmapVertexAttrs.add(VertexAttribName)) { + if (const auto& attr = heatmapVertexAttrs.add(idVertexAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(HeatmapLayoutVertex, a1), /*vertexOffset=*/0, @@ -409,7 +412,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, for (auto& drawable : heatmapBuilder->clearDrawables()) { drawable->setTileID(tileID); - drawable->mutableUniformBuffers().createOrUpdate(HeatmapInterpolateUBOName, &interpolateUBO, context); + drawable->mutableUniformBuffers().createOrUpdate(idHeatmapInterpolateUBOName, &interpolateUBO, context); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.drawablesAdded; @@ -445,7 +448,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, const auto textureVertexCount = sharedTextureVertices->elements(); gfx::VertexAttributeArray textureVertexAttrs; - if (const auto& attr = textureVertexAttrs.add(VertexAttribName)) { + if (const auto& attr = textureVertexAttrs.add(idVertexAttribName)) { attr->setSharedRawData(sharedTextureVertices, offsetof(HeatmapLayoutVertex, a1), /*vertexOffset=*/0, @@ -468,11 +471,11 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders, heatmapTextureBuilder->setSegments( gfx::Triangles(), RenderStaticData::quadTriangleIndices().vector(), segments.data(), segments.size()); - auto imageLocation = heatmapTextureShader->getSamplerLocation("u_image"); + auto imageLocation = heatmapTextureShader->getSamplerLocation(idTexImageName); if (imageLocation.has_value()) { heatmapTextureBuilder->setTexture(renderTarget->getTexture(), imageLocation.value()); } - auto colorRampLocation = heatmapTextureShader->getSamplerLocation("u_color_ramp"); + auto colorRampLocation = heatmapTextureShader->getSamplerLocation(idTexColorRampName); if (colorRampLocation.has_value()) { std::shared_ptr texture = context.createTexture2D(); texture->setImage(colorRamp); diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp index 3ba9691f0..ca41a5aa0 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp @@ -281,8 +281,9 @@ void RenderHillshadeLayer::removeRenderTargets(UniqueChangeRequestVec& changes) static const std::string HillshadePrepareShaderGroupName = "HillshadePrepareShader"; static const std::string HillshadeShaderGroupName = "HillshadeShader"; -constexpr auto PosAttribName = "a_pos"; -constexpr auto TexturePosAttribName = "a_texture_pos"; +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"); void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, @@ -377,14 +378,14 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, gfx::VertexAttributeArray hillshadePrepareVertexAttrs; - if (const auto& attr = hillshadePrepareVertexAttrs.add(PosAttribName)) { + if (const auto& attr = hillshadePrepareVertexAttrs.add(idPosAttribName)) { attr->setSharedRawData(staticDataSharedVertices, offsetof(HillshadeLayoutVertex, a1), 0, sizeof(HillshadeLayoutVertex), gfx::AttributeDataType::Short2); } - if (const auto& attr = hillshadePrepareVertexAttrs.getOrAdd(TexturePosAttribName)) { + if (const auto& attr = hillshadePrepareVertexAttrs.getOrAdd(idTexturePosAttribName)) { attr->setSharedRawData(staticDataSharedVertices, offsetof(HillshadeLayoutVertex, a2), 0, @@ -405,7 +406,7 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, hillshadePrepareBuilder->setSegments( gfx::Triangles(), staticDataIndices.vector(), staticDataSegments.data(), staticDataSegments.size()); - auto imageLocation = hillshadePrepareShader->getSamplerLocation("u_image"); + auto imageLocation = hillshadePrepareShader->getSamplerLocation(idTexImageName); if (imageLocation.has_value()) { std::shared_ptr texture = context.createTexture2D(); texture->setImage(bucket.getDEMData().getImagePtr()); @@ -438,14 +439,14 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, gfx::VertexAttributeArray hillshadeVertexAttrs; - if (const auto& attr = hillshadeVertexAttrs.add(PosAttribName)) { + if (const auto& attr = hillshadeVertexAttrs.add(idPosAttribName)) { attr->setSharedRawData(vertices, offsetof(HillshadeLayoutVertex, a1), 0, sizeof(HillshadeLayoutVertex), gfx::AttributeDataType::Short2); } - if (const auto& attr = hillshadeVertexAttrs.getOrAdd(TexturePosAttribName)) { + if (const auto& attr = hillshadeVertexAttrs.getOrAdd(idTexturePosAttribName)) { attr->setSharedRawData(vertices, offsetof(HillshadeLayoutVertex, a2), 0, @@ -475,7 +476,7 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, } drawable.setIndexData(indices->vector(), std::move(drawSegments)); - auto imageLocation = hillshadeShader->getSamplerLocation("u_image"); + auto imageLocation = hillshadeShader->getSamplerLocation(idTexImageName); if (imageLocation.has_value()) { drawable.setTexture(bucket.renderTarget->getTexture(), imageLocation.value()); } @@ -493,7 +494,7 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders, hillshadeBuilder->setRawVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); hillshadeBuilder->setSegments(gfx::Triangles(), indices->vector(), segments->data(), segments->size()); - auto imageLocation = hillshadeShader->getSamplerLocation("u_image"); + auto imageLocation = hillshadeShader->getSamplerLocation(idTexImageName); if (imageLocation.has_value()) { hillshadeBuilder->setTexture(bucket.renderTarget->getTexture(), imageLocation.value()); } diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index 5146ce0ca..2f79b0f76 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #endif #if MLN_DRAWABLE_RENDERER @@ -55,8 +56,8 @@ inline const LineLayer::Impl& impl_cast(const Immutable& imp #if MLN_DRAWABLE_RENDERER -constexpr auto VertexAttribName = "a_pos_normal"; -constexpr auto DataAttribName = "a_data"; +static const StringIdentity idVertexAttribName = StringIndexer::get("a_pos_normal"); +static const StringIdentity idDataAttribName = StringIndexer::get("a_data"); #endif // MLN_DRAWABLE_RENDERER @@ -356,7 +357,13 @@ float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature, #if MLN_DRAWABLE_RENDERER /// Property interpolation UBOs +static const StringIdentity idLineInterpolationUBOName = StringIndexer::get("LineInterpolationUBO"); +static const StringIdentity idLineGradientInterpolationUBOName = StringIndexer::get("LineGradientInterpolationUBO"); +static const StringIdentity idLinePatternInterpolationUBOName = StringIndexer::get("LinePatternInterpolationUBO"); +static const StringIdentity idLineSDFInterpolationUBOName = StringIndexer::get("LineSDFInterpolationUBO"); +/// 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); @@ -368,7 +375,7 @@ void RenderLineLayer::updateLayerTweaker() { } } -static constexpr auto LineImageUniformName = "u_image"; +static const StringIdentity idLineImageUniformName = StringIndexer::get("u_image"); void RenderLineLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, @@ -436,7 +443,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, : gfx::ColorMode::unblended()); builder->setCullFaceMode(gfx::CullFaceMode::disabled()); builder->setEnableStencil(true); - builder->setVertexAttrName(VertexAttribName); + builder->setVertexAttrNameId(idVertexAttribName); return builder; }; @@ -446,7 +453,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, const auto vertexCount = bucket.vertices.elements(); builder.setRawVertices({}, vertexCount, gfx::AttributeDataType::Short4); - if (const auto& attr = vertexAttrs.add(VertexAttribName)) { + if (const auto& attr = vertexAttrs.add(idVertexAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(LineLayoutVertex, a1), /*vertexOffset=*/0, @@ -454,7 +461,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, gfx::AttributeDataType::Short2); } - if (const auto& attr = vertexAttrs.add(DataAttribName)) { + if (const auto& attr = vertexAttrs.add(idDataAttribName)) { attr->setSharedRawData(bucket.sharedVertices, offsetof(LineLayoutVertex, a2), /*vertexOffset=*/0, @@ -544,23 +551,26 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, auto& drawableUniforms = drawable.mutableUniformBuffers(); // simple line interpolation UBO - if (shaderUniforms.get("LineInterpolationUBO")) { - drawableUniforms.createOrUpdate("LineInterpolationUBO", &lineInterpolationUBO, context); + if (shaderUniforms.get(idLineInterpolationUBOName)) { + drawableUniforms.createOrUpdate(idLineInterpolationUBOName, &lineInterpolationUBO, context); } // gradient line interpolation UBO - else if (shaderUniforms.get("LineGradientInterpolationUBO")) { - drawableUniforms.createOrUpdate("LineGradientInterpolationUBO", &lineGradientInterpolationUBO, context); + else if (shaderUniforms.get(idLineGradientInterpolationUBOName)) { + drawableUniforms.createOrUpdate( + idLineGradientInterpolationUBOName, &lineGradientInterpolationUBO, context); } // pattern line interpolation UBO - else if (shaderUniforms.get("LinePatternInterpolationUBO")) { + else if (shaderUniforms.get(idLinePatternInterpolationUBOName)) { // interpolation - drawableUniforms.createOrUpdate("LinePatternInterpolationUBO", &linePatternInterpolationUBO, context); + drawableUniforms.createOrUpdate( + idLinePatternInterpolationUBOName, &linePatternInterpolationUBO, context); // tile properties - drawableUniforms.createOrUpdate("LinePatternTilePropertiesUBO", &linePatternTilePropertiesUBO, context); + drawableUniforms.createOrUpdate( + idLinePatternTilePropertiesUBOName, &linePatternTilePropertiesUBO, context); } // SDF line interpolation UBO - else if (shaderUniforms.get("LineSDFInterpolationUBO")) { - drawableUniforms.createOrUpdate("LineSDFInterpolationUBO", &lineSDFInterpolationUBO, context); + else if (shaderUniforms.get(idLineSDFInterpolationUBOName)) { + drawableUniforms.createOrUpdate(idLineSDFInterpolationUBOName, &lineSDFInterpolationUBO, context); } }); @@ -610,7 +620,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, drawable->setTileID(tileID); drawable->setData(std::make_unique(cap)); drawable->mutableUniformBuffers().createOrUpdate( - "LineSDFInterpolationUBO", &lineSDFInterpolationUBO, context); + idLineSDFInterpolationUBOName, &lineSDFInterpolationUBO, context); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.drawablesAdded; @@ -652,8 +662,8 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, if (!iconTweaker) { iconTweaker = std::make_shared( atlases, - "", - LineImageUniformName, + 0, + idLineImageUniformName, /*isText*/ false, /*sdfIcons*/ true, // to force linear filter /*rotationAlignment_*/ AlignmentType::Auto, @@ -670,9 +680,9 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::Pattern)); drawable->setTileID(tileID); drawable->mutableUniformBuffers().createOrUpdate( - "LinePatternInterpolationUBO", &linePatternInterpolationUBO, context); + idLinePatternInterpolationUBOName, &linePatternInterpolationUBO, context); drawable->mutableUniformBuffers().createOrUpdate( - "LinePatternTilePropertiesUBO", &linePatternTilePropertiesUBO, context); + idLinePatternTilePropertiesUBOName, &linePatternTilePropertiesUBO, context); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.drawablesAdded; @@ -706,7 +716,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, addAttributes(*builder, bucket, std::move(vertexAttrs)); // texture - if (const auto samplerLocation = builder->getShader()->getSamplerLocation(LineImageUniformName)) { + if (const auto samplerLocation = builder->getShader()->getSamplerLocation(idLineImageUniformName)) { if (!colorRampTexture2D && colorRamp->valid()) { // create texture. to be reused for all the tiles of the layer colorRampTexture2D = context.createTexture2D(); @@ -727,7 +737,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::Gradient)); drawable->setTileID(tileID); drawable->mutableUniformBuffers().createOrUpdate( - "LineGradientInterpolationUBO", &lineGradientInterpolationUBO, context); + idLineGradientInterpolationUBOName, &lineGradientInterpolationUBO, context); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.drawablesAdded; @@ -778,7 +788,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders, drawable->setType(mbgl::underlying_type(LineLayerTweaker::LineType::Simple)); drawable->setTileID(tileID); drawable->mutableUniformBuffers().createOrUpdate( - "LineInterpolationUBO", &lineInterpolationUBO, context); + idLineInterpolationUBOName, &lineInterpolationUBO, context); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.drawablesAdded; diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index 9ab34f138..a4c55a9ee 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -227,10 +227,10 @@ void RenderRasterLayer::markLayerRenderable(bool willRender, UniqueChangeRequest activateLayerGroup(imageLayerGroup, willRender, changes); } -constexpr auto PosAttribName = "a_pos"; -constexpr auto TexturePosAttribName = "a_texture_pos"; -constexpr auto Image0UniformName = "u_image0"; -constexpr auto Image1UniformName = "u_image1"; +static const StringIdentity idPosAttribName = StringIndexer::get("a_pos"); +static const StringIdentity idTexturePosAttribName = StringIndexer::get("a_texture_pos"); +static const StringIdentity idTexImage0Name = StringIndexer::get("u_image0"); +static const StringIdentity idTexImage1Name = StringIndexer::get("u_image1"); void RenderRasterLayer::updateLayerTweaker() { if (layerGroup || imageLayerGroup) { @@ -306,7 +306,7 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, : gfx::DepthMaskType::ReadOnly); builder->setColorMode(gfx::ColorMode::alphaBlended()); builder->setCullFaceMode(gfx::CullFaceMode::disabled()); - builder->setVertexAttrName(PosAttribName); + builder->setVertexAttrNameId(idPosAttribName); return builder; }; @@ -314,14 +314,14 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, auto setTextures = [&context, &filter, this](std::unique_ptr& builder, const RasterBucket& bucket) { // textures - auto location0 = rasterShader->getSamplerLocation(Image0UniformName); + 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(Image1UniformName); + auto location1 = rasterShader->getSamplerLocation(idTexImage1Name); if (location1.has_value()) { std::shared_ptr tex1 = context.createTexture2D(); tex1->setImage(bucket.image); @@ -345,7 +345,7 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, { gfx::VertexAttributeArray vertexAttrs; - if (auto& attr = vertexAttrs.add(PosAttribName)) { + if (auto& attr = vertexAttrs.add(idPosAttribName)) { attr->setSharedRawData(vertices, offsetof(RasterLayoutVertex, a1), /*vertexOffset=*/0, @@ -353,7 +353,7 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, gfx::AttributeDataType::Short2); } - if (auto& attr = vertexAttrs.add(TexturePosAttribName)) { + if (auto& attr = vertexAttrs.add(idTexturePosAttribName)) { attr->setSharedRawData(vertices, offsetof(RasterLayoutVertex, a2), /*vertexOffset=*/0, diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 2085e9b6f..2457b6dec 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -378,8 +378,8 @@ void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) evaluatedProperties = std::move(properties); #if MLN_DRAWABLE_RENDERER - if (layerGroup) { - layerGroup->setLayerTweaker(std::make_shared(getID(), evaluatedProperties)); + if (layerGroup && layerGroup->getLayerTweaker()) { + layerGroup->getLayerTweaker()->updateProperties(evaluatedProperties); } #endif // MLN_DRAWABLE_RENDERER } @@ -745,34 +745,34 @@ SymbolDrawableTilePropsUBO buildTileUBO(const SymbolBucket& bucket, }; } -constexpr auto dataAttibName = "a_data"; -constexpr auto posOffsetAttribName = "a_pos_offset"; -constexpr auto pixOffsetAttribName = "a_pixeloffset"; -constexpr auto projPosAttribName = "a_projected_pos"; -constexpr auto fadeOpacityAttribName = "a_fade_opacity"; -constexpr auto texUniformName = "u_texture"; -constexpr auto iconTexUniformName = "u_texture_icon"; +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"); std::vector updateTileAttributes(const SymbolBucket::Buffer& buffer, const bool isText, const SymbolBucket::PaintProperties& paintProps, const SymbolPaintProperties::PossiblyEvaluated& evaluated, gfx::VertexAttributeArray& attribs) { - if (const auto& attr = attribs.getOrAdd(posOffsetAttribName)) { + if (const auto& attr = attribs.getOrAdd(idPosOffsetAttribName)) { attr->setSharedRawData(buffer.sharedVertices, offsetof(SymbolLayoutVertex, a1), /*vertexOffset=*/0, sizeof(SymbolLayoutVertex), gfx::AttributeDataType::Short4); } - if (const auto& attr = attribs.getOrAdd(dataAttibName)) { + if (const auto& attr = attribs.getOrAdd(idDataAttibName)) { attr->setSharedRawData(buffer.sharedVertices, offsetof(SymbolLayoutVertex, a2), /*vertexOffset=*/0, sizeof(SymbolLayoutVertex), gfx::AttributeDataType::UShort4); } - if (const auto& attr = attribs.getOrAdd(pixOffsetAttribName)) { + if (const auto& attr = attribs.getOrAdd(idPixOffsetAttribName)) { attr->setSharedRawData(buffer.sharedVertices, offsetof(SymbolLayoutVertex, a3), /*vertexOffset=*/0, @@ -780,7 +780,7 @@ std::vector updateTileAttributes(const SymbolBucket::Buffer& buffer gfx::AttributeDataType::Short4); } - if (const auto& attr = attribs.getOrAdd(projPosAttribName)) { + if (const auto& attr = attribs.getOrAdd(idProjPosAttribName)) { using Vertex = gfx::Vertex; attr->setSharedRawData(buffer.sharedDynamicVertices, offsetof(Vertex, a1), @@ -788,7 +788,7 @@ std::vector updateTileAttributes(const SymbolBucket::Buffer& buffer sizeof(Vertex), gfx::AttributeDataType::Float3); } - if (const auto& attr = attribs.getOrAdd(fadeOpacityAttribName)) { + if (const auto& attr = attribs.getOrAdd(idFadeOpacityAttribName)) { using Vertex = gfx::Vertex; attr->setSharedRawData(buffer.sharedOpacityVertices, offsetof(Vertex, a1), @@ -811,7 +811,9 @@ void updateTileDrawable(gfx::Drawable& drawable, const SymbolBucket& bucket, const SymbolBucket::PaintProperties& paintProps, const SymbolPaintProperties::PossiblyEvaluated& evaluated, - const TransformState& state) { + const TransformState& state, + gfx::UniformBufferPtr& textInterpUBO, + gfx::UniformBufferPtr& iconInterpUBO) { if (!drawable.getData()) { return; } @@ -824,12 +826,25 @@ void updateTileDrawable(gfx::Drawable& drawable, // This property can be set after the initial appearance of the tile, as part of the layout process. drawData.bucketVariablePlacement = bucket.hasVariablePlacement; - const auto tileUBO = buildTileUBO(bucket, drawData, currentZoom); - const auto interpolateUBO = buildInterpUBO(paintProps, isText, currentZoom); - auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.createOrUpdate(SymbolLayerTweaker::SymbolDrawableTilePropsUBOName, &tileUBO, context); - uniforms.createOrUpdate(SymbolLayerTweaker::SymbolDrawableInterpolateUBOName, &interpolateUBO, context); + + // Create or update the shared interpolation UBO + gfx::UniformBufferPtr& interpUBO = isText ? textInterpUBO : iconInterpUBO; + if (interpUBO) { + uniforms.addOrReplace(SymbolLayerTweaker::idSymbolDrawableInterpolateUBOName, interpUBO); + } else { + const auto ubo = buildInterpUBO(paintProps, isText, currentZoom); + interpUBO = uniforms.get(SymbolLayerTweaker::idSymbolDrawableInterpolateUBOName); + if (interpUBO) { + interpUBO->update(&ubo, sizeof(ubo)); + } else { + interpUBO = context.createUniformBuffer(&ubo, sizeof(ubo)); + uniforms.addOrReplace(SymbolLayerTweaker::idSymbolDrawableInterpolateUBOName, interpUBO); + } + } + + const auto tileUBO = buildTileUBO(bucket, drawData, currentZoom); + uniforms.createOrUpdate(SymbolLayerTweaker::idSymbolDrawableTilePropsUBOName, &tileUBO, context); const auto& buffer = isText ? bucket.text : (sdfIcons ? bucket.sdfIcon : bucket.icon); const auto vertexCount = buffer.vertices().elements(); @@ -844,63 +859,63 @@ void updateTileDrawable(gfx::Drawable& drawable, drawable.setVertexAttributes(std::move(attribs)); } -constexpr auto CollisionPosAttribName = "a_pos"; -constexpr auto CollisionAnchorPosAttribName = "a_anchor_pos"; -constexpr auto CollisionExtrudeAttribName = "a_extrude"; -constexpr auto CollisionPlacedAttribName = "a_placed"; -constexpr auto CollisionShiftAttribName = "a_shift"; +static const StringIdentity idCollisionPosAttribName = StringIndexer::get("a_pos"); +static const StringIdentity idCollisionAnchorPosAttribName = StringIndexer::get("a_anchor_pos"); +static const StringIdentity idCollisionExtrudeAttribName = StringIndexer::get("a_extrude"); +static const StringIdentity idCollisionPlacedAttribName = StringIndexer::get("a_placed"); +static const StringIdentity idCollisionShiftAttribName = StringIndexer::get("a_shift"); gfx::VertexAttributeArray getCollisionVertexAttributes(const SymbolBucket::CollisionBuffer& buffer, bool staticCopy) { gfx::VertexAttributeArray vertexAttrs; if (staticCopy) { - if (auto& attr = vertexAttrs.getOrAdd(CollisionPosAttribName)) { + if (auto& attr = vertexAttrs.getOrAdd(idCollisionPosAttribName)) { std::size_t index{0}; for (auto& v : buffer.vertices().vector()) { attr->set(index++, {v.a1[0], v.a1[1]}); } } - if (auto& attr = vertexAttrs.getOrAdd(CollisionAnchorPosAttribName)) { + if (auto& attr = vertexAttrs.getOrAdd(idCollisionAnchorPosAttribName)) { std::size_t index{0}; for (auto& v : buffer.vertices().vector()) { attr->set(index++, {v.a2[0], v.a2[1]}); } } - if (auto& attr = vertexAttrs.getOrAdd(CollisionExtrudeAttribName)) { + if (auto& attr = vertexAttrs.getOrAdd(idCollisionExtrudeAttribName)) { std::size_t index{0}; for (auto& v : buffer.vertices().vector()) { attr->set(index++, {v.a3[0], v.a3[1]}); } } - if (auto& attr = vertexAttrs.getOrAdd(CollisionPlacedAttribName)) { + if (auto& attr = vertexAttrs.getOrAdd(idCollisionPlacedAttribName)) { std::size_t index{0}; for (auto& v : buffer.dynamicVertices().vector()) { attr->set(index++, {v.a1[0], v.a1[1]}); } } - if (auto& attr = vertexAttrs.getOrAdd(CollisionShiftAttribName)) { + if (auto& attr = vertexAttrs.getOrAdd(idCollisionShiftAttribName)) { std::size_t index{0}; for (auto& v : buffer.dynamicVertices().vector()) { attr->set(index++, {v.a2[0], v.a2[1]}); } } } else { - if (const auto& attr = vertexAttrs.getOrAdd(CollisionPosAttribName)) { + if (const auto& attr = vertexAttrs.getOrAdd(idCollisionPosAttribName)) { attr->setSharedRawData(buffer.sharedVertices, offsetof(CollisionBoxVertex, a1), /*vertexOffset=*/0, sizeof(CollisionBoxVertex), gfx::AttributeDataType::Short2); } - if (const auto& attr = vertexAttrs.getOrAdd(CollisionAnchorPosAttribName)) { + if (const auto& attr = vertexAttrs.getOrAdd(idCollisionAnchorPosAttribName)) { attr->setSharedRawData(buffer.sharedVertices, offsetof(CollisionBoxVertex, a2), /*vertexOffset=*/0, sizeof(CollisionBoxVertex), gfx::AttributeDataType::Short2); } - if (const auto& attr = vertexAttrs.getOrAdd(CollisionExtrudeAttribName)) { + if (const auto& attr = vertexAttrs.getOrAdd(idCollisionExtrudeAttribName)) { attr->setSharedRawData(buffer.sharedVertices, offsetof(CollisionBoxVertex, a3), /*vertexOffset=*/0, @@ -910,14 +925,14 @@ gfx::VertexAttributeArray getCollisionVertexAttributes(const SymbolBucket::Colli using DynamicVertex = gfx::Vertex; - if (const auto& attr = vertexAttrs.getOrAdd(CollisionPlacedAttribName)) { + if (const auto& attr = vertexAttrs.getOrAdd(idCollisionPlacedAttribName)) { attr->setSharedRawData(buffer.sharedDynamicVertices, offsetof(DynamicVertex, a1), /*vertexOffset=*/0, sizeof(DynamicVertex), gfx::AttributeDataType::UByte2); } - if (const auto& attr = vertexAttrs.getOrAdd(CollisionShiftAttribName)) { + if (const auto& attr = vertexAttrs.getOrAdd(idCollisionShiftAttribName)) { attr->setSharedRawData(buffer.sharedDynamicVertices, offsetof(DynamicVertex, a2), /*vertexOffset=*/0, @@ -1032,7 +1047,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, collisionBuilder->setRenderPass(passes); collisionBuilder->setCullFaceMode(gfx::CullFaceMode::disabled()); collisionBuilder->setColorMode(gfx::ColorMode::alphaBlended()); - collisionBuilder->setVertexAttrName(CollisionPosAttribName); + collisionBuilder->setVertexAttrNameId(idCollisionPosAttribName); for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); @@ -1085,7 +1100,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, if (hasCollisionBox) { const auto& collisionBox = isText ? bucket.textCollisionBox : bucket.iconCollisionBox; if (const auto shader = std::static_pointer_cast( - collisionBoxGroup->getOrCreateShader(context, {}, CollisionPosAttribName))) { + collisionBoxGroup->getOrCreateShader( + context, {}, StringIndexer::get(idCollisionPosAttribName)))) { collisionBuilder->setDrawableName(layerCollisionPrefix + suffix + "box"); collisionBuilder->setShader(shader); addVertices(collisionBox->vertices().vector(), staticVertexAndAttributes); @@ -1102,7 +1118,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, if (hasCollisionCircle) { const auto& collisionCircle = isText ? bucket.textCollisionCircle : bucket.iconCollisionCircle; if (const auto shader = std::static_pointer_cast( - collisionCircleGroup->getOrCreateShader(context, {}, CollisionPosAttribName))) { + collisionCircleGroup->getOrCreateShader( + context, {}, StringIndexer::get(idCollisionPosAttribName)))) { collisionBuilder->setDrawableName(layerCollisionPrefix + suffix + "circle"); collisionBuilder->setShader(shader); addVertices(collisionCircle->vertices().vector(), staticVertexAndAttributes); @@ -1129,10 +1146,13 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, // If we already have drawables for this tile, update them. if (tileLayerGroup->getDrawableCount(passes, tileID) > 0) { + gfx::UniformBufferPtr textInterpUBO, iconInterpUBO; + // Just update the drawables we already created tileLayerGroup->visitDrawables(passes, tileID, [&](gfx::Drawable& drawable) { const auto& evaluated = getEvaluated(renderData.layerProperties); - updateTileDrawable(drawable, context, bucket, bucketPaintProperties, evaluated, state); + updateTileDrawable( + drawable, context, bucket, bucketPaintProperties, evaluated, state, textInterpUBO, iconInterpUBO); }); // re-create collision drawables @@ -1181,6 +1201,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, struct TileInfo { RawVertexVec textVertices, iconVertices; gfx::DrawableTweakerPtr textTweaker, iconTweaker; + gfx::UniformBufferPtr textInterp, iconInterp; }; std::unordered_map tileCache; @@ -1220,101 +1241,105 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders, evaluated.get().constantOr(1); const auto iconFill = evaluated.get().constantOr(Color::black()).a > 0.0f; - const auto interpolateUBO = buildInterpUBO(bucketPaintProperties, isText, currentZoom); + // Share interpolation UBOs across all the elements of the same type in each tile + auto& interpUBO = isText ? tileInfo.textInterp : tileInfo.iconInterp; + if (!interpUBO) { + const auto interpolateBuf = buildInterpUBO(bucketPaintProperties, isText, currentZoom); + interpUBO = context.createUniformBuffer(&interpolateBuf, sizeof(interpolateBuf)); + } if (builder) { builder->clearTweakers(); } - const auto draw = [&](const gfx::ShaderGroupPtr& shaderGroup, - const bool isHalo, - const std::string_view suffix) { - if (!shaderGroup) { - return; - } + const auto draw = + [&](const gfx::ShaderGroupPtr& shaderGroup, const bool isHalo, const std::string_view suffix) { + if (!shaderGroup) { + return; + } - // We can use the same tweakers for all the segments in a tile - if (isText && !tileInfo.textTweaker) { - const bool textSizeIsZoomConstant = - bucket.textSizeBinder->evaluateForZoom(static_cast(state.getZoom())).isZoomConstant; - tileInfo.textTweaker = std::make_shared(atlases, - iconTexUniformName, - texUniformName, - isText, - false, - values.rotationAlignment, - false, - textSizeIsZoomConstant); - } - if (!isText && !tileInfo.iconTweaker) { - const bool iconScaled = layout.get().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear; - tileInfo.iconTweaker = std::make_shared(atlases, - iconTexUniformName, - texUniformName, - isText, - sdfIcons, - values.rotationAlignment, - iconScaled, - false); - } + // We can use the same tweakers for all the segments in a tile + if (isText && !tileInfo.textTweaker) { + const bool textSizeIsZoomConstant = + bucket.textSizeBinder->evaluateForZoom(static_cast(state.getZoom())).isZoomConstant; + tileInfo.textTweaker = std::make_shared(atlases, + idTexIconUniformName, + idTexUniformName, + isText, + false, + values.rotationAlignment, + false, + textSizeIsZoomConstant); + } + if (!isText && !tileInfo.iconTweaker) { + const bool iconScaled = layout.get().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear; + tileInfo.iconTweaker = std::make_shared(atlases, + idTexIconUniformName, + idTexUniformName, + isText, + sdfIcons, + values.rotationAlignment, + iconScaled, + false); + } - if (!builder) { - builder = context.createDrawableBuilder(layerPrefix); - builder->setSubLayerIndex(0); - builder->setEnableStencil(false); - builder->setRenderPass(passes); - builder->setCullFaceMode(gfx::CullFaceMode::disabled()); - builder->setDepthType(gfx::DepthMaskType::ReadOnly); - builder->setColorMode( - ((mbgl::underlying_type(passes) & mbgl::underlying_type(RenderPass::Translucent)) != 0) - ? gfx::ColorMode::alphaBlended() - : gfx::ColorMode::unblended()); - builder->setVertexAttrName(posOffsetAttribName); - } + if (!builder) { + builder = context.createDrawableBuilder(layerPrefix); + builder->setSubLayerIndex(0); + builder->setEnableStencil(false); + builder->setRenderPass(passes); + builder->setCullFaceMode(gfx::CullFaceMode::disabled()); + builder->setDepthType(gfx::DepthMaskType::ReadOnly); + builder->setColorMode( + ((mbgl::underlying_type(passes) & mbgl::underlying_type(RenderPass::Translucent)) != 0) + ? gfx::ColorMode::alphaBlended() + : gfx::ColorMode::unblended()); + builder->setVertexAttrNameId(idPosOffsetAttribName); + } - if (!shaderGroup) { - return; - } - const auto shader = std::static_pointer_cast( - shaderGroup->getOrCreateShader(context, uniformProps, posOffsetAttribName)); - if (!shader) { - return; - } - builder->setShader(shader); + if (!shaderGroup) { + return; + } + const auto shader = std::static_pointer_cast( + shaderGroup->getOrCreateShader(context, uniformProps, StringIndexer::get(idPosOffsetAttribName))); + if (!shader) { + return; + } + builder->setShader(shader); - builder->clearTweakers(); - builder->addTweaker(isText ? tileInfo.textTweaker : tileInfo.iconTweaker); - builder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short4); - builder->setDrawableName(layerPrefix + std::string(suffix)); - builder->setVertexAttributes(attribs); + builder->clearTweakers(); + builder->addTweaker(isText ? tileInfo.textTweaker : tileInfo.iconTweaker); + builder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short4); + builder->setDrawableName(layerPrefix + std::string(suffix)); + builder->setVertexAttributes(attribs); - builder->setSegments(gfx::Triangles(), buffer.sharedTriangles, &renderable.segment.get(), 1); + builder->setSegments(gfx::Triangles(), buffer.sharedTriangles, &renderable.segment.get(), 1); - builder->flush(); + builder->flush(); - for (auto& drawable : builder->clearDrawables()) { - drawable->setTileID(tileID); + for (auto& drawable : builder->clearDrawables()) { + drawable->setTileID(tileID); - auto drawData = std::make_unique( - /*.isHalo=*/isHalo, - /*.bucketVaraiblePlacement=*/bucket.hasVariablePlacement, - /*.symbolType=*/renderable.type, - /*.pitchAlignment=*/values.pitchAlignment, - /*.rotationAlignment=*/values.rotationAlignment, - /*.placement=*/layout.get(), - /*.textFit=*/layout.get()); + auto drawData = std::make_unique( + /*.isHalo=*/isHalo, + /*.bucketVaraiblePlacement=*/bucket.hasVariablePlacement, + /*.symbolType=*/renderable.type, + /*.pitchAlignment=*/values.pitchAlignment, + /*.rotationAlignment=*/values.rotationAlignment, + /*.placement=*/layout.get(), + /*.textFit=*/layout.get()); - const auto tileUBO = buildTileUBO(bucket, *drawData, currentZoom); - drawable->setData(std::move(drawData)); + const auto tileUBO = buildTileUBO(bucket, *drawData, currentZoom); + drawable->setData(std::move(drawData)); - auto& uniforms = drawable->mutableUniformBuffers(); - uniforms.createOrUpdate(SymbolLayerTweaker::SymbolDrawableTilePropsUBOName, &tileUBO, context); - uniforms.createOrUpdate(SymbolLayerTweaker::SymbolDrawableInterpolateUBOName, &interpolateUBO, context); + auto& uniforms = drawable->mutableUniformBuffers(); + uniforms.createOrUpdate(SymbolLayerTweaker::idSymbolDrawableTilePropsUBOName, &tileUBO, context); + uniforms.addOrReplace(SymbolLayerTweaker::idSymbolDrawableInterpolateUBOName, interpUBO); - tileLayerGroup->addDrawable(passes, tileID, std::move(drawable)); - ++stats.drawablesAdded; - } - }; + tileLayerGroup->addDrawable(passes, tileID, std::move(drawable)); + ++stats.drawablesAdded; + } + }; if (isText) { if (bucket.iconsInText) { diff --git a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp index 3dc563af4..7fe815239 100644 --- a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp @@ -63,9 +63,9 @@ struct alignas(16) SymbolDrawablePaintUBO { }; static_assert(sizeof(SymbolDrawablePaintUBO) == 3 * 16); -Size getTexSize(const gfx::Drawable& drawable, const std::string_view name) { +Size getTexSize(const gfx::Drawable& drawable, const StringIdentity nameId) { if (const auto& shader = drawable.getShader()) { - if (const auto index = shader->getSamplerLocation(name)) { + if (const auto index = shader->getSamplerLocation(nameId)) { if (const auto& tex = drawable.getTexture(*index)) { return tex->getSize(); } @@ -78,8 +78,8 @@ std::array toArray(const Size& s) { return util::cast(std::array{s.width, s.height}); } -constexpr auto texUniformName = "u_texture"; -constexpr auto texIconUniformName = "u_texture_icon"; +static const StringIdentity idTexUniformName = StringIndexer::get("u_texture"); +static const StringIdentity idTexIconUniformName = StringIndexer::get("u_texture_icon"); SymbolDrawablePaintUBO buildPaintUBO(bool isText, const SymbolPaintProperties::PossiblyEvaluated& evaluated) { return { @@ -96,6 +96,14 @@ SymbolDrawablePaintUBO buildPaintUBO(bool isText, const SymbolPaintProperties::P } // namespace +const StringIdentity SymbolLayerTweaker::idSymbolDrawableUBOName = StringIndexer::get("SymbolDrawableUBO"); +const StringIdentity SymbolLayerTweaker::idSymbolDynamicUBOName = StringIndexer::get("SymbolDynamicUBO"); +const StringIdentity SymbolLayerTweaker::idSymbolDrawablePaintUBOName = StringIndexer::get("SymbolDrawablePaintUBO"); +const StringIdentity SymbolLayerTweaker::idSymbolDrawableTilePropsUBOName = StringIndexer::get( + "SymbolDrawableTilePropsUBO"); +const StringIdentity SymbolLayerTweaker::idSymbolDrawableInterpolateUBOName = StringIndexer::get( + "SymbolDrawableInterpolateUBO"); + void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { @@ -121,14 +129,14 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, const auto& symbolData = static_cast(*drawable.getData()); const auto isText = (symbolData.symbolType == SymbolType::Text); - if (isText && !textPaintBuffer) { + if (isText && (!textPaintBuffer || propertiesUpdated)) { const auto props = buildPaintUBO(true, evaluated); textPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props)); - } - if (!isText && !iconPaintBuffer) { + } else if (!isText && (!iconPaintBuffer || propertiesUpdated)) { const auto props = buildPaintUBO(false, evaluated); iconPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props)); } + propertiesUpdated = false; // from RenderTile::translatedMatrix const auto translate = isText ? evaluated.get() : evaluated.get(); @@ -169,8 +177,8 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, /*.label_plane_matrix=*/util::cast(labelPlaneMatrix), /*.coord_matrix=*/util::cast(glCoordMatrix), - /*.texsize=*/toArray(getTexSize(drawable, texUniformName)), - /*.texsize_icon=*/toArray(getTexSize(drawable, texIconUniformName)), + /*.texsize=*/toArray(getTexSize(drawable, idTexUniformName)), + /*.texsize_icon=*/toArray(getTexSize(drawable, idTexIconUniformName)), /*.gamma_scale=*/gammaScale, /*.device_pixel_ratio=*/parameters.pixelRatio, @@ -187,9 +195,9 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, /*.pad2=*/{0, 0}}; auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.createOrUpdate(SymbolDrawableUBOName, &drawableUBO, context); - uniforms.createOrUpdate(SymbolDynamicUBOName, &dynamicUBO, context); - uniforms.addOrReplace(SymbolDrawablePaintUBOName, isText ? textPaintBuffer : iconPaintBuffer); + uniforms.createOrUpdate(idSymbolDrawableUBOName, &drawableUBO, context); + uniforms.createOrUpdate(idSymbolDynamicUBOName, &dynamicUBO, context); + uniforms.addOrReplace(idSymbolDrawablePaintUBOName, isText ? textPaintBuffer : iconPaintBuffer); }); } diff --git a/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp b/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp index 98f2b14eb..c650f2612 100644 --- a/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/symbol_layer_tweaker.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -19,11 +20,11 @@ public: void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; - static constexpr std::string_view SymbolDrawableUBOName = "SymbolDrawableUBO"; - static constexpr std::string_view SymbolDynamicUBOName = "SymbolDynamicUBO"; - static constexpr std::string_view SymbolDrawablePaintUBOName = "SymbolDrawablePaintUBO"; - static constexpr std::string_view SymbolDrawableTilePropsUBOName = "SymbolDrawableTilePropsUBO"; - static constexpr std::string_view SymbolDrawableInterpolateUBOName = "SymbolDrawableInterpolateUBO"; + static const StringIdentity idSymbolDrawableUBOName; + static const StringIdentity idSymbolDynamicUBOName; + static const StringIdentity idSymbolDrawablePaintUBOName; + static const StringIdentity idSymbolDrawableTilePropsUBOName; + static const StringIdentity idSymbolDrawableInterpolateUBOName; private: gfx::UniformBufferPtr textPaintBuffer; diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index a71810e2f..f8b5793f0 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -72,8 +72,9 @@ public: PatternAtlas& patternAtlas_, RenderLayerReferences layersNeedPlacement_, Immutable placement_, - bool updateSymbolOpacities_) - : RenderTree(std::move(parameters_)), + bool updateSymbolOpacities_, + double startTime_) + : RenderTree(std::move(parameters_), startTime_), layerRenderItems(std::move(layerRenderItems_)), sourceRenderItems(std::move(sourceRenderItems_)), lineAtlas(lineAtlas_), @@ -143,6 +144,8 @@ void RenderOrchestrator::setObserver(RendererObserver* observer_) { std::unique_ptr RenderOrchestrator::createRenderTree( const std::shared_ptr& updateParameters) { + const auto startTime = util::MonotonicTimer::now().count(); + const bool isMapModeContinuous = updateParameters->mode == MapMode::Continuous; if (!isMapModeContinuous) { // Reset zoom history state. @@ -504,7 +507,8 @@ std::unique_ptr RenderOrchestrator::createRenderTree( *patternAtlas, std::move(layersNeedPlacement), placementController.getPlacement(), - symbolBucketsChanged); + symbolBucketsChanged, + startTime); } std::vector RenderOrchestrator::queryRenderedFeatures(const ScreenLineString& geometry, diff --git a/src/mbgl/renderer/render_tree.hpp b/src/mbgl/renderer/render_tree.hpp index 42383dec0..4d4d3e6b3 100644 --- a/src/mbgl/renderer/render_tree.hpp +++ b/src/mbgl/renderer/render_tree.hpp @@ -3,6 +3,7 @@ #include #endif #include +#include #include #include @@ -83,12 +84,17 @@ public: // Parameters const RenderTreeParameters& getParameters() const { return *parameters; } + double getElapsedTime() const { return util::MonotonicTimer::now().count() - startTime; } + protected: - RenderTree(std::unique_ptr parameters_) - : parameters(std::move(parameters_)) { + RenderTree(std::unique_ptr parameters_, double startTime_) + : parameters(std::move(parameters_)), + startTime(startTime_) { assert(parameters); } std::unique_ptr parameters; + + double startTime; }; } // namespace mbgl diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index d13648b2b..e63f7afd5 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -406,7 +406,8 @@ void Renderer::Impl::render(const RenderTree& renderTree, observer->onDidFinishRenderingFrame( renderTreeParameters.loaded ? RendererObserver::RenderMode::Full : RendererObserver::RenderMode::Partial, renderTreeParameters.needsRepaint, - renderTreeParameters.placementChanged); + renderTreeParameters.placementChanged, + renderTree.getElapsedTime()); if (!renderTreeParameters.loaded) { renderState = RenderState::Partial; diff --git a/src/mbgl/renderer/sources/render_tile_source.cpp b/src/mbgl/renderer/sources/render_tile_source.cpp index f23dbfe98..fe81eec85 100644 --- a/src/mbgl/renderer/sources/render_tile_source.cpp +++ b/src/mbgl/renderer/sources/render_tile_source.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #endif @@ -54,7 +55,6 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr float pad1, pad2, pad3; }; static_assert(sizeof(DebugUBO) % 16 == 0); - constexpr auto DebugUBOName = "DebugUBO"; // initialize auto& context = parameters.context; @@ -67,7 +67,8 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr } // create a builder - constexpr auto VertexAttribName = "a_pos"; + static const StringIdentity idVertexAttribName = StringIndexer::get("a_pos"); + static const StringIdentity idDebugUBOName = StringIndexer::get("DebugUBO"); std::unique_ptr builder = context.createDrawableBuilder("debug-builder"); builder->setShader(debugShader); builder->setRenderPass(renderPass); @@ -75,7 +76,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr builder->setColorMode(gfx::ColorMode::unblended()); builder->setCullFaceMode(gfx::CullFaceMode::disabled()); builder->setEnableStencil(false); - builder->setVertexAttrName(VertexAttribName); + builder->setVertexAttrNameId(idVertexAttribName); // add or get the layer group for a debug type const auto addOrGetLayerGroupForType = [&debugLayerGroups, &context]( @@ -108,8 +109,8 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr texture->setImage(emptyImage); texture->setSamplerConfiguration( {gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); - constexpr auto DebugOverlayUniformName = "u_overlay"; - samplerLocation = debugShader->getSamplerLocation(DebugOverlayUniformName); + static const StringIdentity idDebugOverlayUniformName = StringIndexer::get("u_overlay"); + samplerLocation = debugShader->getSamplerLocation(idDebugOverlayUniformName); } assert(samplerLocation.has_value()); if (!samplerLocation.has_value()) return; @@ -120,7 +121,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr auto updatedCount = tileLayerGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { // update existing drawable auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.createOrUpdate(DebugUBOName, &debugUBO, context); + uniforms.createOrUpdate(idDebugUBOName, &debugUBO, context); }); return updatedCount; }; @@ -149,7 +150,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr for (auto& drawable : builder->clearDrawables()) { drawable->setTileID(tileID); auto& uniforms = drawable->mutableUniformBuffers(); - uniforms.createOrUpdate(DebugUBOName, &debugUBO, context); + uniforms.createOrUpdate(idDebugUBOName, &debugUBO, context); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); } diff --git a/src/mbgl/renderer/tile_layer_group.cpp b/src/mbgl/renderer/tile_layer_group.cpp index a81b374c3..24e5820af 100644 --- a/src/mbgl/renderer/tile_layer_group.cpp +++ b/src/mbgl/renderer/tile_layer_group.cpp @@ -23,8 +23,7 @@ struct TileLayerGroupTileKey { }; struct TileLayerGroup::Impl { - Impl(std::size_t initialCapacity) - : drawablesByTile(initialCapacity) {} + Impl(std::size_t initialCapacity) { drawablesByTile.reserve(initialCapacity); } using TileMap = std::unordered_multimap; TileMap drawablesByTile; diff --git a/src/mbgl/shaders/gl/shader_program_gl.cpp b/src/mbgl/shaders/gl/shader_program_gl.cpp index f945fa2e4..364dd16f9 100644 --- a/src/mbgl/shaders/gl/shader_program_gl.cpp +++ b/src/mbgl/shaders/gl/shader_program_gl.cpp @@ -71,10 +71,11 @@ gfx::AttributeDataType mapType(platform::GLenum attrType) { using namespace platform; -void addAttr(VertexAttributeArrayGL& attrs, const char* name, GLint index, GLsizei length, GLint count, GLenum glType) { +void addAttr( + VertexAttributeArrayGL& attrs, const StringIdentity id, GLint index, GLsizei length, GLint count, GLenum glType) { const auto elementType = mapType(glType); if (elementType != gfx::AttributeDataType::Invalid && length > 0) { - if (const auto& newAttr = attrs.add(name, index, elementType, count)) { + if (const auto& newAttr = attrs.add(id, index, elementType, count)) { const auto& glAttr = static_cast(newAttr.get()); glAttr->setGLType(glType); } @@ -89,21 +90,27 @@ ShaderProgramGL::ShaderProgramGL(UniqueProgram&& glProgram_) ShaderProgramGL::ShaderProgramGL(UniqueProgram&& program, UniformBlockArrayGL&& uniformBlocks_, - VertexAttributeArrayGL&& attributes_) + VertexAttributeArrayGL&& attributes_, + SamplerLocationMap&& samplerLocations_) : ShaderProgramBase(), glProgram(std::move(program)), uniformBlocks(std::move(uniformBlocks_)), - vertexAttributes(std::move(attributes_)) {} + vertexAttributes(std::move(attributes_)), + samplerLocations(std::move(samplerLocations_)) {} ShaderProgramGL::ShaderProgramGL(ShaderProgramGL&& other) : ShaderProgramBase(std::forward(other)), glProgram(std::move(other.glProgram)), uniformBlocks(std::move(other.uniformBlocks)), - vertexAttributes(std::move(other.vertexAttributes)) {} + vertexAttributes(std::move(other.vertexAttributes)), + samplerLocations(std::move(other.samplerLocations)) {} -std::optional ShaderProgramGL::getSamplerLocation(const std::string_view name) const { - GLint sampler_location = MBGL_CHECK_ERROR(glGetUniformLocation(glProgram, name.data())); - return (sampler_location == -1) ? std::optional{} : sampler_location; +std::optional ShaderProgramGL::getSamplerLocation(const StringIdentity id) const { + std::optional result{}; + if (auto it = samplerLocations.find(id); it != samplerLocations.end()) { + result = it->second; + } + return result; } std::shared_ptr ShaderProgramGL::create(Context& context, @@ -151,7 +158,29 @@ std::shared_ptr ShaderProgramGL::create(Context& context, MBGL_CHECK_ERROR(glGetActiveUniformBlockiv(program, index, GL_UNIFORM_BLOCK_DATA_SIZE, &size)); assert(length > 0 && size > 0); MBGL_CHECK_ERROR(glUniformBlockBinding(program, index, binding)); - uniformBlocks.add(name.data(), index, size); + uniformBlocks.add(StringIndexer::get(name.data()), index, size); + } + + SamplerLocationMap samplerLocations; + GLint numActiveUniforms = 0; + MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numActiveUniforms)); + MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength)); + name.resize(maxLength); + for (GLint index = 0; index < numActiveUniforms; ++index) { + GLsizei actualLength = 0; + GLint size = 0; + GLenum type = GL_ZERO; + + MBGL_CHECK_ERROR(glGetActiveUniform(program, index, maxLength, &actualLength, &size, &type, name.data())); + + if (type == GL_SAMPLER_2D) { + // This uniform is a texture sampler + GLint location = MBGL_CHECK_ERROR(glGetUniformLocation(program, name.data())); + assert(location != -1); + if (location != -1) { + samplerLocations[StringIndexer::get(name.data())] = location; + } + } } VertexAttributeArrayGL attrs; @@ -169,10 +198,11 @@ std::shared_ptr ShaderProgramGL::create(Context& context, continue; } const GLint location = MBGL_CHECK_ERROR(glGetAttribLocation(program, name.data())); - addAttr(attrs, name.data(), location, length, size, glType); + addAttr(attrs, StringIndexer::get(name.data()), location, length, size, glType); } - return std::make_shared(std::move(program), std::move(uniformBlocks), std::move(attrs)); + return std::make_shared( + std::move(program), std::move(uniformBlocks), std::move(attrs), std::move(samplerLocations)); } } // namespace gl diff --git a/src/mbgl/shaders/mtl/shader_program.cpp b/src/mbgl/shaders/mtl/shader_program.cpp index 164524a41..6a77f9ff6 100644 --- a/src/mbgl/shaders/mtl/shader_program.cpp +++ b/src/mbgl/shaders/mtl/shader_program.cpp @@ -10,12 +10,14 @@ #include #include #include +#include #include #include #include #include +#include using namespace std::string_literals; @@ -160,23 +162,20 @@ MTLRenderPipelineStatePtr ShaderProgram::getRenderPipelineState(const gfx::Rende return rps; } -std::optional ShaderProgram::getSamplerLocation(std::string_view name) const { - std::size_t index = 0; - for (const auto& bindingName : textureBindings) { - if (bindingName == name) { - return index; - } - index += 1; +std::optional ShaderProgram::getSamplerLocation(const StringIdentity id) const { + if (auto it = textureBindings.find(id); it != textureBindings.end()) { + return it->second; } return std::nullopt; } void ShaderProgram::initAttribute(const shaders::AttributeInfo& info) { - vertexAttributes.add(std::string(info.name), static_cast(info.index), info.dataType, info.count); + vertexAttributes.add(StringIndexer::get(info.name.data()), static_cast(info.index), info.dataType, info.count); } void ShaderProgram::initUniformBlock(const shaders::UniformBlockInfo& info) { - if (const auto& block_ = uniformBlocks.add(info.name.data(), static_cast(info.index), info.size)) { + if (const auto& block_ = uniformBlocks.add( + StringIndexer::get(info.name.data()), static_cast(info.index), info.size)) { auto& block = static_cast(*block_); block.setBindVertex(info.vertex); block.setBindFragment(info.fragment); @@ -184,8 +183,7 @@ void ShaderProgram::initUniformBlock(const shaders::UniformBlockInfo& info) { } void ShaderProgram::initTexture(const shaders::TextureInfo& info) { - textureBindings.resize(std::max(textureBindings.size(), info.index + 1)); - textureBindings[info.index] = info.name; + textureBindings[StringIndexer::get(info.name.data())] = info.index; } } // namespace mtl diff --git a/src/mbgl/style/paint_property.hpp b/src/mbgl/style/paint_property.hpp index 782cc4860..b7ac4ae4f 100644 --- a/src/mbgl/style/paint_property.hpp +++ b/src/mbgl/style/paint_property.hpp @@ -7,9 +7,14 @@ #include #include +#include +#include #include namespace mbgl { + +using StringIdentity = std::size_t; + namespace style { template @@ -41,8 +46,12 @@ public: using UniformList = TypeList; static constexpr const std::array AttributeNames = {A::name()}; + static std::array, 1> AttributeNameIDs; }; +template +std::array, 1> DataDrivenPaintProperty::AttributeNameIDs = {std::nullopt}; + template class CrossFadedDataDrivenPaintProperty { public: @@ -60,8 +69,13 @@ public: using UniformList = TypeList; static constexpr const std::array AttributeNames = {A1::name(), A2::name()}; + static std::array, 2> AttributeNameIDs; }; +template +std::array, 2> CrossFadedDataDrivenPaintProperty::AttributeNameIDs = { + std::nullopt, std::nullopt}; + template class CrossFadedPaintProperty { public: diff --git a/src/mbgl/util/string_indexer.cpp b/src/mbgl/util/string_indexer.cpp new file mode 100644 index 000000000..3f2f6d9fb --- /dev/null +++ b/src/mbgl/util/string_indexer.cpp @@ -0,0 +1,70 @@ +#include + +#include + +namespace mbgl { + +namespace { +const std::string empty; +} + +StringIdentity StringIndexer::get(const std::string& string) { + { + std::shared_lock readerLock(instance().sharedMutex); + + auto& stringToIdentity = instance().stringToIdentity; + [[maybe_unused]] auto& identityToString = instance().identityToString; + assert(stringToIdentity.size() == identityToString.size()); + + if (auto it = stringToIdentity.find(string); it != stringToIdentity.end()) { + return it->second; + } + } + + { + std::unique_lock writerLock(instance().sharedMutex); + + auto& stringToIdentity = instance().stringToIdentity; + auto& identityToString = instance().identityToString; + assert(stringToIdentity.size() == identityToString.size()); + + StringIdentity id = identityToString.size(); + auto result = stringToIdentity.insert({string, id}); + if (result.second) { + // this writer made the insert + identityToString.push_back(string); + } else { + // another writer inserted into the map + id = result.first->second; + } + return id; + } +} + +const std::string& StringIndexer::get(const StringIdentity id) { + std::shared_lock readerLock(instance().sharedMutex); + + const auto& identityToString = instance().identityToString; + assert(id < identityToString.size()); + + return id < identityToString.size() ? identityToString[id] : empty; +} + +void StringIndexer::clear() { + std::unique_lock writerLock(instance().sharedMutex); + + instance().stringToIdentity.clear(); + instance().identityToString.clear(); +} + +size_t StringIndexer::size() { + std::shared_lock readerLock(instance().sharedMutex); + + [[maybe_unused]] auto& stringToIdentity = instance().stringToIdentity; + auto& identityToString = instance().identityToString; + assert(stringToIdentity.size() == identityToString.size()); + + return identityToString.size(); +} + +} // namespace mbgl diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 25437cd90..c12e11f13 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -99,6 +99,7 @@ add_library( ${PROJECT_SOURCE_DIR}/test/util/rotation.test.cpp ${PROJECT_SOURCE_DIR}/test/util/run_loop.test.cpp ${PROJECT_SOURCE_DIR}/test/util/string.test.cpp + ${PROJECT_SOURCE_DIR}/test/util/string_indexer.test.cpp ${PROJECT_SOURCE_DIR}/test/util/text_conversions.test.cpp ${PROJECT_SOURCE_DIR}/test/util/thread.test.cpp ${PROJECT_SOURCE_DIR}/test/util/thread_local.test.cpp diff --git a/test/util/string_indexer.test.cpp b/test/util/string_indexer.test.cpp new file mode 100644 index 000000000..ba1f0f95e --- /dev/null +++ b/test/util/string_indexer.test.cpp @@ -0,0 +1,49 @@ +#include + +#include + +#include + +using namespace mbgl; + +TEST(StringIndexer, AddStrings) { + StringIndexer::clear(); + EXPECT_EQ(StringIndexer::size(), 0); + + const auto id1 = StringIndexer::get("test string1"); + EXPECT_EQ(id1, 0); + EXPECT_EQ(StringIndexer::size(), 1); + + const auto id2 = StringIndexer::get("test string2"); + EXPECT_EQ(id2, 1); + EXPECT_EQ(StringIndexer::size(), 2); +} + +TEST(StringIndexer, GetString) { + StringIndexer::clear(); + EXPECT_EQ(StringIndexer::size(), 0); + + constexpr auto str = "test string1"; + + const auto id1 = StringIndexer::get(str); + EXPECT_EQ(id1, 0); + EXPECT_EQ(StringIndexer::size(), 1); + + const std::string str1 = StringIndexer::get(id1); + EXPECT_EQ(str, str1); + + const auto str2 = str; + const auto id2 = StringIndexer::get(str2); + EXPECT_EQ(id1, id2); +} + +TEST(StringIndexer, GetOOBIdentity) { + StringIndexer::clear(); + EXPECT_EQ(StringIndexer::size(), 0); + + std::string str; + EXPECT_DEATH_IF_SUPPORTED(str = StringIndexer::get(42), "id < identityToString.size()"); + EXPECT_TRUE(str.empty()); + EXPECT_DEATH_IF_SUPPORTED(str = StringIndexer::get(-1), "id < identityToString.size()"); + EXPECT_TRUE(str.empty()); +}