Drawable performance fixes (2) (#1610)
Co-authored-by: Tim Sylvester <tim@wetdogweather.com> Co-authored-by: Bart Louwers <bart.louwers@gmail.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <mbgl/gfx/drawable_tweaker.hpp>
|
||||
#include <mbgl/style/types.hpp>
|
||||
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -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;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/gfx/types.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
@@ -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;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
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<std::string, std::unique_ptr<UniformBlock>>;
|
||||
using UniformBlockMap = std::unordered_map<StringIdentity, std::unique_ptr<UniformBlock>>;
|
||||
|
||||
/// @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<UniformBlock>& get(const std::string& name) const;
|
||||
const std::unique_ptr<UniformBlock>& 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<UniformBlock>& add(std::string name, int index, std::size_t size);
|
||||
const std::unique_ptr<UniformBlock>& 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<UniformBlock>& add(std::string name, std::unique_ptr<UniformBlock>&& uniformBlock) {
|
||||
const auto result = uniformBlockMap.insert(std::make_pair(std::move(name), std::unique_ptr<UniformBlock>()));
|
||||
const std::unique_ptr<UniformBlock>& add(const StringIdentity id, std::unique_ptr<UniformBlock>&& uniformBlock) {
|
||||
const auto result = uniformBlockMap.insert(std::make_pair(id, std::unique_ptr<UniformBlock>()));
|
||||
if (result.second) {
|
||||
result.first->second = std::move(uniformBlock);
|
||||
return result.first->second;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@@ -44,9 +46,9 @@ protected:
|
||||
/// Stores a collection of uniform buffers by name
|
||||
class UniformBufferArray {
|
||||
public:
|
||||
using UniformBufferMap = std::unordered_map<std::string, std::shared_ptr<UniformBuffer>>;
|
||||
using UniformBufferMap = std::unordered_map<StringIdentity, std::shared_ptr<UniformBuffer>>;
|
||||
|
||||
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<UniformBuffer>& get(std::string_view name) const;
|
||||
const std::shared_ptr<UniformBuffer>& get(const StringIdentity id) const;
|
||||
|
||||
/// Add a new uniform buffer element or replace the existing one.
|
||||
const std::shared_ptr<UniformBuffer>& addOrReplace(std::string_view name,
|
||||
const std::shared_ptr<UniformBuffer>& addOrReplace(const StringIdentity id,
|
||||
std::shared_ptr<UniformBuffer> uniformBuffer);
|
||||
|
||||
/// Create and add a new buffer or update an existing one
|
||||
void createOrUpdate(std::string_view name, const std::vector<uint8_t>& 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<uint8_t>& data, gfx::Context&);
|
||||
void createOrUpdate(const StringIdentity id, const void* data, std::size_t size, gfx::Context&);
|
||||
template <typename T>
|
||||
std::enable_if_t<!std::is_pointer_v<T>> createOrUpdate(std::string_view name,
|
||||
std::enable_if_t<!std::is_pointer_v<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<UniformBuffer>& add(const std::string_view name, std::shared_ptr<UniformBuffer>&&);
|
||||
const std::shared_ptr<UniformBuffer>& add(const StringIdentity id, std::shared_ptr<UniformBuffer>&&);
|
||||
|
||||
virtual std::unique_ptr<UniformBuffer> copy(const UniformBuffer&) = 0;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <mbgl/gfx/gfx_types.hpp>
|
||||
#include <mbgl/renderer/paint_property_binder.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@@ -271,9 +272,9 @@ protected:
|
||||
/// Stores a collection of vertex attributes by name
|
||||
class VertexAttributeArray {
|
||||
public:
|
||||
using AttributeMap = std::unordered_map<std::string, std::unique_ptr<VertexAttribute>>;
|
||||
using AttributeMap = std::unordered_map<StringIdentity, std::unique_ptr<VertexAttribute>>;
|
||||
|
||||
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<VertexAttribute>& 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<VertexAttribute>& 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<VertexAttribute>& 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 <typename T>
|
||||
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<void(const std::string&, VertexAttribute&)>& f) {
|
||||
void visitAttributes(const std::function<void(const StringIdentity, VertexAttribute&)>& 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<void(const std::string&, const VertexAttribute&)>& f) const {
|
||||
void visitAttributes(const std::function<void(const StringIdentity, const VertexAttribute&)>& 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<void(const std::string&, VertexAttribute&, const UniqueVertexAttribute&)>;
|
||||
using ResolveDelegate =
|
||||
std::function<void(const StringIdentity, VertexAttribute&, const std::unique_ptr<VertexAttribute>&)>;
|
||||
/// 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<DataDrivenPaintProperty>()) {
|
||||
using Attribute = typename DataDrivenPaintProperty::Attribute;
|
||||
using Type = typename Attribute::Type; // ::mbgl::gfx::AttributeType<type_, n_>
|
||||
using InterpType = ZoomInterpolatedAttributeType<Type>;
|
||||
#if !defined(NDEBUG)
|
||||
using Value = typename Type::Value; // std::array<T, N>
|
||||
using InterpValue = typename InterpType::Value; // std::array<T, 2*N>
|
||||
#endif
|
||||
|
||||
const auto vertexCount = binder->getVertexCount();
|
||||
const auto isConstant = evaluated.template get<DataDrivenPaintProperty>().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<uint32_t>(sharedVector->getRawSize());
|
||||
const bool isInterpolated = binder->isInterpolated();
|
||||
const auto dataType = isInterpolated ? InterpType::DataType : Type::DataType;
|
||||
assert(rawSize ==
|
||||
static_cast<uint32_t>(isInterpolated ? sizeof(InterpValue) : sizeof(Value)));
|
||||
assert(rawSize == static_cast<uint32_t>(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<VertexAttribute>&&);
|
||||
const UniqueVertexAttribute& add(const StringIdentity id, std::unique_ptr<VertexAttribute>&&);
|
||||
|
||||
virtual UniqueVertexAttribute create(int index, AttributeDataType dataType, std::size_t count) const {
|
||||
return std::make_unique<VertexAttribute>(index, dataType, count, count);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <mbgl/gl/vertex_array.hpp>
|
||||
#include <mbgl/gl/vertex_attribute_gl.hpp>
|
||||
#include <mbgl/programs/segment.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -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&);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<gfx::VertexAttribute> create(int index,
|
||||
gfx::AttributeDataType dataType,
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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&);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)) {}
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ public:
|
||||
|
||||
virtual void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) = 0;
|
||||
|
||||
void updateProperties(Immutable<style::LayerProperties>);
|
||||
|
||||
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<style::LayerProperties> evaluatedProperties;
|
||||
bool propertiesUpdated = true;
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
// For Metal, whether a property is provided through attribtues or uniforms is specified in
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#include <mbgl/gl/uniform_block_gl.hpp>
|
||||
#include <mbgl/gl/vertex_attribute_gl.hpp>
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -13,8 +16,13 @@ namespace gl {
|
||||
|
||||
class ShaderProgramGL final : public gfx::ShaderProgramBase {
|
||||
public:
|
||||
using SamplerLocationMap = std::unordered_map<StringIdentity, int>;
|
||||
|
||||
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<uint32_t> getSamplerLocation(std::string_view name) const override;
|
||||
std::optional<uint32_t> 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
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
const MTLVertexDescriptorPtr&,
|
||||
const gfx::ColorMode& colorMode) const;
|
||||
|
||||
std::optional<uint32_t> getSamplerLocation(std::string_view name) const override;
|
||||
std::optional<uint32_t> 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<std::string> textureBindings;
|
||||
std::unordered_map<StringIdentity, std::size_t> textureBindings;
|
||||
};
|
||||
|
||||
} // namespace mtl
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <mbgl/gfx/uniform_block.hpp>
|
||||
#include <mbgl/gfx/vertex_attribute.hpp>
|
||||
#include <mbgl/util/identity.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
@@ -18,8 +19,8 @@ protected:
|
||||
~ShaderProgramBase() noexcept override = default;
|
||||
|
||||
template <typename T>
|
||||
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<uint32_t> getSamplerLocation(std::string_view name) const = 0;
|
||||
virtual std::optional<uint32_t> getSamplerLocation(const StringIdentity) const = 0;
|
||||
|
||||
/// Get the available uniform blocks attached to this shader
|
||||
virtual const gfx::UniformBlockArray& getUniformBlocks() const = 0;
|
||||
|
||||
46
include/mbgl/util/string_indexer.hpp
Normal file
46
include/mbgl/util/string_indexer.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
|
||||
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<std::string, StringIdentity>;
|
||||
using VectorType = std::vector<std::string>;
|
||||
|
||||
static StringIndexer& instance() {
|
||||
static StringIndexer inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
MapType stringToIdentity;
|
||||
VectorType identityToString;
|
||||
std::shared_mutex sharedMutex;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -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); }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -2043,7 +2043,7 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
NSAssert(self.styleNames.count == self.styleURLs.count, @"Style names and URLs don’t match.");
|
||||
}
|
||||
|
||||
|
||||
@@ -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<std::string> 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<std::pair<std::string, double>> result;
|
||||
std::vector<std::pair<std::string, double> > 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::microseconds>(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::microseconds>(std::chrono::steady_clock::now() - started).count();
|
||||
const auto wallClockFPS = double(frames * 1e6) / duration;
|
||||
const auto frameTime = static_cast<double>(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);
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace mbgl {
|
||||
namespace bench {
|
||||
|
||||
const std::vector<Location> 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 },
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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 <typename T>
|
||||
std::enable_if_t<!std::is_pointer_v<T>, bool> emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& ptr,
|
||||
const T* data) {
|
||||
return emplaceOrUpdateUniformBuffer(ptr, data, sizeof(T));
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
#include <mbgl/gfx/vertex_attribute.hpp>
|
||||
#include <mbgl/renderer/render_pass.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
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<Impl>()) {}
|
||||
|
||||
|
||||
@@ -5,9 +5,6 @@ namespace gfx {
|
||||
|
||||
std::unique_ptr<UniformBlock> 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<UniformBlock>& UniformBlockArray::get(const std::string& name) const {
|
||||
const auto result = uniformBlockMap.find(name);
|
||||
const std::unique_ptr<UniformBlock>& UniformBlockArray::get(const StringIdentity id) const {
|
||||
const auto result = uniformBlockMap.find(id);
|
||||
return (result != uniformBlockMap.end()) ? result->second : nullref;
|
||||
}
|
||||
|
||||
const std::unique_ptr<UniformBlock>& 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<UniformBlock>()));
|
||||
const std::unique_ptr<UniformBlock>& UniformBlockArray::add(const StringIdentity id, int index, std::size_t size) {
|
||||
const auto result = uniformBlockMap.insert(std::make_pair(id, std::unique_ptr<UniformBlock>()));
|
||||
if (result.second) {
|
||||
result.first->second = create(index, size);
|
||||
return result.first->second;
|
||||
|
||||
@@ -7,9 +7,6 @@ namespace gfx {
|
||||
|
||||
std::shared_ptr<UniformBuffer> 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<UniformBuffer>& UniformBufferArray::get(const std::string_view name) const {
|
||||
const auto result = uniformBufferMap.find(std::string(name));
|
||||
const std::shared_ptr<UniformBuffer>& UniformBufferArray::get(const StringIdentity id) const {
|
||||
const auto result = uniformBufferMap.find(id);
|
||||
return (result != uniformBufferMap.end()) ? result->second : nullref;
|
||||
}
|
||||
|
||||
const std::shared_ptr<UniformBuffer>& UniformBufferArray::addOrReplace(const std::string_view name,
|
||||
const std::shared_ptr<UniformBuffer>& UniformBufferArray::addOrReplace(const StringIdentity id,
|
||||
std::shared_ptr<UniformBuffer> uniformBuffer) {
|
||||
const auto result = uniformBufferMap.insert(std::make_pair(name, std::shared_ptr<UniformBuffer>()));
|
||||
const auto result = uniformBufferMap.insert(std::make_pair(id, std::shared_ptr<UniformBuffer>()));
|
||||
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<uint8_t>& 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<UniformBuffer>& UniformBufferArray::add(const std::string_view name,
|
||||
const std::shared_ptr<UniformBuffer>& UniformBufferArray::add(const StringIdentity id,
|
||||
std::shared_ptr<UniformBuffer>&& uniformBuffer) {
|
||||
const auto result = uniformBufferMap.insert(std::make_pair(name, std::shared_ptr<UniformBuffer>()));
|
||||
const auto result = uniformBufferMap.insert(std::make_pair(id, std::shared_ptr<UniformBuffer>()));
|
||||
if (result.second) {
|
||||
result.first->second = std::move(uniformBuffer);
|
||||
return result.first->second;
|
||||
|
||||
@@ -19,9 +19,6 @@ std::size_t VertexAttribute::getCount() const {
|
||||
|
||||
std::unique_ptr<VertexAttribute> 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<VertexAttribute>& VertexAttributeArray::get(const std::string& name) const {
|
||||
const auto result = attrs.find(name);
|
||||
const std::unique_ptr<VertexAttribute>& VertexAttributeArray::get(const StringIdentity id) const {
|
||||
const auto result = attrs.find(id);
|
||||
return (result != attrs.end()) ? result->second : nullref;
|
||||
}
|
||||
|
||||
const std::unique_ptr<VertexAttribute>& VertexAttributeArray::add(std::string name,
|
||||
const std::unique_ptr<VertexAttribute>& 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<VertexAttribute>()));
|
||||
const auto result = attrs.insert(std::make_pair(id, std::unique_ptr<VertexAttribute>()));
|
||||
if (result.second) {
|
||||
result.first->second = create(index, dataType, count);
|
||||
return result.first->second;
|
||||
@@ -58,11 +55,11 @@ const std::unique_ptr<VertexAttribute>& VertexAttributeArray::add(std::string na
|
||||
}
|
||||
}
|
||||
|
||||
const std::unique_ptr<VertexAttribute>& VertexAttributeArray::getOrAdd(std::string name,
|
||||
const std::unique_ptr<VertexAttribute>& 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<VertexAttribute>()));
|
||||
const auto result = attrs.insert(std::make_pair(id, std::unique_ptr<VertexAttribute>()));
|
||||
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<VertexAttribute>&& attr) {
|
||||
const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr<VertexAttribute>()));
|
||||
const UniqueVertexAttribute& VertexAttributeArray::add(const StringIdentity id,
|
||||
std::unique_ptr<VertexAttribute>&& attr) {
|
||||
const auto result = attrs.insert(std::make_pair(id, std::unique_ptr<VertexAttribute>()));
|
||||
if (result.second) {
|
||||
result.first->second = std::move(attr);
|
||||
return result.first->second;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <mbgl/programs/segment.hpp>
|
||||
#include <mbgl/shaders/gl/shader_program_gl.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
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<std::size_t>(indexAttribute ? indexAttribute->getIndex() : -1);
|
||||
|
||||
std::vector<std::unique_ptr<gfx::VertexBufferResource>> vertexBuffers;
|
||||
|
||||
@@ -22,7 +22,7 @@ std::unique_ptr<gfx::Drawable::DrawSegment> DrawableGLBuilder::createSegment(gfx
|
||||
void DrawableGLBuilder::init() {
|
||||
auto& drawableGL = static_cast<DrawableGL&>(*currentDrawable);
|
||||
|
||||
drawableGL.setVertexAttrName(vertexAttrName);
|
||||
drawableGL.setVertexAttrNameId(vertexAttrNameId);
|
||||
|
||||
if (impl->rawVerticesCount) {
|
||||
auto raw = impl->rawVertices;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <mbgl/programs/segment.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/util/mat4.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@@ -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 {
|
||||
|
||||
@@ -196,10 +196,11 @@ gfx::AttributeBindingArray UploadPass::buildAttributeBindings(
|
||||
constexpr std::uint8_t padding = 0;
|
||||
|
||||
std::vector<std::uint8_t> allData;
|
||||
allData.reserve(vertexData.size() + (defaults.getTotalSize() + align) * vertexCount);
|
||||
|
||||
uint32_t vertexStride = 0;
|
||||
if (vertexAttributeIndex != static_cast<std::size_t>(-1)) {
|
||||
if (vertexAttributeIndex != static_cast<std::size_t>(-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<const VertexAttributeGL&>(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;
|
||||
}
|
||||
|
||||
|
||||
@@ -182,5 +182,18 @@ const std::vector<std::uint8_t>& 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<const VertexAttributeGL&>(*kv.second);
|
||||
if (const auto& shared = glAttrib.getSharedRawData()) {
|
||||
return shared->getDirty();
|
||||
}
|
||||
}
|
||||
return kv.second && kv.second->isDirty();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<void()>&) final;
|
||||
|
||||
@@ -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<gfx::OffscreenTexture> Context::createOffscreenTexture(Size, gfx::TextureChannelDataType) {
|
||||
|
||||
@@ -206,12 +206,14 @@ void Drawable::setVertices(std::vector<uint8_t>&& 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;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ std::unique_ptr<gfx::Drawable::DrawSegment> DrawableBuilder::createSegment(gfx::
|
||||
void DrawableBuilder::init() {
|
||||
auto& drawable = static_cast<Drawable&>(*currentDrawable);
|
||||
|
||||
drawable.setVertexAttrName(vertexAttrName);
|
||||
drawable.setVertexAttrNameId(vertexAttrNameId);
|
||||
|
||||
if (impl->rawVerticesCount) {
|
||||
auto raw = impl->rawVertices;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <mbgl/programs/segment.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/util/mat4.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <Foundation/NSSharedPtr.hpp>
|
||||
#include <Metal/MTLVertexDescriptor.hpp>
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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<const VertexAttribute&>(default_);
|
||||
const auto stride = defaultAttr.getStride();
|
||||
|
||||
@@ -40,6 +40,11 @@ mat4 LayerTweaker::getTileMatrix(const UnwrappedTileID& tileID,
|
||||
return RenderTile::translateVtxMatrix(tileID, tileMatrix, translation, anchor, state, inViewportPixelUnits);
|
||||
}
|
||||
|
||||
void LayerTweaker::updateProperties(Immutable<style::LayerProperties> 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();
|
||||
|
||||
@@ -9,14 +9,19 @@
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/style/layers/background_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
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<float>(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<BackgroundOpacity>(),
|
||||
/* .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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
#include <mbgl/style/layers/circle_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
#include <mbgl/shaders/mtl/circle.hpp>
|
||||
@@ -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<float>(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
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <mbgl/style/layers/fill_extrusion_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <mbgl/style/layers/fill_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
#include <mbgl/shaders/mtl/fill.hpp>
|
||||
@@ -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<float>(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<float>(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<float>(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<float>(matrix),
|
||||
/*.scale=*/{pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale},
|
||||
@@ -312,15 +348,15 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
|
||||
/*.texsize=*/{static_cast<float>(textureSize.width), static_cast<float>(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
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <mbgl/renderer/render_tree.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
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<float>(parameters.state.getZoom())),
|
||||
/* .padding = */ {0}};
|
||||
|
||||
uniforms.createOrUpdate(HeatmapDrawableUBOName, &drawableUBO, context);
|
||||
uniforms.createOrUpdate(idHeatmapDrawableUBOName, &drawableUBO, context);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <mbgl/renderer/render_tree.hpp>
|
||||
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <mbgl/renderer/render_tree.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
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<float, 2> 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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <mbgl/renderer/render_tree.hpp>
|
||||
#include <mbgl/style/layers/hillshade_layer_properties.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
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<float, 4>& 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<float>(drawableData.maxzoom)};
|
||||
|
||||
drawable.mutableUniformBuffers().createOrUpdate(
|
||||
HillshadePrepareDrawableUBOName, &drawableUBO, parameters.context);
|
||||
idHillshadePrepareDrawableUBOName, &drawableUBO, parameters.context);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/gfx/line_drawable_data.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
#include <mbgl/geometry/line_atlas.hpp>
|
||||
#include <mbgl/renderer/image_atlas.hpp>
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
@@ -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<float>(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<float>(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<LineDasharray>().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<float>(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
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,13 +10,15 @@
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/gfx/image_drawable_data.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
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<RasterBrightnessMax>(),
|
||||
/*.saturation_factor = */ saturationFactor(evaluated.get<RasterSaturation>()),
|
||||
/*.contrast_factor = */ contrastFactor(evaluated.get<RasterContrast>()),
|
||||
/* .overdrawInspector = */ overdrawInspector,
|
||||
/*.overdrawInspector = */ overdrawInspector,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0};
|
||||
auto& uniforms = drawable.mutableUniformBuffers();
|
||||
uniforms.createOrUpdate("RasterDrawableUBO", &drawableUBO, parameters.context);
|
||||
uniforms.createOrUpdate(idRasterDrawableUBOName, &drawableUBO, parameters.context);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <mbgl/renderer/update_parameters.hpp>
|
||||
#include <mbgl/shaders/circle_layer_ubo.hpp>
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
#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;
|
||||
|
||||
@@ -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<gfx::DrawableAtlasesTweaker>(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;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <mbgl/renderer/update_parameters.hpp>
|
||||
#include <mbgl/shaders/fill_layer_ubo.hpp>
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
#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<style::Layer::Impl>& impl) {
|
||||
@@ -497,8 +505,8 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
||||
if (const auto& atlases = tile.getAtlasTextures(); atlases && atlases->icon) {
|
||||
atlasTweaker = std::make_shared<gfx::DrawableAtlasesTweaker>(
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
#include <mbgl/gfx/shader_group.hpp>
|
||||
#include <mbgl/gfx/shader_registry.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
#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<gfx::Texture2D> texture = context.createTexture2D();
|
||||
texture->setImage(colorRamp);
|
||||
|
||||
@@ -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<gfx::Texture2D> 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());
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <mbgl/renderer/layers/line_layer_tweaker.hpp>
|
||||
#include <mbgl/gfx/line_drawable_data.hpp>
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
#endif
|
||||
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
@@ -55,8 +56,8 @@ inline const LineLayer::Impl& impl_cast(const Immutable<style::Layer::Impl>& 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<LineLayerTweaker>(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<gfx::LineDrawableData>(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<gfx::DrawableAtlasesTweaker>(
|
||||
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;
|
||||
|
||||
@@ -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<gfx::DrawableBuilder>& builder,
|
||||
const RasterBucket& bucket) {
|
||||
// textures
|
||||
auto location0 = rasterShader->getSamplerLocation(Image0UniformName);
|
||||
auto location0 = rasterShader->getSamplerLocation(idTexImage0Name);
|
||||
if (location0.has_value()) {
|
||||
std::shared_ptr<gfx::Texture2D> 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<gfx::Texture2D> 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,
|
||||
|
||||
@@ -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<SymbolLayerTweaker>(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<std::string> 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<std::string> 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<SymbolDynamicLayoutAttributes>;
|
||||
attr->setSharedRawData(buffer.sharedDynamicVertices,
|
||||
offsetof(Vertex, a1),
|
||||
@@ -788,7 +788,7 @@ std::vector<std::string> 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<SymbolOpacityAttributes>;
|
||||
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<gfx::VertexAttribute::int2>(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<gfx::VertexAttribute::int2>(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<gfx::VertexAttribute::int2>(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<gfx::VertexAttribute::int2>(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<gfx::VertexAttribute::float2>(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<CollisionBoxDynamicAttributes>;
|
||||
|
||||
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<gfx::ShaderProgramBase>(
|
||||
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<gfx::ShaderProgramBase>(
|
||||
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<SymbolLayerProperties>(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<UnwrappedTileID, TileInfo> tileCache;
|
||||
|
||||
@@ -1220,101 +1241,105 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
|
||||
evaluated.get<style::IconHaloWidth>().constantOr(1);
|
||||
const auto iconFill = evaluated.get<style::IconColor>().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<float>(state.getZoom())).isZoomConstant;
|
||||
tileInfo.textTweaker = std::make_shared<gfx::DrawableAtlasesTweaker>(atlases,
|
||||
iconTexUniformName,
|
||||
texUniformName,
|
||||
isText,
|
||||
false,
|
||||
values.rotationAlignment,
|
||||
false,
|
||||
textSizeIsZoomConstant);
|
||||
}
|
||||
if (!isText && !tileInfo.iconTweaker) {
|
||||
const bool iconScaled = layout.get<IconSize>().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear;
|
||||
tileInfo.iconTweaker = std::make_shared<gfx::DrawableAtlasesTweaker>(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<float>(state.getZoom())).isZoomConstant;
|
||||
tileInfo.textTweaker = std::make_shared<gfx::DrawableAtlasesTweaker>(atlases,
|
||||
idTexIconUniformName,
|
||||
idTexUniformName,
|
||||
isText,
|
||||
false,
|
||||
values.rotationAlignment,
|
||||
false,
|
||||
textSizeIsZoomConstant);
|
||||
}
|
||||
if (!isText && !tileInfo.iconTweaker) {
|
||||
const bool iconScaled = layout.get<IconSize>().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear;
|
||||
tileInfo.iconTweaker = std::make_shared<gfx::DrawableAtlasesTweaker>(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<gfx::ShaderProgramBase>(
|
||||
shaderGroup->getOrCreateShader(context, uniformProps, posOffsetAttribName));
|
||||
if (!shader) {
|
||||
return;
|
||||
}
|
||||
builder->setShader(shader);
|
||||
if (!shaderGroup) {
|
||||
return;
|
||||
}
|
||||
const auto shader = std::static_pointer_cast<gfx::ShaderProgramBase>(
|
||||
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<gfx::SymbolDrawableData>(
|
||||
/*.isHalo=*/isHalo,
|
||||
/*.bucketVaraiblePlacement=*/bucket.hasVariablePlacement,
|
||||
/*.symbolType=*/renderable.type,
|
||||
/*.pitchAlignment=*/values.pitchAlignment,
|
||||
/*.rotationAlignment=*/values.rotationAlignment,
|
||||
/*.placement=*/layout.get<SymbolPlacement>(),
|
||||
/*.textFit=*/layout.get<IconTextFit>());
|
||||
auto drawData = std::make_unique<gfx::SymbolDrawableData>(
|
||||
/*.isHalo=*/isHalo,
|
||||
/*.bucketVaraiblePlacement=*/bucket.hasVariablePlacement,
|
||||
/*.symbolType=*/renderable.type,
|
||||
/*.pitchAlignment=*/values.pitchAlignment,
|
||||
/*.rotationAlignment=*/values.rotationAlignment,
|
||||
/*.placement=*/layout.get<SymbolPlacement>(),
|
||||
/*.textFit=*/layout.get<IconTextFit>());
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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<float, 2> toArray(const Size& s) {
|
||||
return util::cast<float>(std::array<uint32_t, 2>{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<gfx::SymbolDrawableData&>(*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<style::TextTranslate>() : evaluated.get<style::IconTranslate>();
|
||||
@@ -169,8 +177,8 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup,
|
||||
/*.label_plane_matrix=*/util::cast<float>(labelPlaneMatrix),
|
||||
/*.coord_matrix=*/util::cast<float>(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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -72,8 +72,9 @@ public:
|
||||
PatternAtlas& patternAtlas_,
|
||||
RenderLayerReferences layersNeedPlacement_,
|
||||
Immutable<Placement> 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<RenderTree> RenderOrchestrator::createRenderTree(
|
||||
const std::shared_ptr<UpdateParameters>& 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<RenderTree> RenderOrchestrator::createRenderTree(
|
||||
*patternAtlas,
|
||||
std::move(layersNeedPlacement),
|
||||
placementController.getPlacement(),
|
||||
symbolBucketsChanged);
|
||||
symbolBucketsChanged,
|
||||
startTime);
|
||||
}
|
||||
|
||||
std::vector<Feature> RenderOrchestrator::queryRenderedFeatures(const ScreenLineString& geometry,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#endif
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/util/monotonic_timer.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
@@ -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<RenderTreeParameters> parameters_)
|
||||
: parameters(std::move(parameters_)) {
|
||||
RenderTree(std::unique_ptr<RenderTreeParameters> parameters_, double startTime_)
|
||||
: parameters(std::move(parameters_)),
|
||||
startTime(startTime_) {
|
||||
assert(parameters);
|
||||
}
|
||||
std::unique_ptr<RenderTreeParameters> parameters;
|
||||
|
||||
double startTime;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <mbgl/renderer/render_static_data.hpp>
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/util/convert.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <unordered_set>
|
||||
#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<gfx::DrawableBuilder> 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));
|
||||
}
|
||||
|
||||
@@ -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<TileLayerGroupTileKey, gfx::UniqueDrawable, TileLayerGroupTileKey::hash>;
|
||||
TileMap drawablesByTile;
|
||||
|
||||
@@ -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<VertexAttributeGL*>(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<ShaderProgramBase&&>(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<uint32_t> ShaderProgramGL::getSamplerLocation(const std::string_view name) const {
|
||||
GLint sampler_location = MBGL_CHECK_ERROR(glGetUniformLocation(glProgram, name.data()));
|
||||
return (sampler_location == -1) ? std::optional<uint32_t>{} : sampler_location;
|
||||
std::optional<uint32_t> ShaderProgramGL::getSamplerLocation(const StringIdentity id) const {
|
||||
std::optional<uint32_t> result{};
|
||||
if (auto it = samplerLocations.find(id); it != samplerLocations.end()) {
|
||||
result = it->second;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::shared_ptr<ShaderProgramGL> ShaderProgramGL::create(Context& context,
|
||||
@@ -151,7 +158,29 @@ std::shared_ptr<ShaderProgramGL> 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> 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<ShaderProgramGL>(std::move(program), std::move(uniformBlocks), std::move(attrs));
|
||||
return std::make_shared<ShaderProgramGL>(
|
||||
std::move(program), std::move(uniformBlocks), std::move(attrs), std::move(samplerLocations));
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
#include <mbgl/programs/program_parameters.hpp>
|
||||
#include <mbgl/shaders/shader_manifest.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <Metal/MTLRenderPass.hpp>
|
||||
#include <Metal/MTLRenderPipeline.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
@@ -160,23 +162,20 @@ MTLRenderPipelineStatePtr ShaderProgram::getRenderPipelineState(const gfx::Rende
|
||||
return rps;
|
||||
}
|
||||
|
||||
std::optional<uint32_t> 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<uint32_t> 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<int>(info.index), info.dataType, info.count);
|
||||
vertexAttributes.add(StringIndexer::get(info.name.data()), static_cast<int>(info.index), info.dataType, info.count);
|
||||
}
|
||||
|
||||
void ShaderProgram::initUniformBlock(const shaders::UniformBlockInfo& info) {
|
||||
if (const auto& block_ = uniformBlocks.add(info.name.data(), static_cast<int>(info.index), info.size)) {
|
||||
if (const auto& block_ = uniformBlocks.add(
|
||||
StringIndexer::get(info.name.data()), static_cast<int>(info.index), info.size)) {
|
||||
auto& block = static_cast<UniformBlock&>(*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
|
||||
|
||||
@@ -7,9 +7,14 @@
|
||||
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
|
||||
#include <mbgl/renderer/data_driven_property_evaluator.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using StringIdentity = std::size_t;
|
||||
|
||||
namespace style {
|
||||
|
||||
template <class T>
|
||||
@@ -41,8 +46,12 @@ public:
|
||||
using UniformList = TypeList<U>;
|
||||
|
||||
static constexpr const std::array<std::string_view, 1> AttributeNames = {A::name()};
|
||||
static std::array<std::optional<StringIdentity>, 1> AttributeNameIDs;
|
||||
};
|
||||
|
||||
template <class T, class A, class U, bool B>
|
||||
std::array<std::optional<StringIdentity>, 1> DataDrivenPaintProperty<T, A, U, B>::AttributeNameIDs = {std::nullopt};
|
||||
|
||||
template <class T, class A1, class U1, class A2, class U2>
|
||||
class CrossFadedDataDrivenPaintProperty {
|
||||
public:
|
||||
@@ -60,8 +69,13 @@ public:
|
||||
using UniformList = TypeList<U1, U2>;
|
||||
|
||||
static constexpr const std::array<std::string_view, 2> AttributeNames = {A1::name(), A2::name()};
|
||||
static std::array<std::optional<StringIdentity>, 2> AttributeNameIDs;
|
||||
};
|
||||
|
||||
template <class T, class A1, class U1, class A2, class U2>
|
||||
std::array<std::optional<StringIdentity>, 2> CrossFadedDataDrivenPaintProperty<T, A1, U1, A2, U2>::AttributeNameIDs = {
|
||||
std::nullopt, std::nullopt};
|
||||
|
||||
template <class T>
|
||||
class CrossFadedPaintProperty {
|
||||
public:
|
||||
|
||||
70
src/mbgl/util/string_indexer.cpp
Normal file
70
src/mbgl/util/string_indexer.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace {
|
||||
const std::string empty;
|
||||
}
|
||||
|
||||
StringIdentity StringIndexer::get(const std::string& string) {
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> 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<std::shared_mutex> 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<std::shared_mutex> 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<std::shared_mutex> writerLock(instance().sharedMutex);
|
||||
|
||||
instance().stringToIdentity.clear();
|
||||
instance().identityToString.clear();
|
||||
}
|
||||
|
||||
size_t StringIndexer::size() {
|
||||
std::shared_lock<std::shared_mutex> readerLock(instance().sharedMutex);
|
||||
|
||||
[[maybe_unused]] auto& stringToIdentity = instance().stringToIdentity;
|
||||
auto& identityToString = instance().identityToString;
|
||||
assert(stringToIdentity.size() == identityToString.size());
|
||||
|
||||
return identityToString.size();
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -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
|
||||
|
||||
49
test/util/string_indexer.test.cpp
Normal file
49
test/util/string_indexer.test.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <mbgl/test/util.hpp>
|
||||
|
||||
#include <mbgl/util/string_indexer.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
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());
|
||||
}
|
||||
Reference in New Issue
Block a user