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:
Stefan Karschti
2023-09-15 17:30:07 +03:00
committed by GitHub
parent 2d71683feb
commit 76469a0c22
92 changed files with 1051 additions and 496 deletions

View File

@@ -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

View File

@@ -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",

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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&);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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) {}

View File

@@ -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;

View File

@@ -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&);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)) {}

View File

@@ -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

View File

@@ -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() {}

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View 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

View File

@@ -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); }

View File

@@ -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);
}

View File

@@ -2043,7 +2043,7 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
}
});
}
NSAssert(self.styleNames.count == self.styleURLs.count, @"Style names and URLs don’t match.");
}

View File

@@ -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);

View File

@@ -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 },

View File

@@ -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() {

View File

@@ -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];
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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 }

View File

@@ -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

View File

@@ -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) {}

View File

@@ -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); }

View File

@@ -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
};

View File

@@ -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);

View File

@@ -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>()) {}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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() {

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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();

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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();

View File

@@ -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();

View File

@@ -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);
}
});
}

View File

@@ -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
});
}

View File

@@ -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.");
}

View File

@@ -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

View File

@@ -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);
});
}

View File

@@ -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;

View File

@@ -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
});

View File

@@ -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;

View File

@@ -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);
});
}

View File

@@ -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);
});
}

View File

@@ -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);
});
}

View File

@@ -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);
});
}

View File

@@ -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
});
}

View File

@@ -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);
});
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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());
}
}

View File

@@ -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);

View File

@@ -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());
}

View File

@@ -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;

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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);
});
}

View File

@@ -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;

View File

@@ -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,

View File

@@ -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

View File

@@ -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;

View File

@@ -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));
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View 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

View File

@@ -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

View 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());
}