Merge remote-tracking branch 'origin' into linux-ci

This commit is contained in:
Bart Louwers
2023-10-05 09:33:52 +00:00
102 changed files with 1989 additions and 881 deletions

View File

@@ -1114,6 +1114,7 @@ if(MLN_WITH_OPENGL)
list(APPEND INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/background_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/circle_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/collision_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/fill_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/fill_extrusion_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/heatmap_layer_ubo.hpp
@@ -1178,6 +1179,8 @@ if(MBGL_WITH_METAL)
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/circle.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/clipping_mask.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/common.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/collision_box.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/collision_circle.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill_extrusion.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp
@@ -1214,6 +1217,25 @@ if(MBGL_WITH_METAL)
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/upload_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/vertex_attribute.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/shader_program.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/background.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/background_pattern.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/circle.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/collision_box.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/collision_circle.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/clipping_mask.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/fill.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/fill_extrusion.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/heatmap.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/heatmap_texture.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/hillshade.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/hillshade_prepare.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/line.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/line_gradient.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/raster.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/symbol_icon.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/symbol_sdf.cpp
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/symbol_text_and_icon.cpp
]
)
endif()

View File

@@ -10,8 +10,8 @@ http_archive(
http_archive(
name = "rules_xcodeproj",
sha256 = "4886d10566dade9048a0b239fc43c21c29bb0ba03fb611a997f7b786d6e859b6",
url = "https://github.com/MobileNativeFoundation/rules_xcodeproj/releases/download/1.11.0/release.tar.gz",
sha256 = "d25a6af62c0b9ad781a824f6c1e866f8106531019cb7a172bd17eb9cc805a6f7",
url = "https://github.com/MobileNativeFoundation/rules_xcodeproj/releases/download/1.12.0/release.tar.gz",
)
load(

View File

@@ -961,6 +961,7 @@ MLN_DRAWABLES_HEADERS = [
"include/mbgl/renderer/render_target.hpp",
"include/mbgl/shaders/background_layer_ubo.hpp",
"include/mbgl/shaders/circle_layer_ubo.hpp",
"include/mbgl/shaders/collision_layer_ubo.hpp",
"include/mbgl/shaders/fill_layer_ubo.hpp",
"include/mbgl/shaders/fill_extrusion_layer_ubo.hpp",
"include/mbgl/shaders/heatmap_layer_ubo.hpp",
@@ -1019,6 +1020,25 @@ MLN_DRAWABLES_MTL_SOURCE = [
"src/mbgl/mtl/upload_pass.cpp",
"src/mbgl/mtl/vertex_attribute.cpp",
"src/mbgl/shaders/mtl/shader_program.cpp",
"src/mbgl/shaders/mtl/background.cpp",
"src/mbgl/shaders/mtl/background_pattern.cpp",
"src/mbgl/shaders/mtl/circle.cpp",
"src/mbgl/shaders/mtl/collision_box.cpp",
"src/mbgl/shaders/mtl/collision_circle.cpp",
"src/mbgl/shaders/mtl/clipping_mask.cpp",
"src/mbgl/shaders/mtl/fill.cpp",
"src/mbgl/shaders/mtl/fill_extrusion.cpp",
"src/mbgl/shaders/mtl/fill_extrusion_pattern.cpp",
"src/mbgl/shaders/mtl/heatmap.cpp",
"src/mbgl/shaders/mtl/heatmap_texture.cpp",
"src/mbgl/shaders/mtl/hillshade.cpp",
"src/mbgl/shaders/mtl/hillshade_prepare.cpp",
"src/mbgl/shaders/mtl/line.cpp",
"src/mbgl/shaders/mtl/line_gradient.cpp",
"src/mbgl/shaders/mtl/raster.cpp",
"src/mbgl/shaders/mtl/symbol_icon.cpp",
"src/mbgl/shaders/mtl/symbol_sdf.cpp",
"src/mbgl/shaders/mtl/symbol_text_and_icon.cpp",
]
MLN_DRAWABLES_MTL_HEADERS = [
@@ -1045,6 +1065,8 @@ MLN_DRAWABLES_MTL_HEADERS = [
"include/mbgl/shaders/mtl/background_pattern.hpp",
"include/mbgl/shaders/mtl/circle.hpp",
"include/mbgl/shaders/mtl/clipping_mask.hpp",
"include/mbgl/shaders/mtl/collision_box.hpp",
"include/mbgl/shaders/mtl/collision_circle.hpp",
"include/mbgl/shaders/mtl/common.hpp",
"include/mbgl/shaders/mtl/fill.hpp",
"include/mbgl/shaders/mtl/fill_extrusion.hpp",

View File

@@ -19,7 +19,7 @@ public:
#if MLN_RENDER_BACKEND_METAL
static constexpr Type DefaultType = Type::Metal;
#else // assume MLN_RENDER_BACKEND_METAL
#else // assume MLN_RENDER_BACKEND_OPENGL
static constexpr Type DefaultType = Type::OpenGL;
#endif
@@ -33,7 +33,11 @@ public:
template <typename T, typename... Args>
static std::unique_ptr<T> Create(Args... args) {
#if MLN_RENDER_BACKEND_METAL
return Create<Type::Metal, T, Args...>(std::forward<Args>(args)...);
#else // assume MLN_RENDER_BACKEND_OPENGL
return Create<Type::OpenGL, T, Args...>(std::forward<Args>(args)...);
#endif
}
private:

View File

@@ -134,7 +134,7 @@ public:
bool getEnableStencil() const { return enableStencil; }
/// Set stencil usage
void setEnableStencil(bool value) { enableStencil = value; }
virtual void setEnableStencil(bool value) { enableStencil = value; }
/// not used for anything yet
DrawPriority getDrawPriority() const { return drawPriority; }
@@ -142,19 +142,19 @@ public:
/// Whether to enable depth testing
bool getEnableDepth() { return enableDepth; }
void setEnableDepth(bool value) { enableDepth = value; }
virtual void setEnableDepth(bool value) { enableDepth = value; }
/// Determines depth range within the layer for 2D drawables
int32_t getSubLayerIndex() const { return subLayerIndex; }
/// Set sub-layer index
void setSubLayerIndex(int32_t value) { subLayerIndex = value; }
virtual void setSubLayerIndex(int32_t value) { subLayerIndex = value; }
/// Depth writability for 2D drawables
DepthMaskType getDepthType() const { return depthType; }
/// Set depth type
void setDepthType(DepthMaskType value) { depthType = value; }
virtual void setDepthType(DepthMaskType value) { depthType = value; }
/// Uses 3D depth mode
bool getIs3D() const { return is3D; }

View File

@@ -6,9 +6,12 @@
#include <mutex>
#include <shared_mutex>
#include <unordered_map>
#include <vector>
#include <unordered_set>
namespace mbgl {
using StringIdentity = std::size_t;
namespace gfx {
class Context;
@@ -138,12 +141,13 @@ public:
/// @brief Get a shader from the group by its set of data driven properties as uniforms.
/// if no shader is found, create and register the shader.
/// @param propertiesAsUniforms Vector of data driven properties as uniforms.
/// @param propertiesAsUniforms Set of data driven properties as uniforms.
/// @param firstAttribName Name of the first attribute
/// @return A `gfx::ShaderPtr`
virtual gfx::ShaderPtr getOrCreateShader(gfx::Context&,
[[maybe_unused]] const std::vector<std::string>& propertiesAsUniforms,
[[maybe_unused]] std::string_view firstAttribName = "a_pos") {
virtual gfx::ShaderPtr getOrCreateShader(
gfx::Context&,
[[maybe_unused]] const std::unordered_set<StringIdentity>& propertiesAsUniforms,
[[maybe_unused]] std::string_view firstAttribName = "a_pos") {
return {};
}

View File

@@ -113,6 +113,7 @@ enum class TexturePixelType : uint8_t {
enum class TextureChannelDataType : uint8_t {
UnsignedByte, ///< 8 bit unsigned byte
HalfFloat, ///< 16 bit "half-float"
Float, ///< 32 bit float
};
/// Texture mip map type

View File

@@ -11,6 +11,7 @@
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <variant>
#include <vector>
@@ -365,9 +366,15 @@ public:
}
/// Specialized DataDrivenPaintProperty reader
/// @param binders Property binders for the target shader
/// @param evaluated Evaluated properties
/// @param propertiesAsUniforms [out] A set of string identities for the properties which will be constant, not
/// attributes.
/// @details The property name IDs refer to the "a\_" prefixed values to match the shader definitions.
template <class... DataDrivenPaintProperty, class Binders, class Evaluated>
std::vector<std::string> readDataDrivenPaintProperties(const Binders& binders, const Evaluated& evaluated) {
std::vector<std::string> propertiesAsUniforms;
void readDataDrivenPaintProperties(const Binders& binders,
const Evaluated& evaluated,
std::unordered_set<StringIdentity>& propertiesAsUniforms) {
propertiesAsUniforms.reserve(sizeof...(DataDrivenPaintProperty));
(
[&](const auto& attributeNames) {
@@ -378,15 +385,14 @@ public:
using Type = typename Attribute::Type; // ::mbgl::gfx::AttributeType<type_, n_>
using InterpType = ZoomInterpolatedAttributeType<Type>;
auto& attributeNameID = DataDrivenPaintProperty::AttributeNameIDs[attrIndex];
if (!attributeNameID) {
attributeNameID = stringIndexer().get(attributePrefix + attributeName.data());
}
const auto vertexCount = binder->getVertexCount();
const auto isConstant = evaluated.template get<DataDrivenPaintProperty>().isConstant();
if (vertexCount > 0 && !isConstant) {
auto& attributeNameID = DataDrivenPaintProperty::AttributeNameIDs[attrIndex];
if (!attributeNameID) {
static const std::string attributePrefix = "a_";
attributeNameID = stringIndexer().get(attributePrefix + attributeName.data());
}
if (auto& attr = getOrAdd(*attributeNameID)) {
if (const auto& sharedVector = binder->getSharedVertexVector()) {
const auto rawSize = static_cast<uint32_t>(sharedVector->getRawSize());
@@ -403,15 +409,13 @@ public:
}
}
}
propertiesAsUniforms.emplace_back(std::string());
} else {
propertiesAsUniforms.emplace_back(attributeName);
propertiesAsUniforms.emplace(*attributeNameID);
}
}
}
}(DataDrivenPaintProperty::AttributeNames),
...);
return propertiesAsUniforms;
}
/// Copy another collection into this one
@@ -436,7 +440,8 @@ protected:
protected:
AttributeMap attrs;
static std::unique_ptr<VertexAttribute> nullref;
static const std::unique_ptr<VertexAttribute> nullref;
static const std::string attributePrefix;
};
} // namespace gfx

View File

@@ -78,6 +78,8 @@ public:
void setDirtyState() override;
std::unique_ptr<gfx::OffscreenTexture> createOffscreenTexture(Size, gfx::TextureChannelDataType, bool, bool);
std::unique_ptr<gfx::OffscreenTexture> createOffscreenTexture(Size, gfx::TextureChannelDataType) override;
std::unique_ptr<gfx::TextureResource> createTextureResource(Size,

View File

@@ -4,8 +4,6 @@
#include <mbgl/gfx/draw_mode.hpp>
#include <mbgl/mtl/upload_pass.hpp>
#include <mbgl/programs/segment.hpp>
#include <mbgl/mtl/mtl_fwd.hpp>
#include <mbgl/mtl/render_pass.hpp>
#include <memory>
@@ -59,6 +57,11 @@ public:
void setShader(gfx::ShaderProgramBasePtr) override;
void setEnableStencil(bool) override;
void setEnableDepth(bool) override;
void setSubLayerIndex(int32_t) override;
void setDepthType(gfx::DepthMaskType) override;
protected:
// For testing only.
Drawable(std::unique_ptr<Impl>);
@@ -76,12 +79,6 @@ protected:
class Impl;
const std::unique_ptr<Impl> impl;
gfx::AttributeBindingArray attributeBindings;
mutable MTLRenderPipelineStatePtr pipelineState;
mutable std::optional<gfx::RenderPassDescriptor> renderPassDescriptor;
};
} // namespace mtl

View File

@@ -11,7 +11,7 @@ class Texture2D;
class OffscreenTexture final : public gfx::OffscreenTexture {
public:
OffscreenTexture(Context&, Size size, gfx::TextureChannelDataType type = gfx::TextureChannelDataType::UnsignedByte);
OffscreenTexture(Context&, Size size, gfx::TextureChannelDataType type, bool depth, bool stencil);
bool isRenderable() override;

View File

@@ -23,7 +23,7 @@ public:
virtual const mbgl::mtl::RendererBackend& getBackend() const = 0;
virtual const mbgl::mtl::MTLCommandBufferPtr& getCommandBuffer() const = 0;
virtual mbgl::mtl::MTLBlitPassDescriptorPtr getUploadPassDescriptor() const = 0;
virtual mbgl::mtl::MTLRenderPassDescriptorPtr getRenderPassDescriptor() const = 0;
virtual const mbgl::mtl::MTLRenderPassDescriptorPtr& getRenderPassDescriptor() const = 0;
};
} // namespace mtl

View File

@@ -1,26 +1,31 @@
#pragma once
#include <mbgl/shaders/shader_source.hpp>
#include <mbgl/util/immutable.hpp>
#include <array>
#include <memory>
#include <string>
#include <vector>
#include <unordered_set>
namespace mbgl {
namespace gfx {
class Drawable;
class UniformBuffer;
using UniformBufferPtr = std::shared_ptr<UniformBuffer>;
} // namespace gfx
namespace shaders {
enum class AttributeSource : int32_t;
struct ExpressionInputsUBO;
} // namespace shaders
namespace style {
class LayerProperties;
enum class TranslateAnchorType : bool;
} // namespace style
class TransformState;
class LayerGroupBase;
class PaintParameters;
@@ -28,6 +33,7 @@ class RenderTree;
class UnwrappedTileID;
using mat4 = std::array<double, 16>;
using StringIdentity = std::size_t;
/**
Base class for layer tweakers, which manipulate layer group per frame
@@ -47,19 +53,21 @@ public:
static shaders::ExpressionInputsUBO buildExpressionUBO(double zoom, uint64_t frameCount);
/// @brief Check whether a property name exists within the previously set collection.
/// @details The string value provided is expected to have the "a_" prefix, as defined in the shader classes.
bool hasPropertyAsUniform(std::string_view) const;
shaders::AttributeSource getAttributeSource(const std::string_view& attribName) const;
bool hasPropertyAsUniform(StringIdentity) const;
shaders::AttributeSource getAttributeSource(StringIdentity) const;
template <shaders::BuiltIn ShaderType>
shaders::AttributeSource getAttributeSource(size_t index) {
using ShaderClass = shaders::ShaderSource<ShaderType, gfx::Backend::Type::Metal>;
return getAttributeSource(ShaderClass::attributes[index].nameID);
}
#endif // MLN_RENDER_BACKEND_METAL
/// @brief Set the collection of attribute names which will be provided at uniform values rather than per-vertex
/// attributes.
/// @details These values should not have "a_" prefixes, as produced by `readDataDrivenPaintProperties`.
#if MLN_RENDER_BACKEND_OPENGL
void setPropertiesAsUniforms(const std::vector<std::string>&) {}
#else
void setPropertiesAsUniforms(std::vector<std::string>);
#endif
void setPropertiesAsUniforms(const std::unordered_set<StringIdentity>&);
const std::unordered_set<StringIdentity>& getPropertiesAsUniforms() const;
void enableOverdrawInspector(bool);
@@ -90,7 +98,7 @@ protected:
#if MLN_RENDER_BACKEND_METAL
// For Metal, whether a property is provided through attribtues or uniforms is specified in
// a uniform buffer rather than by a shader compiled with different preprocessor definitions.
std::vector<std::string> propertiesAsUniforms;
std::unordered_set<StringIdentity> propertiesAsUniforms;
#endif // MLN_RENDER_BACKEND_METAL
// Indicates that the evaluated properties have changed

View File

@@ -0,0 +1,18 @@
#pragma once
#include <mbgl/shaders/layer_ubo.hpp>
namespace mbgl {
namespace shaders {
struct alignas(16) CollisionUBO {
std::array<float, 4 * 4> matrix;
std::array<float, 2> extrude_scale;
float camera_to_center_distance;
float overscale_factor;
};
static_assert(sizeof(CollisionUBO) % 16 == 0);
static_assert(sizeof(CollisionUBO) == 80);
} // namespace shaders
} // namespace mbgl

View File

@@ -4,6 +4,10 @@
#include <mbgl/shaders/gl/shader_program_gl.hpp>
#include <mbgl/shaders/shader_source.hpp>
#include <mbgl/programs/program_parameters.hpp>
#include <mbgl/util/hash.hpp>
#include <sstream>
#include <unordered_set>
namespace mbgl {
namespace gl {
@@ -13,40 +17,61 @@ class ShaderGroupGL final : public gfx::ShaderGroup {
public:
ShaderGroupGL(const ProgramParameters& programParameters_)
: ShaderGroup(),
programParameters(programParameters_){};
programParameters(programParameters_) {}
~ShaderGroupGL() noexcept override = default;
gfx::ShaderPtr getOrCreateShader(gfx::Context& context,
const std::vector<std::string>& propertiesAsUniforms,
const std::unordered_set<StringIdentity>& propertiesAsUniforms,
std::string_view firstAttribName) override {
constexpr auto& name = shaders::ShaderSource<ShaderID, gfx::Backend::Type::OpenGL>::name;
constexpr auto& vert = shaders::ShaderSource<ShaderID, gfx::Backend::Type::OpenGL>::vertex;
constexpr auto& frag = shaders::ShaderSource<ShaderID, gfx::Backend::Type::OpenGL>::fragment;
uint32_t key = 0;
// Generate a map key for the specified combination of properties
const size_t key = util::order_independent_hash(propertiesAsUniforms.begin(), propertiesAsUniforms.end());
// We could cache these by key here to avoid creating a string key each time, but we
// would need another mutex. We could also push string IDs down into `ShaderGroup`.
const std::string shaderName = getShaderName(key);
auto shader = get<gl::ShaderProgramGL>(shaderName);
if (shader) {
return shader;
}
// No match, we need to create the shader.
std::string additionalDefines;
for (unsigned int i = 0; i < propertiesAsUniforms.size(); i++) {
if (propertiesAsUniforms[i].empty()) {
continue;
additionalDefines.reserve(propertiesAsUniforms.size() * 48);
for (const auto nameID : propertiesAsUniforms) {
// We expect the names to be prefixed by "a_", but we need just the base here.
const auto prefixedAttrName = stringIndexer().get(nameID);
const auto* prefix = prefixedAttrName.data();
if (prefix[0] == 'a' && prefix[1] == '_') {
prefix += 2;
}
key |= 1 << i;
additionalDefines += "#define HAS_UNIFORM_u_";
additionalDefines += propertiesAsUniforms[i];
additionalDefines += prefix;
additionalDefines += "\n";
}
const std::string shaderName = std::string(name) + "#" + std::to_string(key);
auto shader = get<gl::ShaderProgramGL>(shaderName);
if (!shader) {
auto& glContext = static_cast<gl::Context&>(context);
shader = ShaderProgramGL::create(
glContext, programParameters, shaderName, firstAttribName, vert, frag, additionalDefines);
if (!shader || !registerShader(shader, shaderName)) {
throw std::runtime_error("Failed to register " + shaderName + " with shader group!");
}
auto& glContext = static_cast<gl::Context&>(context);
shader = ShaderProgramGL::create(
glContext, programParameters, shaderName, firstAttribName, vert, frag, additionalDefines);
if (!shader || !registerShader(shader, shaderName)) {
throw std::runtime_error("Failed to register " + shaderName + " with shader group!");
}
return shader;
}
protected:
std::string getShaderName(std::size_t key) {
constexpr auto& name = shaders::ShaderSource<ShaderID, gfx::Backend::Type::OpenGL>::name;
// This could be more efficient.
std::ostringstream stream;
stream << name << '#' << key;
return stream.str();
}
private:
ProgramParameters programParameters;
};

View File

@@ -5,8 +5,6 @@
#include <array>
#include <cstdint>
#define MLN_STRINGIZE(X) #X
namespace mbgl {
namespace shaders {

View File

@@ -14,14 +14,9 @@ struct ShaderSource<BuiltIn::BackgroundShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Float3, 1, "a_pos"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(1, true, true, BackgroundLayerUBO),
MLN_MTL_UNIFORM_BLOCK(2, true, false, BackgroundDrawableUBO),
};
static constexpr TextureInfo textures[] = {};
static const std::array<AttributeInfo, 1> attributes;
static const std::array<UniformBlockInfo, 2> uniforms;
static const std::array<TextureInfo, 0> textures;
static constexpr auto source = R"(
#include <metal_stdlib>

View File

@@ -9,11 +9,7 @@ template <>
struct ShaderSource<BuiltIn::BackgroundPatternShader, gfx::Backend::Type::Metal>
: public ShaderSource<BuiltIn::BackgroundShader, gfx::Backend::Type::Metal> {
static constexpr auto name = "BackgroundPatternShader";
static constexpr UniformBlockInfo uniforms[] = {
{1, sizeof(BackgroundLayerUBO), true, false, "BackgroundLayerUBO"},
{2, sizeof(BackgroundDrawableUBO), true, false, "BackgroundDrawableUBO"},
{3, sizeof(BackgroundPatternLayerUBO), true, false, "BackgroundPatternLayerUBO"},
};
static const std::array<UniformBlockInfo, 3> uniforms;
};
} // namespace shaders

View File

@@ -14,25 +14,9 @@ struct ShaderSource<BuiltIn::CircleShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
{1, gfx::AttributeDataType::Float2, 1, "a_color"},
{2, gfx::AttributeDataType::Float2, 1, "a_radius"},
{3, gfx::AttributeDataType::Float2, 1, "a_blur"},
{4, gfx::AttributeDataType::Float2, 1, "a_opacity"},
{5, gfx::AttributeDataType::Float4, 1, "a_stroke_color"},
{6, gfx::AttributeDataType::Float2, 1, "a_stroke_width"},
{7, gfx::AttributeDataType::Float2, 1, "a_stroke_opacity"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(8, true, false, CircleDrawableUBO),
MLN_MTL_UNIFORM_BLOCK(9, true, true, CirclePaintParamsUBO),
MLN_MTL_UNIFORM_BLOCK(10, true, true, CircleEvaluatedPropsUBO),
MLN_MTL_UNIFORM_BLOCK(11, true, false, CircleInterpolateUBO),
MLN_MTL_UNIFORM_BLOCK(12, true, true, CirclePermutationUBO),
MLN_MTL_UNIFORM_BLOCK(13, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {};
static const std::array<AttributeInfo, 8> attributes;
static const std::array<UniformBlockInfo, 6> uniforms;
static const std::array<TextureInfo, 0> textures;
static constexpr auto source = R"(

View File

@@ -20,13 +20,9 @@ struct ShaderSource<BuiltIn::ClippingMaskProgram, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Float3, 1, "a_pos"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(1, true, false, ClipUBO),
};
static constexpr TextureInfo textures[] = {};
static const std::array<AttributeInfo, 1> attributes;
static const std::array<UniformBlockInfo, 1> uniforms;
static const std::array<TextureInfo, 0> textures;
static constexpr auto source = R"(
#include <metal_stdlib>

View File

@@ -0,0 +1,91 @@
#pragma once
#include <mbgl/shaders/collision_layer_ubo.hpp>
#include <mbgl/shaders/shader_source.hpp>
#include <mbgl/shaders/mtl/common.hpp>
#include <mbgl/shaders/mtl/shader_program.hpp>
namespace mbgl {
namespace shaders {
template <>
struct ShaderSource<BuiltIn::CollisionBoxShader, gfx::Backend::Type::Metal> {
static constexpr auto name = "CollisionBoxShader";
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static const std::array<AttributeInfo, 5> attributes;
static const std::array<UniformBlockInfo, 1> uniforms;
static const std::array<TextureInfo, 0> textures;
static constexpr auto source = R"(
struct VertexStage {
short2 pos [[attribute(0)]];
short2 anchor_pos [[attribute(1)]];
short2 extrude [[attribute(2)]];
uchar2 placed [[attribute(3)]];
float2 shift [[attribute(4)]];
};
struct FragmentStage {
float4 position [[position, invariant]];
float placed;
float notUsed;
};
struct alignas(16) CollisionBoxUBO {
float4x4 matrix;
float2 extrude_scale;
float camera_to_center_distance;
float pad1;
};
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
device const CollisionBoxUBO& drawable [[buffer(5)]]) {
float4 projectedPoint = drawable.matrix * float4(float2(vertx.anchor_pos), 0, 1);
float camera_to_anchor_distance = projectedPoint.w;
float collision_perspective_ratio = clamp(
0.5 + 0.5 * (drawable.camera_to_center_distance / camera_to_anchor_distance),
0.0, // Prevents oversized near-field boxes in pitched/overzoomed tiles
4.0);
float4 position = drawable.matrix * float4(float2(vertx.pos), 0.0, 1.0);
position.xy += (float2(vertx.extrude) + vertx.shift) * drawable.extrude_scale * position.w * collision_perspective_ratio;
float placed = float(vertx.placed.x);
float notUsed = float(vertx.placed.y);
return {
.position = position,
.placed = placed,
.notUsed = notUsed,
};
}
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
device const CollisionBoxUBO& drawable [[buffer(5)]]) {
float alpha = 0.5;
// Red = collision, hide label
float4 color = float4(1.0, 0.0, 0.0, 1.0) * alpha;
// Blue = no collision, label is showing
if (in.placed > 0.5) {
color = float4(0.0, 0.0, 1.0, 0.5) * alpha;
}
if (in.notUsed > 0.5) {
// This box not used, fade it out
color *= 0.1;
}
return half4(color);
}
)";
};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,110 @@
#pragma once
#include <mbgl/shaders/collision_layer_ubo.hpp>
#include <mbgl/shaders/shader_source.hpp>
#include <mbgl/shaders/mtl/common.hpp>
#include <mbgl/shaders/mtl/shader_program.hpp>
namespace mbgl {
namespace shaders {
template <>
struct ShaderSource<BuiltIn::CollisionCircleShader, gfx::Backend::Type::Metal> {
static constexpr auto name = "CollisionCircleShader";
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static const std::array<AttributeInfo, 4> attributes;
static const std::array<UniformBlockInfo, 1> uniforms;
static const std::array<TextureInfo, 0> textures;
static constexpr auto source = R"(
struct VertexStage {
short2 pos [[attribute(0)]];
short2 anchor_pos [[attribute(1)]];
short2 extrude [[attribute(2)]];
uchar2 placed [[attribute(3)]];
};
struct FragmentStage {
float4 position [[position, invariant]];
float placed;
float notUsed;
float radius;
float2 extrude;
float2 extrude_scale;
};
struct alignas(16) CollisionCircleUBO {
float4x4 matrix;
float2 extrude_scale;
float camera_to_center_distance;
float overscale_factor;
};
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
device const CollisionCircleUBO& drawable [[buffer(4)]]) {
float4 projectedPoint = drawable.matrix * float4(float2(vertx.anchor_pos), 0, 1);
float camera_to_anchor_distance = projectedPoint.w;
float collision_perspective_ratio = clamp(
0.5 + 0.5 * (drawable.camera_to_center_distance / camera_to_anchor_distance),
0.0, // Prevents oversized near-field circles in pitched/overzoomed tiles
4.0);
float4 position = drawable.matrix * float4(float2(vertx.pos), 0.0, 1.0);
float padding_factor = 1.2; // Pad the vertices slightly to make room for anti-alias blur
position.xy += float2(vertx.extrude) * drawable.extrude_scale * padding_factor * position.w * collision_perspective_ratio;
float placed = float(vertx.placed.x);
float notUsed = float(vertx.placed.y);
float radius = abs(float(vertx.extrude.y)); // We don't pitch the circles, so both units of the extrusion vector are equal in magnitude to the radius
float2 extrude = float2(vertx.extrude) * padding_factor;
float2 extrude_scale = drawable.extrude_scale * drawable.camera_to_center_distance * collision_perspective_ratio;
return {
.position = position,
.placed = placed,
.notUsed = notUsed,
.radius = radius,
.extrude = extrude,
.extrude_scale = extrude_scale,
};
}
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
device const CollisionCircleUBO& drawable [[buffer(4)]]) {
float alpha = 0.5;
// Red = collision, hide label
float4 color = float4(1.0, 0.0, 0.0, 1.0) * alpha;
// Blue = no collision, label is showing
if (in.placed > 0.5) {
color = float4(0.0, 0.0, 1.0, 0.5) * alpha;
}
if (in.notUsed > 0.5) {
// This box not used, fade it out
color *= 0.2;
}
float extrude_scale_length = length(in.extrude_scale);
float extrude_length = length(in.extrude) * extrude_scale_length;
float stroke_width = 15.0 * extrude_scale_length / drawable.overscale_factor;
float radius = in.radius * extrude_scale_length;
float distance_to_edge = abs(extrude_length - radius);
float opacity_t = smoothstep(-stroke_width, 0.0, -distance_to_edge);
return half4(opacity_t * color);
}
)";
};
} // namespace shaders
} // namespace mbgl

View File

@@ -1,8 +1,5 @@
#pragma once
#define MLN_MTL_UNIFORM_BLOCK(idx, vert, frag, struc) \
{ idx, vert, frag, sizeof(struc), MLN_STRINGIZE(struc) }
namespace mbgl {
namespace shaders {

View File

@@ -14,24 +14,9 @@ struct ShaderSource<BuiltIn::FillShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
{1, gfx::AttributeDataType::Float2, 1, "a_color"},
{2, gfx::AttributeDataType::Float2, 1, "a_opacity"},
// This shader doesn't use it, but we need this so that the layer can assign the same
// attributes to all the drawables. If/When `VertexAttributeArray::resolve` allows it,
// this can be removed.
{8, gfx::AttributeDataType::Float2, 1, "a_outline_color"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(3, true, false, FillDrawableUBO),
MLN_MTL_UNIFORM_BLOCK(4, true, true, FillEvaluatedPropsUBO),
MLN_MTL_UNIFORM_BLOCK(5, true, false, FillInterpolateUBO),
MLN_MTL_UNIFORM_BLOCK(6, true, true, FillPermutationUBO),
MLN_MTL_UNIFORM_BLOCK(7, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {};
static const std::array<AttributeInfo, 4> attributes;
static const std::array<UniformBlockInfo, 5> uniforms;
static const std::array<TextureInfo, 0> textures;
static constexpr auto source = R"(
@@ -104,22 +89,9 @@ struct ShaderSource<BuiltIn::FillOutlineShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
{1, gfx::AttributeDataType::Float2, 1, "a_outline_color"},
{2, gfx::AttributeDataType::Float2, 1, "a_opacity"},
// See `a_outline_color` in FillShader
{8, gfx::AttributeDataType::Float2, 1, "a_color"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(3, true, false, FillOutlineDrawableUBO),
MLN_MTL_UNIFORM_BLOCK(4, true, true, FillOutlineEvaluatedPropsUBO),
MLN_MTL_UNIFORM_BLOCK(5, true, false, FillOutlineInterpolateUBO),
MLN_MTL_UNIFORM_BLOCK(6, true, true, FillOutlinePermutationUBO),
MLN_MTL_UNIFORM_BLOCK(7, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {};
static const std::array<AttributeInfo, 4> attributes;
static const std::array<UniformBlockInfo, 5> uniforms;
static const std::array<TextureInfo, 0> textures;
static constexpr auto source = R"(
@@ -203,24 +175,9 @@ struct ShaderSource<BuiltIn::FillPatternShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
{1, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"},
{2, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"},
{3, gfx::AttributeDataType::Float2, 1, "a_opacity"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(4, true, true, FillPatternDrawableUBO),
MLN_MTL_UNIFORM_BLOCK(5, true, false, FillPatternTilePropsUBO),
MLN_MTL_UNIFORM_BLOCK(6, true, true, FillPatternEvaluatedPropsUBO),
MLN_MTL_UNIFORM_BLOCK(7, true, false, FillPatternInterpolateUBO),
MLN_MTL_UNIFORM_BLOCK(8, true, true, FillPatternPermutationUBO),
MLN_MTL_UNIFORM_BLOCK(9, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {
{0, "u_image"},
};
static const std::array<AttributeInfo, 4> attributes;
static const std::array<UniformBlockInfo, 6> uniforms;
static const std::array<TextureInfo, 1> textures;
static constexpr auto source = R"(
@@ -341,24 +298,9 @@ struct ShaderSource<BuiltIn::FillOutlinePatternShader, gfx::Backend::Type::Metal
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
{1, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"},
{2, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"},
{3, gfx::AttributeDataType::Float2, 1, "a_opacity"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(4, true, true, FillOutlinePatternDrawableUBO),
MLN_MTL_UNIFORM_BLOCK(5, true, false, FillOutlinePatternTilePropsUBO),
MLN_MTL_UNIFORM_BLOCK(6, true, true, FillOutlinePatternEvaluatedPropsUBO),
MLN_MTL_UNIFORM_BLOCK(7, true, false, FillOutlinePatternInterpolateUBO),
MLN_MTL_UNIFORM_BLOCK(8, true, true, FillOutlinePatternPermutationUBO),
MLN_MTL_UNIFORM_BLOCK(9, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {
{0, "u_image"},
};
static const std::array<AttributeInfo, 4> attributes;
static const std::array<UniformBlockInfo, 6> uniforms;
static const std::array<TextureInfo, 1> textures;
static constexpr auto source = R"(

View File

@@ -14,21 +14,9 @@ struct ShaderSource<BuiltIn::FillExtrusionShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
{1, gfx::AttributeDataType::Short4, 1, "a_normal_ed"},
{2, gfx::AttributeDataType::Float4, 1, "a_color"},
{3, gfx::AttributeDataType::Float, 1, "a_base"},
{4, gfx::AttributeDataType::Float, 1, "a_height"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(5, true, false, FillExtrusionDrawableUBO),
MLN_MTL_UNIFORM_BLOCK(6, true, false, FillExtrusionDrawablePropsUBO),
MLN_MTL_UNIFORM_BLOCK(7, true, false, FillExtrusionInterpolateUBO),
MLN_MTL_UNIFORM_BLOCK(8, true, false, FillExtrusionPermutationUBO),
MLN_MTL_UNIFORM_BLOCK(9, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {};
static const std::array<AttributeInfo, 5> attributes;
static const std::array<UniformBlockInfo, 5> uniforms;
static const std::array<TextureInfo, 0> textures;
static constexpr auto source = R"(
struct alignas(16) FillExtrusionInterpolateUBO {

View File

@@ -14,9 +14,9 @@ struct ShaderSource<BuiltIn::FillExtrusionPatternShader, gfx::Backend::Type::Met
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {};
static constexpr UniformBlockInfo uniforms[] = {};
static constexpr TextureInfo textures[] = {};
static const std::array<AttributeInfo, 0> attributes;
static const std::array<UniformBlockInfo, 0> uniforms;
static const std::array<TextureInfo, 0> textures;
static constexpr auto source = R"(
)";

View File

@@ -14,19 +14,9 @@ struct ShaderSource<BuiltIn::HeatmapShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
{1, gfx::AttributeDataType::Float2, 1, "a_weight"},
{2, gfx::AttributeDataType::Float2, 1, "a_radius"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(3, true, false, HeatmapDrawableUBO),
MLN_MTL_UNIFORM_BLOCK(4, true, true, HeatmapEvaluatedPropsUBO),
MLN_MTL_UNIFORM_BLOCK(5, true, false, HeatmapInterpolateUBO),
MLN_MTL_UNIFORM_BLOCK(6, true, true, HeatmapPermutationUBO),
MLN_MTL_UNIFORM_BLOCK(7, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {};
static const std::array<AttributeInfo, 3> attributes;
static const std::array<UniformBlockInfo, 5> uniforms;
static const std::array<TextureInfo, 0> textures;
static constexpr auto source = R"(

View File

@@ -14,16 +14,10 @@ struct ShaderSource<BuiltIn::HeatmapTextureShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(1, true, true, HeatmapTextureDrawableUBO),
};
static constexpr TextureInfo textures[] = {
{0, "u_image"},
{1, "u_color_ramp"},
};
static const std::array<AttributeInfo, 1> attributes;
static const std::array<UniformBlockInfo, 1> uniforms;
static const std::array<TextureInfo, 2> textures;
static constexpr auto source = R"(
struct VertexStage {

View File

@@ -14,17 +14,9 @@ struct ShaderSource<BuiltIn::HillshadeShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
{1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(2, true, true, HillshadeDrawableUBO),
MLN_MTL_UNIFORM_BLOCK(3, false, true, HillshadeEvaluatedPropsUBO),
};
static constexpr TextureInfo textures[] = {
{0, "u_image"},
};
static const std::array<AttributeInfo, 2> attributes;
static const std::array<UniformBlockInfo, 2> uniforms;
static const std::array<TextureInfo, 1> textures;
static constexpr auto source = R"(

View File

@@ -14,16 +14,10 @@ struct ShaderSource<BuiltIn::HillshadePrepareShader, gfx::Backend::Type::Metal>
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
{1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(2, true, true, HillshadePrepareDrawableUBO),
};
static constexpr TextureInfo textures[] = {
{0, "u_image"},
};
static const std::array<AttributeInfo, 2> attributes;
static const std::array<UniformBlockInfo, 1> uniforms;
static const std::array<TextureInfo, 1> textures;
static constexpr auto source = R"(
struct VertexStage {

View File

@@ -14,24 +14,9 @@ struct ShaderSource<BuiltIn::LineShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"},
{1, gfx::AttributeDataType::UByte4, 1, "a_data"},
{2, gfx::AttributeDataType::Float4, 1, "a_color"},
{3, gfx::AttributeDataType::Float2, 1, "a_blur"},
{4, gfx::AttributeDataType::Float2, 1, "a_opacity"},
{5, gfx::AttributeDataType::Float2, 1, "a_gapwidth"},
{6, gfx::AttributeDataType::Float2, 1, "a_offset"},
{7, gfx::AttributeDataType::Float2, 1, "a_width"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(8, true, true, LineUBO),
MLN_MTL_UNIFORM_BLOCK(9, true, false, LinePropertiesUBO),
MLN_MTL_UNIFORM_BLOCK(10, true, false, LineInterpolationUBO),
MLN_MTL_UNIFORM_BLOCK(11, true, true, LinePermutationUBO),
MLN_MTL_UNIFORM_BLOCK(12, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {};
static const std::array<AttributeInfo, 8> attributes;
static const std::array<UniformBlockInfo, 5> uniforms;
static const std::array<TextureInfo, 0> textures;
static constexpr auto source = R"(
@@ -143,28 +128,9 @@ struct ShaderSource<BuiltIn::LinePatternShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"},
{1, gfx::AttributeDataType::UByte4, 1, "a_data"},
{2, gfx::AttributeDataType::Float2, 1, "a_blur"},
{3, gfx::AttributeDataType::Float2, 1, "a_opacity"},
{4, gfx::AttributeDataType::Float2, 1, "a_gapwidth"},
{5, gfx::AttributeDataType::Float2, 1, "a_offset"},
{6, gfx::AttributeDataType::Float2, 1, "a_width"},
{7, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"},
{8, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(9, true, true, LinePatternUBO),
MLN_MTL_UNIFORM_BLOCK(10, true, false, LinePatternPropertiesUBO),
MLN_MTL_UNIFORM_BLOCK(11, true, false, LinePatternInterpolationUBO),
MLN_MTL_UNIFORM_BLOCK(12, true, false, LinePatternTilePropertiesUBO),
MLN_MTL_UNIFORM_BLOCK(13, true, true, LinePermutationUBO),
MLN_MTL_UNIFORM_BLOCK(14, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {
{0, "u_image"},
};
static const std::array<AttributeInfo, 9> attributes;
static const std::array<UniformBlockInfo, 6> uniforms;
static const std::array<TextureInfo, 1> textures;
static constexpr auto source = R"(

View File

@@ -14,25 +14,9 @@ struct ShaderSource<BuiltIn::LineGradientShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"},
{1, gfx::AttributeDataType::UByte4, 1, "a_data"},
{2, gfx::AttributeDataType::Float2, 1, "a_blur"},
{3, gfx::AttributeDataType::Float2, 1, "a_opacity"},
{4, gfx::AttributeDataType::Float2, 1, "a_gapwidth"},
{5, gfx::AttributeDataType::Float2, 1, "a_offset"},
{6, gfx::AttributeDataType::Float2, 1, "a_width"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(7, true, true, LineGradientUBO),
MLN_MTL_UNIFORM_BLOCK(8, true, false, LineGradientPropertiesUBO),
MLN_MTL_UNIFORM_BLOCK(9, true, false, LineGradientInterpolationUBO),
MLN_MTL_UNIFORM_BLOCK(10, true, true, LinePermutationUBO),
MLN_MTL_UNIFORM_BLOCK(11, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {
{0, "u_image"},
};
static const std::array<AttributeInfo, 7> attributes;
static const std::array<UniformBlockInfo, 5> uniforms;
static const std::array<TextureInfo, 1> textures;
static constexpr auto source = R"(
struct VertexStage {

View File

@@ -14,17 +14,10 @@ struct ShaderSource<BuiltIn::RasterShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
{1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(2, true, true, RasterDrawableUBO),
};
static constexpr TextureInfo textures[] = {
{0, "u_image0"},
{1, "u_image1"},
};
static const std::array<AttributeInfo, 2> attributes;
static const std::array<UniformBlockInfo, 1> uniforms;
static const std::array<TextureInfo, 2> textures;
static constexpr auto source = R"(
struct VertexStage {

View File

@@ -22,32 +22,20 @@ public:
~ShaderGroup() noexcept override = default;
gfx::ShaderPtr getOrCreateShader(gfx::Context& gfxContext,
const std::vector<std::string>& propertiesAsUniforms,
const std::unordered_set<StringIdentity>& propertiesAsUniforms,
std::string_view /*firstAttribName*/) override {
constexpr auto& name = shaders::ShaderSource<ShaderID, gfx::Backend::Type::Metal>::name;
constexpr auto& source = shaders::ShaderSource<ShaderID, gfx::Backend::Type::Metal>::source;
constexpr auto& vertMain = shaders::ShaderSource<ShaderID, gfx::Backend::Type::Metal>::vertexMainFunction;
constexpr auto& fragMain = shaders::ShaderSource<ShaderID, gfx::Backend::Type::Metal>::fragmentMainFunction;
uint32_t key = 0;
assert(propertiesAsUniforms.size() < 32);
std::unordered_map<std::string, std::string> additionalDefines(propertiesAsUniforms.size());
for (unsigned int i = 0; i < propertiesAsUniforms.size(); i++) {
if (!propertiesAsUniforms[i].empty()) {
key |= 1U << i;
auto name = std::string("HAS_UNIFORM_u_") + propertiesAsUniforms[i];
additionalDefines.insert(std::make_pair(std::move(name), "1"));
}
}
const std::string shaderName = std::string(name); // + "#" + std::to_string(key);
const std::string shaderName = std::string(name);
const auto shaderSource = std::string(shaders::prelude) + source;
auto shader = get<mtl::ShaderProgram>(shaderName);
if (!shader) {
auto& context = static_cast<Context&>(gfxContext);
shader = context.createProgram(
shaderName, shaderSource, vertMain, fragMain, programParameters, additionalDefines);
shader = context.createProgram(shaderName, shaderSource, vertMain, fragMain, programParameters, {});
assert(shader);
if (!shader || !registerShader(shader, shaderName)) {
assert(false);

View File

@@ -15,21 +15,27 @@
namespace mbgl {
namespace shaders {
struct AttributeInfo {
AttributeInfo(std::size_t index, gfx::AttributeDataType dataType, std::size_t count, std::string_view name);
std::size_t index;
gfx::AttributeDataType dataType;
std::size_t count;
std::string_view name;
StringIdentity nameID;
};
struct UniformBlockInfo {
UniformBlockInfo(std::size_t index, bool vertex, bool fragment, std::size_t size, std::string_view name);
std::size_t index;
bool vertex;
bool fragment;
std::size_t size;
std::string_view name;
StringIdentity nameID;
};
struct TextureInfo {
TextureInfo(std::size_t index, std::string_view name);
std::size_t index;
std::string_view name;
StringIdentity nameID;
};
} // namespace shaders
namespace mtl {

View File

@@ -14,28 +14,9 @@ struct ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
// always attributes
{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"},
{1, gfx::AttributeDataType::UShort4, 1, "a_data"},
{2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"},
{3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"},
{4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"},
// sometimes uniforms
{5, gfx::AttributeDataType::Float, 1, "a_opacity"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(8, true, true, SymbolDrawableUBO),
MLN_MTL_UNIFORM_BLOCK(9, true, true, SymbolDrawablePaintUBO),
MLN_MTL_UNIFORM_BLOCK(10, true, false, SymbolDrawableTilePropsUBO),
MLN_MTL_UNIFORM_BLOCK(11, true, false, SymbolDrawableInterpolateUBO),
MLN_MTL_UNIFORM_BLOCK(12, true, true, SymbolPermutationUBO),
MLN_MTL_UNIFORM_BLOCK(13, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {
{0, "u_texture"},
};
static const std::array<AttributeInfo, 6> attributes;
static const std::array<UniformBlockInfo, 6> uniforms;
static const std::array<TextureInfo, 1> textures;
static constexpr auto source = R"(
struct VertexStage {

View File

@@ -14,32 +14,9 @@ struct ShaderSource<BuiltIn::SymbolSDFIconShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
// always attributes
{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"},
{1, gfx::AttributeDataType::UShort4, 1, "a_data"},
{2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"},
{3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"},
{4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"},
// sometimes uniforms
{5, gfx::AttributeDataType::Float4, 1, "a_fill_color"},
{6, gfx::AttributeDataType::Float4, 1, "a_halo_color"},
{7, gfx::AttributeDataType::Float, 1, "a_opacity"},
{8, gfx::AttributeDataType::Float, 1, "a_halo_width"},
{9, gfx::AttributeDataType::Float, 1, "a_halo_blur"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(10, true, true, SymbolDrawableUBO),
MLN_MTL_UNIFORM_BLOCK(11, true, false, SymbolDrawablePaintUBO),
MLN_MTL_UNIFORM_BLOCK(12, true, true, SymbolDrawableTilePropsUBO),
MLN_MTL_UNIFORM_BLOCK(13, true, false, SymbolDrawableInterpolateUBO),
MLN_MTL_UNIFORM_BLOCK(14, true, true, SymbolPermutationUBO),
MLN_MTL_UNIFORM_BLOCK(15, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {
{0, "u_texture"},
};
static const std::array<AttributeInfo, 10> attributes;
static const std::array<UniformBlockInfo, 6> uniforms;
static const std::array<TextureInfo, 1> textures;
static constexpr auto source = R"(
struct VertexStage {

View File

@@ -14,32 +14,9 @@ struct ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Metal>
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
// always attributes
{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"},
{1, gfx::AttributeDataType::UShort4, 1, "a_data"},
{2, gfx::AttributeDataType::Float3, 1, "a_projected_pos"},
{3, gfx::AttributeDataType::Float, 1, "a_fade_opacity"},
// sometimes uniforms
{4, gfx::AttributeDataType::Float4, 1, "a_fill_color"},
{5, gfx::AttributeDataType::Float4, 1, "a_halo_color"},
{6, gfx::AttributeDataType::Float, 1, "a_opacity"},
{7, gfx::AttributeDataType::Float, 1, "a_halo_width"},
{8, gfx::AttributeDataType::Float, 1, "a_halo_blur"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(9, true, true, SymbolDrawableUBO),
MLN_MTL_UNIFORM_BLOCK(10, true, false, SymbolDrawablePaintUBO),
MLN_MTL_UNIFORM_BLOCK(11, true, true, SymbolDrawableTilePropsUBO),
MLN_MTL_UNIFORM_BLOCK(12, true, false, SymbolDrawableInterpolateUBO),
MLN_MTL_UNIFORM_BLOCK(13, true, true, SymbolPermutationUBO),
MLN_MTL_UNIFORM_BLOCK(14, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {
{0, "u_texture"},
{1, "u_texture_icon"},
};
static const std::array<AttributeInfo, 9> attributes;
static const std::array<UniformBlockInfo, 6> uniforms;
static const std::array<TextureInfo, 2> textures;
static constexpr auto source = R"(
#define SDF 1.0
@@ -141,7 +118,7 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
const float2x2 rotation_matrix = float2x2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);
const float4 projected_pos = drawable.label_plane_matrix * float4(vertx.projected_pos.xy, 0.0, 1.0);
const float2 pos_rot = a_offset / 32.0 * fontScale + a_pxoffset;
const float2 pos_rot = a_offset / 32.0 * fontScale;
const float2 pos0 = projected_pos.xy / projected_pos.w + rotation_matrix * pos_rot;
const float4 position = drawable.coord_matrix * float4(pos0, 0.0, 1.0);
const float gamma_scale = position.w;
@@ -178,7 +155,7 @@ half4 fragment fragmentMain(FragmentStage in [[stage_in]],
if (in.data1.w == ICON) {
const float2 tex_icon = in.data0.zw;
const float alpha = opacity * fade_opacity;
const float alpha = in.opacity * fade_opacity;
return half4(icon_image.sample(icon_sampler, tex_icon) * alpha);
}

View File

@@ -11,7 +11,7 @@
namespace mbgl {
using StringIdentity = size_t;
using StringIdentity = std::size_t;
class StringIndexer {
public:

View File

@@ -55,7 +55,7 @@ cc_library(
"src/mbgl/util/thread_local.cpp",
"src/mbgl/util/utf.cpp",
] + select({
"//:metal_renderer": [],
"//:metal_renderer": ["src/mbgl/mtl/headless_backend.cpp"],
"//conditions:default": ["src/mbgl/gl/headless_backend.cpp"],
}) + select({
"//:linux": [
@@ -89,7 +89,7 @@ cc_library(
"include/mbgl/storage/sqlite3.hpp",
"include/mbgl/text/unaccent.hpp",
] + select({
"//:metal_renderer": [],
"//:metal_renderer": ["include/mbgl/mtl/headless_backend.hpp"],
"//conditions:default": ["include/mbgl/gl/headless_backend.hpp"],
}),
copts = CPP_FLAGS + MAPLIBRE_FLAGS,

View File

@@ -24,11 +24,7 @@ public:
static std::unique_ptr<HeadlessBackend> Create(const Size size = {256, 256},
SwapBehaviour swapBehavior = SwapBehaviour::NoFlush,
const gfx::ContextMode contextMode = gfx::ContextMode::Unique) {
#if MLN_RENDER_BACKEND_METAL
throw std::runtime_error("Not yet implemented");
#else // MLN_RENDER_BACKEND_OPENGL
return Backend::Create<HeadlessBackend, Size, SwapBehaviour, gfx::ContextMode>(size, swapBehavior, contextMode);
#endif
}
virtual PremultipliedImage readStillImage() = 0;

View File

@@ -0,0 +1,33 @@
#pragma once
#include <mbgl/gfx/headless_backend.hpp>
#include <mbgl/mtl/renderer_backend.hpp>
#include <memory>
#include <functional>
namespace mbgl {
namespace mtl {
class HeadlessBackend final : public mtl::RendererBackend, public gfx::HeadlessBackend {
public:
HeadlessBackend(Size = {256, 256},
SwapBehaviour = SwapBehaviour::NoFlush,
gfx::ContextMode = gfx::ContextMode::Unique);
~HeadlessBackend() override;
void updateAssumedState() override;
gfx::Renderable& getDefaultRenderable() override;
PremultipliedImage readStillImage() override;
RendererBackend* getRendererBackend() override;
SwapBehaviour getSwapBehaviour();
private:
void activate() override;
void deactivate() override;
private:
bool active = false;
SwapBehaviour swapBehaviour = SwapBehaviour::NoFlush;
};
} // namespace mtl
} // namespace mbgl

View File

@@ -0,0 +1,107 @@
#include <mbgl/mtl/headless_backend.hpp>
#include <mbgl/mtl/renderable_resource.hpp>
#include <mbgl/mtl/offscreen_texture.hpp>
#include <mbgl/mtl/context.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <cassert>
#include <stdexcept>
#include <type_traits>
#include <Metal/Metal.hpp>
namespace mbgl {
namespace mtl {
class HeadlessRenderableResource final : public mtl::RenderableResource {
public:
HeadlessRenderableResource(HeadlessBackend& backend_, mtl::Context& context_, Size size)
: backend(backend_),
context(context_) {
offscreenTexture = context.createOffscreenTexture(size, gfx::TextureChannelDataType::UnsignedByte, true, true);
}
~HeadlessRenderableResource() noexcept override = default;
void bind() override { offscreenTexture->getResource<RenderableResource>().bind(); }
void swap() override { offscreenTexture->getResource<RenderableResource>().swap(); }
PremultipliedImage readStillImage() { return offscreenTexture->readStillImage(); }
const RendererBackend& getBackend() const override { return context.getBackend(); }
const MTLCommandBufferPtr& getCommandBuffer() const override {
return offscreenTexture->getResource<RenderableResource>().getCommandBuffer();
}
MTLBlitPassDescriptorPtr getUploadPassDescriptor() const override {
return offscreenTexture->getResource<RenderableResource>().getUploadPassDescriptor();
}
const MTLRenderPassDescriptorPtr& getRenderPassDescriptor() const override {
return offscreenTexture->getResource<RenderableResource>().getRenderPassDescriptor();
}
HeadlessBackend& backend;
Context& context;
std::unique_ptr<gfx::OffscreenTexture> offscreenTexture;
};
HeadlessBackend::HeadlessBackend(const Size size_,
gfx::HeadlessBackend::SwapBehaviour swapBehaviour_,
const gfx::ContextMode contextMode_)
: mbgl::mtl::RendererBackend(contextMode_),
mbgl::gfx::HeadlessBackend(size_),
swapBehaviour(swapBehaviour_) {}
HeadlessBackend::~HeadlessBackend() {
gfx::BackendScope guard{*this, gfx::BackendScope::ScopeType::Implicit};
// Explicitly reset the renderable resource
resource.reset();
// Explicitly reset the context
context.reset();
}
void HeadlessBackend::activate() {
active = true;
}
void HeadlessBackend::deactivate() {
active = false;
}
gfx::Renderable& HeadlessBackend::getDefaultRenderable() {
if (!resource) {
resource = std::make_unique<HeadlessRenderableResource>(*this, static_cast<mtl::Context&>(getContext()), size);
}
return *this;
}
void HeadlessBackend::updateAssumedState() {
// no-op
}
PremultipliedImage HeadlessBackend::readStillImage() {
return getResource<HeadlessRenderableResource>().readStillImage();
}
RendererBackend* HeadlessBackend::getRendererBackend() {
return this;
}
HeadlessBackend::SwapBehaviour HeadlessBackend::getSwapBehaviour() {
return swapBehaviour;
}
} // namespace mtl
namespace gfx {
template <>
std::unique_ptr<gfx::HeadlessBackend> Backend::Create<gfx::Backend::Type::Metal>(
const Size size, gfx::HeadlessBackend::SwapBehaviour swapBehavior, const gfx::ContextMode contextMode) {
return std::make_unique<mtl::HeadlessBackend>(size, swapBehavior, contextMode);
}
} // namespace gfx
} // namespace mbgl

View File

@@ -1,6 +1,6 @@
#import "MBXFrameTimeGraphView.h"
const CGFloat MBXFrameTimeExaggeration = 4.f * 1000.f;
const CGFloat MBXFrameTimeExaggeration = 10.f;
const CGFloat MBXFrameTimeBarWidth = 4.f;
@interface MBXFrameTimeGraphView ()
@@ -58,7 +58,7 @@ const CGFloat MBXFrameTimeBarWidth = 4.f;
if (!CGRectEqualToRect(self.scrollLayer.frame, self.bounds)) {
self.scrollLayer.frame = self.bounds;
CGRect thresholdLineRect = CGRectMake(0, self.frame.size.height - [self renderDurationTargetMilliseconds], self.frame.size.width, 1);
CGRect thresholdLineRect = CGRectMake(0, self.frame.size.height - self.frame.size.height * MBXFrameTimeExaggeration * [self renderDurationTargetMilliseconds], self.frame.size.width, 1);
{
CGPathRef path = CGPathCreateWithRect(thresholdLineRect, nil);
@@ -96,8 +96,8 @@ const CGFloat MBXFrameTimeBarWidth = 4.f;
maximumFramesPerSecond = 60;
}
CGFloat target = (1.0 / maximumFramesPerSecond) * MBXFrameTimeExaggeration;
return [self roundedFloat:target];
CGFloat target = (1.0 / maximumFramesPerSecond);
return target;
}
- (CGFloat)roundedFloat:(CGFloat)f {
@@ -112,7 +112,7 @@ const CGFloat MBXFrameTimeBarWidth = 4.f;
- (CAShapeLayer *)barWithFrameDuration:(CFTimeInterval)frameDuration {
CAShapeLayer *bar = [CAShapeLayer layer];
CGRect barRect = CGRectMake(0, 0, MBXFrameTimeBarWidth, -(fminf(frameDuration * MBXFrameTimeExaggeration, self.frame.size.height)));
CGRect barRect = CGRectMake(0, 0, MBXFrameTimeBarWidth, -(fminf(frameDuration * MBXFrameTimeExaggeration * self.frame.size.height, self.frame.size.height)));
UIBezierPath *barPath = [UIBezierPath bezierPathWithRect:barRect];
bar.path = barPath.CGPath;
bar.fillColor = [self colorForFrameDuration:frameDuration].CGColor;
@@ -121,15 +121,15 @@ const CGFloat MBXFrameTimeBarWidth = 4.f;
}
- (UIColor *)colorForFrameDuration:(CFTimeInterval)frameDuration {
CGFloat renderDurationTargetMilliseconds = [self renderDurationTargetMilliseconds];
frameDuration *= MBXFrameTimeExaggeration;
const double greenLevel = [self renderDurationTargetMilliseconds];
const double yellowLevel = greenLevel * 3.0;
if (frameDuration < renderDurationTargetMilliseconds && frameDuration > (renderDurationTargetMilliseconds * 0.75)) {
return self.warningColor;
} else if (frameDuration > renderDurationTargetMilliseconds) {
return self.dangerColor;
} else {
if (frameDuration <= greenLevel) {
return self.safeColor;
} else if (frameDuration <= yellowLevel) {
return self.warningColor;
} else {
return self.dangerColor;
}
}

View File

@@ -69,6 +69,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsAnnotationsRows) {
MBXSettingsAnnotations10000Sprites,
MBXSettingsAnnotationAnimation,
MBXSettingsAnnotationsTestShapes,
MBXSettingsAnnotationsManyTestShapes,
MBXSettingsAnnotationsCustomCallout,
MBXSettingsAnnotationsQueryAnnotations,
MBXSettingsAnnotationsCustomUserDot,
@@ -400,6 +401,7 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
@"Add 10,000 Sprites",
@"Animate an Annotation View",
@"Add Test Shapes",
@"Add 10x Test Shapes",
@"Add Point With Custom Callout",
@"Query Annotations",
[NSString stringWithFormat:@"%@ Custom User Dot", (_customUserLocationAnnnotationEnabled ? @"Disable" : @"Enable")],
@@ -548,7 +550,10 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
[self animateAnnotationView];
break;
case MBXSettingsAnnotationsTestShapes:
[self addTestShapes];
[self addTestShapes:1];
break;
case MBXSettingsAnnotationsManyTestShapes:
[self addTestShapes:10];
break;
case MBXSettingsAnnotationsCustomCallout:
[self addAnnotationWithCustomCallout];
@@ -881,102 +886,107 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
});
};
- (void)addTestShapes
- (void)addTestShapes:(NSUInteger)featuresCount
{
// Pacific Northwest triangle
//
CLLocationCoordinate2D triangleCoordinates[3] =
{
CLLocationCoordinate2DMake(44, -122),
CLLocationCoordinate2DMake(46, -122),
CLLocationCoordinate2DMake(46, -121)
};
MLNPolygon *triangle = [MLNPolygon polygonWithCoordinates:triangleCoordinates count:3];
[self.mapView addAnnotation:triangle];
// West coast polyline
//
CLLocationCoordinate2D lineCoordinates[4] = {
CLLocationCoordinate2DMake(47.6025, -122.3327),
CLLocationCoordinate2DMake(45.5189, -122.6726),
CLLocationCoordinate2DMake(37.7790, -122.4177),
CLLocationCoordinate2DMake(34.0532, -118.2349)
};
MLNPolyline *line = [MLNPolyline polylineWithCoordinates:lineCoordinates count:4];
[self.mapView addAnnotation:line];
// Orcas Island, WA hike polyline
//
NSDictionary *hike = [NSJSONSerialization JSONObjectWithData:
[NSData dataWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:@"polyline" ofType:@"geojson"]]
options:0
error:nil];
NSArray *hikeCoordinatePairs = hike[@"features"][0][@"geometry"][@"coordinates"];
CLLocationCoordinate2D *polylineCoordinates = (CLLocationCoordinate2D *)malloc([hikeCoordinatePairs count] * sizeof(CLLocationCoordinate2D));
for (NSUInteger i = 0; i < [hikeCoordinatePairs count]; i++)
{
polylineCoordinates[i] = CLLocationCoordinate2DMake([hikeCoordinatePairs[i][1] doubleValue], [hikeCoordinatePairs[i][0] doubleValue]);
}
MLNPolyline *polyline = [MLNPolyline polylineWithCoordinates:polylineCoordinates
count:[hikeCoordinatePairs count]];
[self.mapView addAnnotation:polyline];
free(polylineCoordinates);
// PA/NJ/DE polygons
//
NSDictionary *threestates = [NSJSONSerialization JSONObjectWithData:
[NSData dataWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:@"threestates" ofType:@"geojson"]]
options:0
error:nil];
for (NSDictionary *feature in threestates[@"features"])
{
NSArray *stateCoordinatePairs = feature[@"geometry"][@"coordinates"];
while ([stateCoordinatePairs count] == 1) stateCoordinatePairs = stateCoordinatePairs[0];
CLLocationCoordinate2D *polygonCoordinates = (CLLocationCoordinate2D *)malloc([stateCoordinatePairs count] * sizeof(CLLocationCoordinate2D));
for (NSUInteger i = 0; i < [stateCoordinatePairs count]; i++)
for (int featureIndex = 0; featureIndex < featuresCount; ++featureIndex) {
double deltaLongitude = featureIndex * 0.01;
double deltaLatitude = -featureIndex * 0.01;
// Pacific Northwest triangle
//
CLLocationCoordinate2D triangleCoordinates[3] =
{
polygonCoordinates[i] = CLLocationCoordinate2DMake([stateCoordinatePairs[i][1] doubleValue], [stateCoordinatePairs[i][0] doubleValue]);
CLLocationCoordinate2DMake(44 + deltaLatitude, -122 + deltaLongitude),
CLLocationCoordinate2DMake(46 + deltaLatitude, -122 + deltaLongitude),
CLLocationCoordinate2DMake(46 + deltaLatitude, -121 + deltaLongitude)
};
MLNPolygon *triangle = [MLNPolygon polygonWithCoordinates:triangleCoordinates count:3];
[self.mapView addAnnotation:triangle];
// West coast polyline
//
CLLocationCoordinate2D lineCoordinates[4] = {
CLLocationCoordinate2DMake(47.6025 + deltaLatitude, -122.3327 + deltaLongitude),
CLLocationCoordinate2DMake(45.5189 + deltaLatitude, -122.6726 + deltaLongitude),
CLLocationCoordinate2DMake(37.7790 + deltaLatitude, -122.4177 + deltaLongitude),
CLLocationCoordinate2DMake(34.0532 + deltaLatitude, -118.2349 + deltaLongitude)
};
MLNPolyline *line = [MLNPolyline polylineWithCoordinates:lineCoordinates count:4];
[self.mapView addAnnotation:line];
// Orcas Island, WA hike polyline
//
NSDictionary *hike = [NSJSONSerialization JSONObjectWithData:
[NSData dataWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:@"polyline" ofType:@"geojson"]]
options:0
error:nil];
NSArray *hikeCoordinatePairs = hike[@"features"][0][@"geometry"][@"coordinates"];
CLLocationCoordinate2D *polylineCoordinates = (CLLocationCoordinate2D *)malloc([hikeCoordinatePairs count] * sizeof(CLLocationCoordinate2D));
for (NSUInteger i = 0; i < [hikeCoordinatePairs count]; i++)
{
polylineCoordinates[i] = CLLocationCoordinate2DMake([hikeCoordinatePairs[i][1] doubleValue] + deltaLatitude, [hikeCoordinatePairs[i][0] doubleValue] + deltaLongitude);
}
MLNPolygon *polygon = [MLNPolygon polygonWithCoordinates:polygonCoordinates count:[stateCoordinatePairs count]];
polygon.title = feature[@"properties"][@"NAME"];
[self.mapView addAnnotation:polygon];
free(polygonCoordinates);
MLNPolyline *polyline = [MLNPolyline polylineWithCoordinates:polylineCoordinates
count:[hikeCoordinatePairs count]];
[self.mapView addAnnotation:polyline];
free(polylineCoordinates);
// PA/NJ/DE polygons
//
NSDictionary *threestates = [NSJSONSerialization JSONObjectWithData:
[NSData dataWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:@"threestates" ofType:@"geojson"]]
options:0
error:nil];
for (NSDictionary *feature in threestates[@"features"])
{
NSArray *stateCoordinatePairs = feature[@"geometry"][@"coordinates"];
while ([stateCoordinatePairs count] == 1) stateCoordinatePairs = stateCoordinatePairs[0];
CLLocationCoordinate2D *polygonCoordinates = (CLLocationCoordinate2D *)malloc([stateCoordinatePairs count] * sizeof(CLLocationCoordinate2D));
for (NSUInteger i = 0; i < [stateCoordinatePairs count]; i++)
{
polygonCoordinates[i] = CLLocationCoordinate2DMake([stateCoordinatePairs[i][1] doubleValue] + deltaLatitude, [stateCoordinatePairs[i][0] doubleValue] + deltaLongitude);
}
MLNPolygon *polygon = [MLNPolygon polygonWithCoordinates:polygonCoordinates count:[stateCoordinatePairs count]];
polygon.title = feature[@"properties"][@"NAME"];
[self.mapView addAnnotation:polygon];
free(polygonCoordinates);
}
// Null Island polygon with an interior hole
//
CLLocationCoordinate2D innerCoordinates[] = {
CLLocationCoordinate2DMake(-5 + deltaLatitude, -5 + deltaLongitude),
CLLocationCoordinate2DMake(-5 + deltaLatitude, 5 + deltaLongitude),
CLLocationCoordinate2DMake(5 + deltaLatitude, 5 + deltaLongitude),
CLLocationCoordinate2DMake(5 + deltaLatitude, -5 + deltaLongitude),
};
MLNPolygon *innerPolygon = [MLNPolygon polygonWithCoordinates:innerCoordinates count:sizeof(innerCoordinates) / sizeof(innerCoordinates[0])];
CLLocationCoordinate2D outerCoordinates[] = {
CLLocationCoordinate2DMake(-10 + deltaLatitude, -10 + deltaLongitude),
CLLocationCoordinate2DMake(-10 + deltaLatitude, 10 + deltaLongitude),
CLLocationCoordinate2DMake(10 + deltaLatitude, 10 + deltaLongitude),
CLLocationCoordinate2DMake(10 + deltaLatitude, -10 + deltaLongitude),
};
MLNPolygon *outerPolygon = [MLNPolygon polygonWithCoordinates:outerCoordinates count:sizeof(outerCoordinates) / sizeof(outerCoordinates[0]) interiorPolygons:@[innerPolygon]];
[self.mapView addAnnotation:outerPolygon];
}
// Null Island polygon with an interior hole
//
CLLocationCoordinate2D innerCoordinates[] = {
CLLocationCoordinate2DMake(-5, -5),
CLLocationCoordinate2DMake(-5, 5),
CLLocationCoordinate2DMake(5, 5),
CLLocationCoordinate2DMake(5, -5),
};
MLNPolygon *innerPolygon = [MLNPolygon polygonWithCoordinates:innerCoordinates count:sizeof(innerCoordinates) / sizeof(innerCoordinates[0])];
CLLocationCoordinate2D outerCoordinates[] = {
CLLocationCoordinate2DMake(-10, -10),
CLLocationCoordinate2DMake(-10, 10),
CLLocationCoordinate2DMake(10, 10),
CLLocationCoordinate2DMake(10, -10),
};
MLNPolygon *outerPolygon = [MLNPolygon polygonWithCoordinates:outerCoordinates count:sizeof(outerCoordinates) / sizeof(outerCoordinates[0]) interiorPolygons:@[innerPolygon]];
[self.mapView addAnnotation:outerPolygon];
}
- (void)addAnnotationWithCustomCallout
@@ -2439,9 +2449,9 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
return features;
}
- (void)mapViewDidFinishRenderingFrame:(MLNMapView *)mapView fullyRendered:(BOOL)fullyRendered {
- (void)mapViewDidFinishRenderingFrame:(MLNMapView *)mapView fullyRendered:(BOOL)fullyRendered frameTime:(double)frameTime {
if (self.frameTimeGraphEnabled) {
[self.frameTimeGraphView updatePathWithFrameDuration:mapView.frameTime];
[self.frameTimeGraphView updatePathWithFrameDuration:frameTime];
}
}

View File

@@ -0,0 +1,2 @@
*/*.pbf

View File

@@ -0,0 +1,2 @@
tiles/

View File

@@ -69,8 +69,12 @@ public:
return NS::TransferPtr(MTL::BlitPassDescriptor::alloc()->init());
}
mbgl::mtl::MTLRenderPassDescriptorPtr getRenderPassDescriptor() const override {
return NS::RetainPtr((__bridge MTL::RenderPassDescriptor*)mtlView.currentRenderPassDescriptor);
const mbgl::mtl::MTLRenderPassDescriptorPtr& getRenderPassDescriptor() const override {
if (!cachedRenderPassDescriptor) {
auto* mtlDesc = mtlView.currentRenderPassDescriptor;
cachedRenderPassDescriptor = NS::RetainPtr((__bridge MTL::RenderPassDescriptor*)mtlDesc);
}
return cachedRenderPassDescriptor;
}
void swap() override {
@@ -83,6 +87,8 @@ public:
commandBuffer = nil;
commandBufferPtr.reset();
cachedRenderPassDescriptor.reset();
}
mbgl::Size framebufferSize() {
@@ -94,6 +100,7 @@ public:
private:
MLNMapViewMetalImpl& backend;
mbgl::mtl::MTLCommandBufferPtr commandBufferPtr;
mutable mbgl::mtl::MTLRenderPassDescriptorPtr cachedRenderPassDescriptor;
public:
MLNMapViewImplDelegate* delegate = nil;

View File

@@ -17,7 +17,8 @@ std::size_t VertexAttribute::getCount() const {
return sharedRawData ? sharedRawData->getRawCount() : items.size();
}
std::unique_ptr<VertexAttribute> VertexAttributeArray::nullref = nullptr;
const std::unique_ptr<VertexAttribute> VertexAttributeArray::nullref;
const std::string VertexAttributeArray::attributePrefix = "a_";
VertexAttributeArray::VertexAttributeArray(VertexAttributeArray&& other)
: attrs(std::move(other.attrs)) {}

View File

@@ -489,12 +489,11 @@ gfx::UniformBufferPtr Context::createUniformBuffer(const void* data, std::size_t
}
gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders, const std::string& name) {
std::vector<std::string> emptyProperties(0);
auto shaderGroup = shaders.getShaderGroup(name);
if (!shaderGroup) {
return nullptr;
}
return std::static_pointer_cast<gfx::ShaderProgramBase>(shaderGroup->getOrCreateShader(*this, emptyProperties));
return std::static_pointer_cast<gfx::ShaderProgramBase>(shaderGroup->getOrCreateShader(*this, {}));
}
TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) {

View File

@@ -122,10 +122,10 @@ void DrawableGL::bindUniformBuffers() const {
const auto& uniformBuffer = getUniformBuffers().get(element.first);
if (!uniformBuffer) {
using namespace std::string_literals;
const auto currTileID = getTileID() ? util::toString(*getTileID()) : "<no tile>";
const auto tileIDStr = getTileID() ? util::toString(*getTileID()) : "<no tile>";
Log::Error(Event::General,
"bindUniformBuffers: UBO "s + std::string(stringIndexer().get(element.first)) +
" not found for " + util::toString(getID()) + " / " + getName() + " / " + currTileID +
" not found for " + util::toString(getID()) + " / " + getName() + " / " + tileIDStr +
". skipping.");
assert(false);
continue;

View File

@@ -397,6 +397,15 @@ platform::GLenum Enum<gfx::TexturePixelType>::sizedFor<>(const gfx::TexturePixel
default:
break;
}
break;
}
case gfx::TextureChannelDataType::Float: {
switch (value) {
case gfx::TexturePixelType::RGBA:
return GL_RGBA32F;
default:
break;
}
}
}
@@ -410,6 +419,8 @@ gfx::TextureChannelDataType Enum<gfx::TextureChannelDataType>::from(const platfo
return gfx::TextureChannelDataType::UnsignedByte;
case GL_HALF_FLOAT:
return gfx::TextureChannelDataType::HalfFloat;
case GL_FLOAT:
return gfx::TextureChannelDataType::Float;
}
return {};
}
@@ -421,6 +432,8 @@ platform::GLenum Enum<gfx::TextureChannelDataType>::to(const gfx::TextureChannel
return GL_UNSIGNED_BYTE;
case gfx::TextureChannelDataType::HalfFloat:
return GL_HALF_FLOAT;
case gfx::TextureChannelDataType::Float:
return GL_FLOAT;
}
return GL_INVALID_ENUM;
}

View File

@@ -151,12 +151,9 @@ gfx::UniformBufferPtr Context::createUniformBuffer(const void* data, std::size_t
}
gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders, const std::string& name) {
std::vector<std::string> emptyProperties(0);
auto shaderGroup = shaders.getShaderGroup(name);
if (!shaderGroup) {
return nullptr;
}
return std::static_pointer_cast<gfx::ShaderProgramBase>(shaderGroup->getOrCreateShader(*this, emptyProperties));
const auto shaderGroup = shaders.getShaderGroup(name);
auto shader = shaderGroup ? shaderGroup->getOrCreateShader(*this, {}) : gfx::ShaderProgramBasePtr{};
return std::static_pointer_cast<gfx::ShaderProgramBase>(std::move(shader));
}
TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) {
@@ -189,8 +186,15 @@ bool Context::emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& buffer, const
void Context::setDirtyState() {}
std::unique_ptr<gfx::OffscreenTexture> Context::createOffscreenTexture(Size size,
gfx::TextureChannelDataType type,
bool depth,
bool stencil) {
return std::make_unique<OffscreenTexture>(*this, size, type, depth, stencil);
}
std::unique_ptr<gfx::OffscreenTexture> Context::createOffscreenTexture(Size size, gfx::TextureChannelDataType type) {
return std::make_unique<OffscreenTexture>(*this, size, type);
return createOffscreenTexture(size, type, false, false);
}
std::unique_ptr<gfx::TextureResource> Context::createTextureResource(Size,

View File

@@ -123,12 +123,32 @@ MTL::Winding mapWindingMode(const gfx::CullFaceWindingType mode) {
} // namespace
void Drawable::setColorMode(const gfx::ColorMode& value) {
pipelineState.reset();
impl->pipelineState.reset();
gfx::Drawable::setColorMode(value);
}
void Drawable::setEnableStencil(bool value) {
gfx::Drawable::setEnableStencil(value);
impl->depthStencilState.reset();
}
void Drawable::setEnableDepth(bool value) {
gfx::Drawable::setEnableDepth(value);
impl->depthStencilState.reset();
}
void Drawable::setSubLayerIndex(int32_t value) {
gfx::Drawable::setSubLayerIndex(value);
impl->depthStencilState.reset();
}
void Drawable::setDepthType(gfx::DepthMaskType value) {
gfx::Drawable::setDepthType(value);
impl->depthStencilState.reset();
}
void Drawable::setShader(gfx::ShaderProgramBasePtr value) {
pipelineState.reset();
impl->pipelineState.reset();
gfx::Drawable::setShader(value);
}
@@ -151,13 +171,12 @@ void Drawable::draw(PaintParameters& parameters) const {
return;
}
if (renderPassDescriptor.has_value() && renderPass.getDescriptor() != renderPassDescriptor.value()) {
pipelineState.reset();
const auto& descriptor = renderPass.getDescriptor();
if (impl->renderPassDescriptor && descriptor != *impl->renderPassDescriptor) {
impl->pipelineState.reset();
}
renderPassDescriptor.emplace(gfx::RenderPassDescriptor{renderPass.getDescriptor().renderable,
renderPass.getDescriptor().clearColor,
renderPass.getDescriptor().clearDepth,
renderPass.getDescriptor().clearStencil});
impl->renderPassDescriptor.emplace(gfx::RenderPassDescriptor{
descriptor.renderable, descriptor.clearColor, descriptor.clearDepth, descriptor.clearStencil});
const auto& shaderMTL = static_cast<const ShaderProgram&>(*shader);
@@ -165,23 +184,6 @@ void Drawable::draw(PaintParameters& parameters) const {
const auto debugGroup = parameters.encoder->createDebugGroup(debugLabel(*this));
#endif
/*
context.setDepthMode(getIs3D() ? parameters.depthModeFor3D()
: parameters.depthModeForSublayer(getSubLayerIndex(), getDepthType()));
// force disable depth test for debugging
// context.setDepthMode({gfx::DepthFunctionType::Always, gfx::DepthMaskType::ReadOnly, {0,1}});
// For 3D mode, stenciling is handled by the layer group
if (!is3D) {
context.setStencilMode(makeStencilMode(parameters));
}
context.setColorMode(getColorMode());
context.setCullFaceMode(getCullFaceMode());
*/
bindAttributes(renderPass);
bindUniformBuffers(renderPass);
bindTextures(renderPass);
@@ -207,11 +209,11 @@ void Drawable::draw(PaintParameters& parameters) const {
encoder->setCullMode(cullMode.enabled ? mapCullMode(cullMode.side) : MTL::CullModeNone);
encoder->setFrontFacingWinding(mapWindingMode(cullMode.winding));
if (!pipelineState) {
pipelineState = shaderMTL.getRenderPipelineState(renderPassDescriptor, impl->vertexDesc, getColorMode());
if (!impl->pipelineState) {
impl->pipelineState = shaderMTL.getRenderPipelineState(renderPassDescriptor, impl->vertexDesc, getColorMode());
}
if (pipelineState) {
encoder->setRenderPipelineState(pipelineState.get());
if (impl->pipelineState) {
encoder->setRenderPipelineState(impl->pipelineState.get());
} else {
assert(!"Failed to create render pipeline state");
return;
@@ -219,12 +221,30 @@ void Drawable::draw(PaintParameters& parameters) const {
// For 3D mode, stenciling is handled by the layer group
if (!is3D) {
const auto depthMode = parameters.depthModeForSublayer(getSubLayerIndex(), getDepthType());
const auto stencilMode = enableStencil ? parameters.stencilModeForClipping(tileID->toUnwrapped())
: gfx::StencilMode::disabled();
if (auto depthStencilState = context.makeDepthStencilState(depthMode, stencilMode, renderPass)) {
encoder->setDepthStencilState(depthStencilState.get());
encoder->setStencilReferenceValue(stencilMode.ref);
std::optional<gfx::StencilMode> newStencilMode;
// If we have a stencil state, we may be able to reuse it, if the tile masks haven't changed.
// We assume that only the reference value needs to be compared.
if (impl->depthStencilState && enableStencil) {
newStencilMode = parameters.stencilModeForClipping(tileID->toUnwrapped());
if (newStencilMode->ref != impl->previousStencilMode.ref) {
// No, need to rebuild it
impl->depthStencilState.reset();
}
}
if (!impl->depthStencilState) {
if (enableStencil && !newStencilMode) {
newStencilMode = parameters.stencilModeForClipping(tileID->toUnwrapped());
}
const auto depthMode = parameters.depthModeForSublayer(getSubLayerIndex(), getDepthType());
const auto stencilMode = enableStencil ? parameters.stencilModeForClipping(tileID->toUnwrapped())
: gfx::StencilMode::disabled();
impl->depthStencilState = context.makeDepthStencilState(depthMode, stencilMode, renderPass);
impl->previousStencilMode = *newStencilMode;
}
if (impl->depthStencilState) {
encoder->setDepthStencilState(impl->depthStencilState.get());
encoder->setStencilReferenceValue(impl->previousStencilMode.ref);
}
}
@@ -266,7 +286,7 @@ void Drawable::draw(PaintParameters& parameters) const {
assert(mlSegment.indexOffset + mlSegment.indexLength <= indexBufferLength);
assert(static_cast<std::size_t>(maxIndex) < mlSegment.vertexLength);
for (const auto& binding : attributeBindings) {
for (const auto& binding : impl->attributeBindings) {
if (binding) {
if (const auto buffer = getMetalBuffer(binding ? binding->vertexBufferResource : nullptr)) {
assert((maxIndex + mlSegment.vertexOffset) * binding->vertexStride <= buffer->length());
@@ -348,7 +368,7 @@ void Drawable::bindAttributes(const RenderPass& renderPass) const {
const auto& encoder = renderPass.getMetalEncoder();
NS::UInteger attributeIndex = 0;
for (const auto& binding : attributeBindings) {
for (const auto& binding : impl->attributeBindings) {
if (const auto buffer = getMetalBuffer(binding ? binding->vertexBufferResource : nullptr)) {
assert(binding->vertexStride * impl->vertexCount <= getBufferSize(binding->vertexBufferResource));
encoder->setVertexBuffer(buffer, /*offset=*/0, attributeIndex);
@@ -363,7 +383,7 @@ void Drawable::unbindAttributes(const RenderPass& renderPass) const {
const auto& encoder = renderPass.getMetalEncoder();
NS::UInteger attributeIndex = 0;
for (const auto& binding : attributeBindings) {
for (const auto& binding : impl->attributeBindings) {
encoder->setVertexBuffer(nullptr, /*offset=*/0, attributeIndex);
attributeIndex += 1;
}
@@ -560,14 +580,14 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
impl->vertexAttributes.visitAttributes(
[](const auto&, gfx::VertexAttribute& attrib) { attrib.setDirty(false); });
if (attributeBindings != attributeBindings_) {
attributeBindings = attributeBindings_;
if (impl->attributeBindings != attributeBindings_) {
impl->attributeBindings = attributeBindings_;
// Create a layout descriptor for each attribute
auto vertDesc = NS::RetainPtr(MTL::VertexDescriptor::vertexDescriptor());
NS::UInteger index = 0;
for (auto& binding : attributeBindings) {
for (auto& binding : impl->attributeBindings) {
if (!binding) {
assert("Missing attribute binding");
continue;
@@ -597,7 +617,7 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
}
impl->vertexDesc = std::move(vertDesc);
pipelineState.reset();
impl->pipelineState.reset();
}
}

View File

@@ -8,6 +8,7 @@
#include <mbgl/gfx/uniform_buffer.hpp>
#include <mbgl/gfx/vertex_attribute.hpp>
#include <mbgl/mtl/mtl_fwd.hpp>
#include <mbgl/mtl/render_pass.hpp>
#include <mbgl/mtl/uniform_buffer.hpp>
#include <mbgl/mtl/upload_pass.hpp>
#include <mbgl/programs/segment.hpp>
@@ -55,6 +56,15 @@ public:
StringIdentity idVertexAttrName = stringIndexer().get("a_pos");
gfx::UniqueVertexBufferResource noBindingBuffer;
gfx::AttributeBindingArray attributeBindings;
MTLRenderPipelineStatePtr pipelineState;
std::optional<gfx::RenderPassDescriptor> renderPassDescriptor;
MTLDepthStencilStatePtr depthStencilState;
gfx::StencilMode previousStencilMode;
};
struct Drawable::DrawSegment final : public gfx::Drawable::DrawSegment {

View File

@@ -11,18 +11,39 @@ namespace mtl {
class OffscreenTextureResource final : public RenderableResource {
public:
OffscreenTextureResource(Context& context_, const Size size_, const gfx::TextureChannelDataType type_)
OffscreenTextureResource(
Context& context_, const Size size_, const gfx::TextureChannelDataType type_, bool depth, bool stencil)
: context(context_),
size(size_),
type(type_) {
assert(!size.isEmpty());
texture = context.createTexture2D();
texture->setSize(size);
texture->setFormat(gfx::TexturePixelType::RGBA, type);
texture->setSamplerConfiguration(
colorTexture = context.createTexture2D();
colorTexture->setSize(size);
colorTexture->setFormat(gfx::TexturePixelType::RGBA, type);
colorTexture->setSamplerConfiguration(
{gfx::TextureFilterType::Nearest, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
static_cast<Texture2D*>(texture.get())
static_cast<Texture2D*>(colorTexture.get())
->setUsage(MTL::TextureUsageShaderRead | MTL::TextureUsageShaderWrite | MTL::TextureUsageRenderTarget);
if (depth) {
depthTexture = context.createTexture2D();
depthTexture->setSize(size);
depthTexture->setFormat(gfx::TexturePixelType::Depth, gfx::TextureChannelDataType::Float);
depthTexture->setSamplerConfiguration(
{gfx::TextureFilterType::Nearest, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
static_cast<Texture2D*>(depthTexture.get())
->setUsage(MTL::TextureUsageShaderRead | MTL::TextureUsageShaderWrite | MTL::TextureUsageRenderTarget);
}
if (stencil) {
stencilTexture = context.createTexture2D();
stencilTexture->setSize(size);
stencilTexture->setFormat(gfx::TexturePixelType::Stencil, gfx::TextureChannelDataType::UnsignedByte);
stencilTexture->setSamplerConfiguration(
{gfx::TextureFilterType::Nearest, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
static_cast<Texture2D*>(stencilTexture.get())
->setUsage(MTL::TextureUsageShaderRead | MTL::TextureUsageShaderWrite | MTL::TextureUsageRenderTarget);
}
}
~OffscreenTextureResource() noexcept override = default;
@@ -30,7 +51,25 @@ public:
void bind() override {
assert(context.getBackend().getCommandQueue());
commandBuffer = NS::RetainPtr(context.getBackend().getCommandQueue()->commandBuffer());
texture->create();
colorTexture->create();
renderPassDescriptor = NS::TransferPtr(MTL::RenderPassDescriptor::alloc()->init());
if (auto* colorTarget = renderPassDescriptor->colorAttachments()->object(0)) {
colorTarget->setTexture(static_cast<Texture2D*>(colorTexture.get())->getMetalTexture());
}
if (depthTexture) {
depthTexture->create();
if (auto* depthTarget = renderPassDescriptor->depthAttachment()) {
depthTarget->setTexture(static_cast<Texture2D*>(depthTexture.get())->getMetalTexture());
}
}
if (stencilTexture) {
stencilTexture->create();
if (auto* stencilTarget = renderPassDescriptor->stencilAttachment()) {
stencilTarget->setTexture(static_cast<Texture2D*>(stencilTexture.get())->getMetalTexture());
}
}
}
void swap() override {
@@ -38,16 +77,24 @@ public:
commandBuffer->commit();
commandBuffer->waitUntilCompleted();
commandBuffer.reset();
renderPassDescriptor.reset();
}
PremultipliedImage readStillImage() {
assert(false);
return PremultipliedImage();
assert(static_cast<Texture2D*>(colorTexture.get())->getMetalTexture());
auto data = std::make_unique<uint8_t[]>(colorTexture->getDataSize());
MTL::Region region = MTL::Region::Make2D(0, 0, size.width, size.height);
NS::UInteger bytesPerRow = size.width * colorTexture->getPixelStride();
static_cast<Texture2D*>(colorTexture.get())->getMetalTexture()->getBytes(data.get(), bytesPerRow, region, 0);
return {size, std::move(data)};
}
gfx::Texture2DPtr& getTexture() {
assert(texture);
return texture;
assert(colorTexture);
return colorTexture;
}
const RendererBackend& getBackend() const override { return context.getBackend(); }
@@ -55,15 +102,11 @@ public:
const MTLCommandBufferPtr& getCommandBuffer() const override { return commandBuffer; }
MTLBlitPassDescriptorPtr getUploadPassDescriptor() const override {
assert(false);
return NS::TransferPtr(MTL::BlitPassDescriptor::alloc()->init());
}
MTLRenderPassDescriptorPtr getRenderPassDescriptor() const override {
auto renderPassDescriptor = NS::TransferPtr(MTL::RenderPassDescriptor::alloc()->init());
if (auto* colorTarget = renderPassDescriptor->colorAttachments()->object(0)) {
colorTarget->setTexture(static_cast<Texture2D*>(texture.get())->getMetalTexture());
}
const MTLRenderPassDescriptorPtr& getRenderPassDescriptor() const override {
assert(renderPassDescriptor);
return renderPassDescriptor;
}
@@ -71,12 +114,16 @@ private:
Context& context;
const Size size;
const gfx::TextureChannelDataType type;
gfx::Texture2DPtr texture;
gfx::Texture2DPtr colorTexture;
gfx::Texture2DPtr depthTexture;
gfx::Texture2DPtr stencilTexture;
MTLCommandBufferPtr commandBuffer;
MTLRenderPassDescriptorPtr renderPassDescriptor;
};
OffscreenTexture::OffscreenTexture(Context& context, const Size size_, const gfx::TextureChannelDataType type)
: gfx::OffscreenTexture(size, std::make_unique<OffscreenTextureResource>(context, size_, type)) {}
OffscreenTexture::OffscreenTexture(
Context& context, const Size size_, const gfx::TextureChannelDataType type, bool depth, bool stencil)
: gfx::OffscreenTexture(size, std::make_unique<OffscreenTextureResource>(context, size_, type, depth, stencil)) {}
bool OffscreenTexture::isRenderable() {
assert(false);

View File

@@ -15,6 +15,8 @@
#include <mbgl/shaders/mtl/background_pattern.hpp>
#include <mbgl/shaders/mtl/circle.hpp>
#include <mbgl/shaders/mtl/clipping_mask.hpp>
#include <mbgl/shaders/mtl/collision_box.hpp>
#include <mbgl/shaders/mtl/collision_circle.hpp>
#include <mbgl/shaders/mtl/fill.hpp>
#include <mbgl/shaders/mtl/fill_extrusion.hpp>
#include <mbgl/shaders/mtl/fill_extrusion_pattern.hpp>
@@ -124,6 +126,8 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar
shaders::BuiltIn::BackgroundPatternShader,
shaders::BuiltIn::CircleShader,
shaders::BuiltIn::ClippingMaskProgram,
shaders::BuiltIn::CollisionBoxShader,
shaders::BuiltIn::CollisionCircleShader,
shaders::BuiltIn::FillShader,
shaders::BuiltIn::FillOutlineShader,
shaders::BuiltIn::FillOutlinePatternShader,

View File

@@ -56,6 +56,8 @@ size_t Texture2D::getPixelStride() const noexcept {
return 1 * numChannels();
case gfx::TextureChannelDataType::HalfFloat:
return 2 * numChannels();
case gfx::TextureChannelDataType::Float:
return 4 * numChannels();
}
}
@@ -65,6 +67,10 @@ size_t Texture2D::numChannels() const noexcept {
return 4;
case gfx::TexturePixelType::Alpha:
return 1;
case gfx::TexturePixelType::Stencil:
return 1;
case gfx::TexturePixelType::Depth:
return 1;
default:
return 0;
}
@@ -78,6 +84,8 @@ MTL::PixelFormat Texture2D::getMetalPixelFormat() const noexcept {
return MTL::PixelFormat::PixelFormatRGBA8Unorm;
case gfx::TexturePixelType::Alpha:
return MTL::PixelFormat::PixelFormatA8Unorm;
case gfx::TexturePixelType::Stencil:
return MTL::PixelFormat::PixelFormatStencil8;
default:
assert(false);
return MTL::PixelFormat::PixelFormatInvalid;
@@ -92,6 +100,18 @@ MTL::PixelFormat Texture2D::getMetalPixelFormat() const noexcept {
assert(false);
return MTL::PixelFormat::PixelFormatInvalid;
}
case gfx::TextureChannelDataType::Float:
switch (pixelFormat) {
case gfx::TexturePixelType::RGBA:
return MTL::PixelFormat::PixelFormatRGBA32Float;
case gfx::TexturePixelType::Alpha:
return MTL::PixelFormat::PixelFormatR32Float;
case gfx::TexturePixelType::Depth:
return MTL::PixelFormat::PixelFormatDepth32Float;
default:
assert(false);
return MTL::PixelFormat::PixelFormatInvalid;
}
default:
assert(false);
return MTL::PixelFormat::PixelFormatInvalid;

View File

@@ -66,30 +66,39 @@ shaders::ExpressionInputsUBO LayerTweaker::buildExpressionUBO(double zoom, uint6
0};
}
#if !MLN_RENDER_BACKEND_OPENGL
void LayerTweaker::setPropertiesAsUniforms(std::vector<std::string> props) {
if (props != propertiesAsUniforms) {
propertiesAsUniforms = std::move(props);
permutationUpdated = true;
}
}
#endif
bool LayerTweaker::hasPropertyAsUniform(const std::string_view attrName) const {
// `attrName` is expected to have the "a_" prefix, while the values in `propertiesAsUniforms`
// do not. Search for the former within the latter without allocating temporary strings.
return propertiesAsUniforms.end() !=
std::find_if(propertiesAsUniforms.begin(), propertiesAsUniforms.end(), [&](const auto& name) {
return name.size() + 2 == attrName.size() && 0 == std::strcmp(name.data(), attrName.data() + 2);
});
bool LayerTweaker::hasPropertyAsUniform(const StringIdentity attrNameID) const {
return propertiesAsUniforms.find(attrNameID) != propertiesAsUniforms.end();
}
using namespace shaders;
AttributeSource LayerTweaker::getAttributeSource(const std::string_view& attribName) const {
return hasPropertyAsUniform(attribName) ? AttributeSource::Constant : AttributeSource::PerVertex;
AttributeSource LayerTweaker::getAttributeSource(const StringIdentity attribNameID) const {
return hasPropertyAsUniform(attribNameID) ? AttributeSource::Constant : AttributeSource::PerVertex;
}
#endif // MLN_RENDER_BACKEND_METAL
void LayerTweaker::setPropertiesAsUniforms([[maybe_unused]] const std::unordered_set<StringIdentity>& props) {
#if MLN_RENDER_BACKEND_METAL
if (props != propertiesAsUniforms) {
propertiesAsUniforms = props;
permutationUpdated = true;
}
#endif
}
#if !MLN_RENDER_BACKEND_METAL
namespace {
const std::unordered_set<StringIdentity> emptyIDSet;
}
#endif
const std::unordered_set<StringIdentity>& LayerTweaker::getPropertiesAsUniforms() const {
#if MLN_RENDER_BACKEND_METAL
return propertiesAsUniforms;
#else
return emptyIDSet;
#endif
}
void LayerTweaker::enableOverdrawInspector(bool value) {
if (overdrawInspector != value) {
overdrawInspector = value;

View File

@@ -60,20 +60,15 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup,
const auto zoom = parameters.state.getZoom();
#if MLN_RENDER_BACKEND_METAL
using ShaderClass = shaders::ShaderSource<BuiltIn::CircleShader, gfx::Backend::Type::Metal>;
if (permutationUpdated) {
const auto source = [this](const std::string_view& attrName) {
return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex;
};
const CirclePermutationUBO permutationUBO = {
/* .color = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}},
/* .radius = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}},
/* .blur = */ {/*.source=*/source(ShaderClass::attributes[3].name), /*.expression=*/{}},
/* .opacity = */ {/*.source=*/source(ShaderClass::attributes[4].name), /*.expression=*/{}},
/* .stroke_color = */ {/*.source=*/source(ShaderClass::attributes[5].name), /*.expression=*/{}},
/* .stroke_width = */ {/*.source=*/source(ShaderClass::attributes[6].name), /*.expression=*/{}},
/* .stroke_opacity = */ {/*.source=*/source(ShaderClass::attributes[7].name), /*.expression=*/{}},
/* .color = */ {/*.source=*/getAttributeSource<BuiltIn::CircleShader>(1), /*.expression=*/{}},
/* .radius = */ {/*.source=*/getAttributeSource<BuiltIn::CircleShader>(2), /*.expression=*/{}},
/* .blur = */ {/*.source=*/getAttributeSource<BuiltIn::CircleShader>(3), /*.expression=*/{}},
/* .opacity = */ {/*.source=*/getAttributeSource<BuiltIn::CircleShader>(4), /*.expression=*/{}},
/* .stroke_color = */ {/*.source=*/getAttributeSource<BuiltIn::CircleShader>(5), /*.expression=*/{}},
/* .stroke_width = */ {/*.source=*/getAttributeSource<BuiltIn::CircleShader>(6), /*.expression=*/{}},
/* .stroke_opacity = */ {/*.source=*/getAttributeSource<BuiltIn::CircleShader>(7), /*.expression=*/{}},
/* .overdrawInspector = */ overdrawInspector,
/* .pad = */ 0,
0,

View File

@@ -9,6 +9,7 @@
#include <mbgl/renderer/render_tree.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/paint_property_binder.hpp>
#include <mbgl/shaders/collision_layer_ubo.hpp>
#include <mbgl/shaders/shader_program_base.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
#include <mbgl/util/convert.hpp>
@@ -18,18 +19,7 @@
namespace mbgl {
using namespace style;
namespace {
struct alignas(16) CollisionUBO {
std::array<float, 4 * 4> matrix;
std::array<float, 2> extrude_scale;
float camera_to_center_distance;
float overscale_factor;
};
static_assert(sizeof(CollisionUBO) == 20 * 4);
} // namespace
using namespace shaders;
const StringIdentity CollisionLayerTweaker::idCollisionCircleUBOName = stringIndexer().get(CollisionCircleUBOName);
const StringIdentity CollisionLayerTweaker::idCollisionBoxUBOName = stringIndexer().get(CollisionBoxUBOName);

View File

@@ -16,6 +16,10 @@
#include <mbgl/util/std.hpp>
#include <mbgl/util/string_indexer.hpp>
#if MLN_RENDER_BACKEND_METAL
#include <mbgl/shaders/mtl/fill_extrusion.hpp>
#endif
namespace mbgl {
using namespace shaders;
@@ -79,9 +83,9 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup,
const auto zoom = parameters.state.getZoom();
if (permutationUpdated) {
const FillExtrusionPermutationUBO permutationUBO = {
/* .color = */ {/*.source=*/getAttributeSource("a_color"), /*.expression=*/{}},
/* .base = */ {/*.source=*/getAttributeSource("a_base"), /*.expression=*/{}},
/* .height = */ {/*.source=*/getAttributeSource("a_height"), /*.expression=*/{}},
/* .color = */ {/*.source=*/getAttributeSource<BuiltIn::FillExtrusionShader>(2), /*.expression=*/{}},
/* .base = */ {/*.source=*/getAttributeSource<BuiltIn::FillExtrusionShader>(3), /*.expression=*/{}},
/* .height = */ {/*.source=*/getAttributeSource<BuiltIn::FillExtrusionShader>(4), /*.expression=*/{}},
/* .overdrawInspector = */ overdrawInspector,
/* .pad = */ 0,
0,

View File

@@ -78,26 +78,21 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str());
#endif
#if MLN_RENDER_BACKEND_METAL
const auto source = [this](const std::string_view& attrName) {
return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex;
};
#endif
// Only run each update function once
bool fillUniformBufferUpdated = false;
bool fillOutlineUniformBufferUpdated = false;
bool fillPatternUniformBufferUpdated = false;
bool fillOutlinePatternUniformBufferUpdated = false;
auto UpdateFillUniformBuffers = [&]() {
const auto UpdateFillUniformBuffers = [&]() {
if (fillUniformBufferUpdated) return;
fillUniformBufferUpdated = true;
#if MLN_RENDER_BACKEND_METAL
using ShaderClass = ShaderSource<BuiltIn::FillShader, gfx::Backend::Type::Metal>;
if (permutationUpdated || !fillPermutationUniformBuffer) {
const FillPermutationUBO permutationUBO = {
/* .color = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}},
/* .opacity = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}},
/* .color = */ {/*.source=*/getAttributeSource<BuiltIn::FillShader>(1), /*.expression=*/{}},
/* .opacity = */ {/*.source=*/getAttributeSource<BuiltIn::FillShader>(2), /*.expression=*/{}},
/* .overdrawInspector = */ overdrawInspector,
0,
0,
@@ -107,16 +102,11 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
0,
};
if (fillPermutationUniformBuffer) {
fillPermutationUniformBuffer->update(&permutationUBO, sizeof(permutationUBO));
} else {
fillPermutationUniformBuffer = context.createUniformBuffer(&permutationUBO, sizeof(permutationUBO));
}
fillUniformBufferUpdated = true;
context.emplaceOrUpdateUniformBuffer(fillPermutationUniformBuffer, &permutationUBO);
}
#endif
if (!fillPropsUniformBuffer) {
if (!fillPropsUniformBuffer || propertiesUpdated) {
const FillEvaluatedPropsUBO paramsUBO = {
/* .color = */ evaluated.get<FillColor>().constantOr(FillColor::defaultValue()),
/* .opacity = */ evaluated.get<FillOpacity>().constantOr(FillOpacity::defaultValue()),
@@ -124,19 +114,20 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
0,
0,
};
fillPropsUniformBuffer = context.createUniformBuffer(&paramsUBO, sizeof(paramsUBO));
context.emplaceOrUpdateUniformBuffer(fillPropsUniformBuffer, &paramsUBO);
}
};
auto UpdateFillOutlineUniformBuffers = [&]() {
const auto UpdateFillOutlineUniformBuffers = [&]() {
if (fillOutlineUniformBufferUpdated) return;
fillOutlineUniformBufferUpdated = true;
#if MLN_RENDER_BACKEND_METAL
using ShaderClass = ShaderSource<BuiltIn::FillOutlineShader, gfx::Backend::Type::Metal>;
if (permutationUpdated || !fillOutlinePermutationUniformBuffer) {
const FillOutlinePermutationUBO permutationUBO = {
/* .outline_color = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}},
/* .opacity = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}},
/* .outline_color = */ {/*.source=*/getAttributeSource<BuiltIn::FillOutlineShader>(1),
/*.expression=*/{}},
/* .opacity = */ {/*.source=*/getAttributeSource<BuiltIn::FillOutlineShader>(2), /*.expression=*/{}},
/* .overdrawInspector = */ overdrawInspector,
0,
0,
@@ -145,17 +136,11 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
0,
0,
};
if (fillOutlinePermutationUniformBuffer) {
fillOutlinePermutationUniformBuffer->update(&permutationUBO, sizeof(permutationUBO));
} else {
fillOutlinePermutationUniformBuffer = context.createUniformBuffer(&permutationUBO,
sizeof(permutationUBO));
}
context.emplaceOrUpdateUniformBuffer(fillOutlinePermutationUniformBuffer, &permutationUBO);
}
#endif
if (!fillOutlinePropsUniformBuffer) {
if (!fillOutlinePropsUniformBuffer || propertiesUpdated) {
const FillOutlineEvaluatedPropsUBO paramsUBO = {
/* .outline_color = */ evaluated.get<FillOutlineColor>().constantOr(FillOutlineColor::defaultValue()),
/* .opacity = */ evaluated.get<FillOpacity>().constantOr(FillOpacity::defaultValue()),
@@ -163,118 +148,104 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
0,
0,
};
fillOutlinePropsUniformBuffer = context.createUniformBuffer(&paramsUBO, sizeof(paramsUBO));
context.emplaceOrUpdateUniformBuffer(fillOutlinePropsUniformBuffer, &paramsUBO);
}
fillOutlineUniformBufferUpdated = true;
};
auto UpdateFillPatternUniformBuffers = [&]() {
const auto UpdateFillPatternUniformBuffers = [&]() {
if (fillPatternUniformBufferUpdated) return;
fillPatternUniformBufferUpdated = true;
#if MLN_RENDER_BACKEND_METAL
using ShaderClass = ShaderSource<BuiltIn::FillOutlinePatternShader, gfx::Backend::Type::Metal>;
if (permutationUpdated || !fillPatternPermutationUniformBuffer) {
const FillPatternPermutationUBO permutationUBO = {
/* .pattern_from = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}},
/* .pattern_to = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}},
/* .opacity = */ {/*.source=*/source(ShaderClass::attributes[3].name), /*.expression=*/{}},
/* .pattern_from = */ {/*.source=*/getAttributeSource<BuiltIn::FillPatternShader>(1),
/*.expression=*/{}},
/* .pattern_to = */
{/*.source=*/getAttributeSource<BuiltIn::FillPatternShader>(2), /*.expression=*/{}},
/* .opacity = */
{/*.source=*/getAttributeSource<BuiltIn::FillPatternShader>(3), /*.expression=*/{}},
/* .overdrawInspector = */ overdrawInspector,
0,
0,
0,
0,
};
if (fillPatternPermutationUniformBuffer) {
fillPatternPermutationUniformBuffer->update(&permutationUBO, sizeof(permutationUBO));
} else {
fillPatternPermutationUniformBuffer = context.createUniformBuffer(&permutationUBO,
sizeof(permutationUBO));
}
context.emplaceOrUpdateUniformBuffer(fillPatternPermutationUniformBuffer, &permutationUBO);
}
#endif
if (!fillPatternPropsUniformBuffer) {
if (!fillPatternPropsUniformBuffer || propertiesUpdated) {
const FillPatternEvaluatedPropsUBO paramsUBO = {
/* .opacity = */ evaluated.get<FillOpacity>().constantOr(FillOpacity::defaultValue()),
/* .fade = */ crossfade.t,
0,
0,
};
fillPatternPropsUniformBuffer = context.createUniformBuffer(&paramsUBO, sizeof(paramsUBO));
context.emplaceOrUpdateUniformBuffer(fillPatternPropsUniformBuffer, &paramsUBO);
}
fillPatternUniformBufferUpdated = true;
};
auto UpdateFillOutlinePatternUniformBuffers = [&]() {
const auto UpdateFillOutlinePatternUniformBuffers = [&]() {
if (fillOutlinePatternUniformBufferUpdated) return;
fillOutlinePatternUniformBufferUpdated = true;
#if MLN_RENDER_BACKEND_METAL
using ShaderClass = ShaderSource<BuiltIn::FillOutlinePatternShader, gfx::Backend::Type::Metal>;
if (permutationUpdated || !fillOutlinePatternPermutationUniformBuffer) {
const FillOutlinePatternPermutationUBO permutationUBO = {
/* .pattern_from = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}},
/* .pattern_to = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}},
/* .opacity = */ {/*.source=*/source(ShaderClass::attributes[3].name), /*.expression=*/{}},
/* .pattern_from = */ {/*.source=*/getAttributeSource<BuiltIn::FillOutlinePatternShader>(1),
/*.expression=*/{}},
/* .pattern_to = */
{/*.source=*/getAttributeSource<BuiltIn::FillOutlinePatternShader>(2), /*.expression=*/{}},
/* .opacity = */
{/*.source=*/getAttributeSource<BuiltIn::FillOutlinePatternShader>(3), /*.expression=*/{}},
/* .overdrawInspector = */ overdrawInspector,
0,
0,
0,
0,
};
if (fillOutlinePatternPermutationUniformBuffer) {
fillOutlinePatternPermutationUniformBuffer->update(&permutationUBO, sizeof(permutationUBO));
} else {
fillOutlinePatternPermutationUniformBuffer = context.createUniformBuffer(&permutationUBO,
sizeof(permutationUBO));
}
context.emplaceOrUpdateUniformBuffer(fillOutlinePatternPermutationUniformBuffer, &permutationUBO);
}
#endif
if (!fillOutlinePatternPropsUniformBuffer) {
if (!fillOutlinePatternPropsUniformBuffer || propertiesUpdated) {
const FillOutlinePatternEvaluatedPropsUBO paramsUBO = {
/* .opacity = */ evaluated.get<FillOpacity>().constantOr(FillOpacity::defaultValue()),
/* .fade = */ crossfade.t,
0,
0,
};
fillOutlinePatternPropsUniformBuffer = context.createUniformBuffer(&paramsUBO, sizeof(paramsUBO));
context.emplaceOrUpdateUniformBuffer(fillOutlinePatternPropsUniformBuffer, &paramsUBO);
}
fillOutlinePatternUniformBufferUpdated = true;
};
#if MLN_RENDER_BACKEND_METAL
if (!expressionUniformBuffer) {
const auto zoom = parameters.state.getZoom();
const auto expressionUBO = buildExpressionUBO(zoom, parameters.frameCount);
expressionUniformBuffer = context.createUniformBuffer(&expressionUBO, sizeof(expressionUBO));
}
const auto zoom = parameters.state.getZoom();
const auto expressionUBO = buildExpressionUBO(zoom, parameters.frameCount);
context.emplaceOrUpdateUniformBuffer(expressionUniformBuffer, &expressionUBO);
#endif
const auto& translation = evaluated.get<FillTranslate>();
const auto anchor = evaluated.get<FillTranslateAnchor>();
const auto renderableSize = parameters.backend.getDefaultRenderable().getSize();
const auto intZoom = parameters.state.getIntegerZoom();
const auto pixelRatio = parameters.pixelRatio;
layerGroup.visitDrawables([&](gfx::Drawable& drawable) {
if (!drawable.getTileID() || !checkTweakDrawable(drawable)) {
return;
}
auto& uniforms = drawable.mutableUniformBuffers();
// auto& drawableType = drawable.getShader()->typeName();
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
const auto& translation = evaluated.get<FillTranslate>();
const auto anchor = evaluated.get<FillTranslateAnchor>();
constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix
constexpr bool nearClipped = false;
const auto matrix = getTileMatrix(
tileID, renderTree, parameters.state, translation, anchor, nearClipped, inViewportPixelUnits);
// from FillPatternProgram::layoutUniformValues
const auto renderableSize = parameters.backend.getDefaultRenderable().getSize();
const auto intZoom = parameters.state.getIntegerZoom();
const auto tileRatio = 1.0f / tileID.pixelsToTileUnits(1.0f, intZoom);
const int32_t tileSizeAtNearestZoom = static_cast<int32_t>(
util::tileSize_D * parameters.state.zoomScale(intZoom - tileID.canonical.z));
@@ -282,7 +253,6 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
tileSizeAtNearestZoom *
(tileID.canonical.x + tileID.wrap * parameters.state.zoomScale(tileID.canonical.z)));
const int32_t pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
const auto pixelRatio = parameters.pixelRatio;
Size textureSize = {0, 0};
if (const auto shader = drawable.getShader()) {
@@ -293,12 +263,13 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
}
}
auto& uniforms = drawable.mutableUniformBuffers();
if (uniforms.get(idFillInterpolateUBOName)) {
UpdateFillUniformBuffers();
uniforms.addOrReplace(idFillEvaluatedPropsUBOName, fillPropsUniformBuffer);
const FillDrawableUBO drawableUBO = {/*.matrix=*/util::cast<float>(matrix)};
const FillDrawableUBO drawableUBO = {/*.matrix=*/util::cast<float>(matrix)};
uniforms.createOrUpdate(idFillDrawableUBOName, &drawableUBO, context);
#if MLN_RENDER_BACKEND_METAL
@@ -308,12 +279,12 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
UpdateFillOutlineUniformBuffers();
uniforms.addOrReplace(idFillOutlineEvaluatedPropsUBOName, fillOutlinePropsUniformBuffer);
const FillOutlineDrawableUBO drawableUBO = {
/*.matrix=*/util::cast<float>(matrix),
/*.world=*/{(float)renderableSize.width, (float)renderableSize.height},
/* pad1 */ 0,
/* pad2 */ 0};
uniforms.createOrUpdate(idFillOutlineDrawableUBOName, &drawableUBO, context);
#if MLN_RENDER_BACKEND_METAL
@@ -323,6 +294,7 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
UpdateFillPatternUniformBuffers();
uniforms.addOrReplace(idFillPatternEvaluatedPropsUBOName, fillPatternPropsUniformBuffer);
const FillPatternDrawableUBO drawableUBO = {
/*.matrix=*/util::cast<float>(matrix),
/*.scale=*/{pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale},
@@ -332,7 +304,6 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
0,
0,
};
uniforms.createOrUpdate(idFillPatternDrawableUBOName, &drawableUBO, context);
#if MLN_RENDER_BACKEND_METAL
@@ -342,6 +313,7 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
UpdateFillOutlinePatternUniformBuffers();
uniforms.addOrReplace(idFillOutlinePatternEvaluatedPropsUBOName, fillOutlinePatternPropsUniformBuffer);
const FillOutlinePatternDrawableUBO drawableUBO = {
/*.matrix=*/util::cast<float>(matrix),
/*.scale=*/{pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale},
@@ -350,7 +322,6 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
/*.pixel_coord_lower=*/{static_cast<float>(pixelX & 0xFFFF), static_cast<float>(pixelY & 0xFFFF)},
/*.texsize=*/{static_cast<float>(textureSize.width), static_cast<float>(textureSize.height)},
};
uniforms.createOrUpdate(idFillOutlinePatternDrawableUBOName, &drawableUBO, context);
#if MLN_RENDER_BACKEND_METAL
@@ -364,6 +335,7 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup,
});
permutationUpdated = false;
propertiesUpdated = false;
}
} // namespace mbgl

View File

@@ -43,15 +43,10 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup,
const auto zoom = parameters.state.getZoom();
#if MLN_RENDER_BACKEND_METAL
using ShaderClass = shaders::ShaderSource<BuiltIn::HeatmapShader, gfx::Backend::Type::Metal>;
if (permutationUpdated) {
const auto source = [this](const std::string_view& attrName) {
return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex;
};
const HeatmapPermutationUBO permutationUBO = {
/* .weight = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}},
/* .radius = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}},
/* .weight = */ {/*.source=*/getAttributeSource<BuiltIn::HeatmapShader>(1), /*.expression=*/{}},
/* .radius = */ {/*.source=*/getAttributeSource<BuiltIn::HeatmapShader>(2), /*.expression=*/{}},
/* .overdrawInspector = */ overdrawInspector,
/* .pad1/2/3 = */ 0,
0,

View File

@@ -112,19 +112,14 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup,
};
#if MLN_RENDER_BACKEND_METAL
using LineShaderClass = shaders::ShaderSource<BuiltIn::LineShader, gfx::Backend::Type::Metal>;
if (permutationUpdated) {
const auto source = [this](const std::string_view& attrName) {
return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex;
};
const LinePermutationUBO permutationUBO = {
/* .color = */ {/*.source=*/source(LineShaderClass::attributes[2].name), /*.expression=*/{}},
/* .blur = */ {/*.source=*/source(LineShaderClass::attributes[3].name), /*.expression=*/{}},
/* .opacity = */ {/*.source=*/source(LineShaderClass::attributes[4].name), /*.expression=*/{}},
/* .gapwidth = */ {/*.source=*/source(LineShaderClass::attributes[5].name), /*.expression=*/{}},
/* .offset = */ {/*.source=*/source(LineShaderClass::attributes[6].name), /*.expression=*/{}},
/* .width = */ {/*.source=*/source(LineShaderClass::attributes[7].name), /*.expression=*/{}},
/* .color = */ {/*.source=*/getAttributeSource<BuiltIn::LineShader>(2), /*.expression=*/{}},
/* .blur = */ {/*.source=*/getAttributeSource<BuiltIn::LineShader>(3), /*.expression=*/{}},
/* .opacity = */ {/*.source=*/getAttributeSource<BuiltIn::LineShader>(4), /*.expression=*/{}},
/* .gapwidth = */ {/*.source=*/getAttributeSource<BuiltIn::LineShader>(5), /*.expression=*/{}},
/* .offset = */ {/*.source=*/getAttributeSource<BuiltIn::LineShader>(6), /*.expression=*/{}},
/* .width = */ {/*.source=*/getAttributeSource<BuiltIn::LineShader>(7), /*.expression=*/{}},
/* .floorwidth = */ {/*.source=*/AttributeSource::Constant, /*.expression=*/{}},
/* .pattern_from = */ {/*.source=*/AttributeSource::Constant, /*.expression=*/{}},
/* .pattern_to = */ {/*.source=*/AttributeSource::Constant, /*.expression=*/{}},

View File

@@ -326,6 +326,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
[&](gfx::Drawable& drawable) { return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); });
const auto& evaluated = static_cast<const CircleLayerProperties&>(*evaluatedProperties).evaluated;
std::unordered_set<StringIdentity> propertiesAsUniforms;
for (const RenderTile& tile : *renderTiles) {
const auto& tileID = tile.getOverscaledTileID();
@@ -377,15 +378,16 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
const auto interpBuffer = context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO));
propertiesAsUniforms.clear();
gfx::VertexAttributeArray circleVertexAttrs;
auto propertiesAsUniforms = circleVertexAttrs.readDataDrivenPaintProperties<CircleColor,
CircleRadius,
CircleBlur,
CircleOpacity,
CircleStrokeColor,
CircleStrokeWidth,
CircleStrokeOpacity>(
paintPropertyBinders, evaluated);
circleVertexAttrs.readDataDrivenPaintProperties<CircleColor,
CircleRadius,
CircleBlur,
CircleOpacity,
CircleStrokeColor,
CircleStrokeWidth,
CircleStrokeOpacity>(
paintPropertyBinders, evaluated, propertiesAsUniforms);
if (!circleShaderGroup) {
continue;
@@ -396,7 +398,7 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
}
if (layerTweaker) {
layerTweaker->setPropertiesAsUniforms(std::move(propertiesAsUniforms));
layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms);
}
if (const auto& attr = circleVertexAttrs.add(idVertexAttribName)) {

View File

@@ -341,6 +341,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
return;
}
std::unordered_set<StringIdentity> propertiesAsUniforms;
for (const RenderTile& tile : *renderTiles) {
const auto& tileID = tile.getOverscaledTileID();
@@ -412,16 +413,17 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
continue;
}
gfx::VertexAttributeArray vertexAttrs;
const auto propertiesAsUniforms = vertexAttrs.readDataDrivenPaintProperties<FillExtrusionBase,
FillExtrusionColor,
FillExtrusionHeight,
FillExtrusionPattern>(binders,
evaluated);
if (!shaderGroup) {
continue;
}
gfx::VertexAttributeArray vertexAttrs;
propertiesAsUniforms.clear();
vertexAttrs.readDataDrivenPaintProperties<FillExtrusionBase,
FillExtrusionColor,
FillExtrusionHeight,
FillExtrusionPattern>(binders, evaluated, propertiesAsUniforms);
const auto shader = std::static_pointer_cast<gfx::ShaderProgramBase>(
shaderGroup->getOrCreateShader(context, propertiesAsUniforms));
if (!shader) {
@@ -429,7 +431,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
}
if (layerTweaker) {
layerTweaker->setPropertiesAsUniforms(std::move(propertiesAsUniforms));
layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms);
}
// The non-pattern path in `render()` only uses two-pass rendering if there's translucency.

View File

@@ -102,9 +102,8 @@ void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) {
evaluatedProperties = std::move(properties);
#if MLN_DRAWABLE_RENDERER
if (layerGroup) {
auto newTweaker = std::make_shared<FillLayerTweaker>(getID(), evaluatedProperties);
replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup});
if (layerTweaker) {
layerTweaker->updateProperties(evaluatedProperties);
}
#endif
}
@@ -372,6 +371,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
return tileID && !hasRenderTile(*tileID);
});
std::unordered_set<StringIdentity> propertiesAsUniforms;
for (const RenderTile& tile : *renderTiles) {
const auto& tileID = tile.getOverscaledTileID();
@@ -502,9 +502,9 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
// `Fill*Program` all use `style::FillPaintProperties`
gfx::VertexAttributeArray vertexAttrs;
const auto propertiesAsUniforms =
vertexAttrs.readDataDrivenPaintProperties<FillColor, FillOpacity, FillOutlineColor, FillPattern>(binders,
evaluated);
propertiesAsUniforms.clear();
vertexAttrs.readDataDrivenPaintProperties<FillColor, FillOpacity, FillOutlineColor, FillPattern>(
binders, evaluated, propertiesAsUniforms);
if (layerTweaker) {
layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms);

View File

@@ -353,6 +353,7 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
[&](gfx::Drawable& drawable) { return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); });
const auto& evaluated = static_cast<const HeatmapLayerProperties&>(*evaluatedProperties).evaluated;
std::unordered_set<StringIdentity> propertiesAsUniforms;
for (const RenderTile& tile : *renderTiles) {
const auto& tileID = tile.getOverscaledTileID();
@@ -389,9 +390,10 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
};
gfx::VertexAttributeArray heatmapVertexAttrs;
const auto propertiesAsUniforms =
heatmapVertexAttrs.readDataDrivenPaintProperties<HeatmapWeight, HeatmapRadius>(paintPropertyBinders,
evaluated);
propertiesAsUniforms.clear();
heatmapVertexAttrs.readDataDrivenPaintProperties<HeatmapWeight, HeatmapRadius>(
paintPropertyBinders, evaluated, propertiesAsUniforms);
if (layerTweaker) {
layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms);
}

View File

@@ -83,6 +83,12 @@ void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) {
#if MLN_DRAWABLE_RENDERER
if (layerGroup) {
auto newTweaker = std::make_shared<LineLayerTweaker>(getID(), evaluatedProperties);
// propertiesAsUniforms isn't recalculated every update, so carry it over
if (layerTweaker) {
newTweaker->setPropertiesAsUniforms(layerTweaker->getPropertiesAsUniforms());
}
replaceTweaker(layerTweaker, std::move(newTweaker), {layerGroup});
}
#endif
@@ -459,6 +465,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
builder->setSegments(gfx::Triangles(), bucket.sharedTriangles, bucket.segments.data(), bucket.segments.size());
};
std::unordered_set<StringIdentity> propertiesAsUniforms;
for (const RenderTile& tile : *renderTiles) {
const auto& tileID = tile.getOverscaledTileID();
@@ -565,6 +572,8 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
else if (shaderUniforms.get(idLineSDFInterpolationUBOName)) {
drawableUniforms.createOrUpdate(idLineSDFInterpolationUBOName, &lineSDFInterpolationUBO, context);
}
// TODO: vertex attributes or `propertiesAsUniforms` updated, is that needed?
});
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) {
@@ -572,27 +581,29 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
}
if (!evaluated.get<LineDasharray>().from.empty()) {
// dash array line (SDF)
gfx::VertexAttributeArray vertexAttrs;
auto propertiesAsUniforms = vertexAttrs.readDataDrivenPaintProperties<LineColor,
LineBlur,
LineOpacity,
LineGapWidth,
LineOffset,
LineWidth,
LineFloorWidth>(paintPropertyBinders,
evaluated);
if (!lineSDFShaderGroup) {
continue;
}
// dash array line (SDF)
propertiesAsUniforms.clear();
gfx::VertexAttributeArray vertexAttrs;
vertexAttrs.readDataDrivenPaintProperties<LineColor,
LineBlur,
LineOpacity,
LineGapWidth,
LineOffset,
LineWidth,
LineFloorWidth>(
paintPropertyBinders, evaluated, propertiesAsUniforms);
auto shader = lineSDFShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
if (!shader) {
continue;
}
if (layerTweaker) {
layerTweaker->setPropertiesAsUniforms(std::move(propertiesAsUniforms));
layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms);
}
auto builder = createLineBuilder("lineSDF", std::move(shader));
@@ -617,27 +628,26 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
++stats.drawablesAdded;
}
} else if (!unevaluated.get<LinePattern>().isUndefined()) {
// pattern line
gfx::VertexAttributeArray vertexAttrs;
paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade);
auto propertiesAsUniforms = vertexAttrs.readDataDrivenPaintProperties<LineBlur,
LineOpacity,
LineOffset,
LineGapWidth,
LineWidth,
LinePattern>(paintPropertyBinders,
evaluated);
if (!linePatternShaderGroup) {
continue;
}
// pattern line
paintPropertyBinders.setPatternParameters(patternPosA, patternPosB, crossfade);
propertiesAsUniforms.clear();
gfx::VertexAttributeArray vertexAttrs;
vertexAttrs
.readDataDrivenPaintProperties<LineBlur, LineOpacity, LineOffset, LineGapWidth, LineWidth, LinePattern>(
paintPropertyBinders, evaluated, propertiesAsUniforms);
auto shader = linePatternShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
if (!shader) {
continue;
}
if (layerTweaker) {
layerTweaker->setPropertiesAsUniforms(std::move(propertiesAsUniforms));
layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms);
}
auto builder = createLineBuilder("linePattern", std::move(shader));
@@ -678,22 +688,23 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
}
}
} else if (!unevaluated.get<LineGradient>().getValue().isUndefined()) {
// gradient line
gfx::VertexAttributeArray vertexAttrs;
auto propertiesAsUniforms =
vertexAttrs.readDataDrivenPaintProperties<LineBlur, LineOpacity, LineGapWidth, LineOffset, LineWidth>(
paintPropertyBinders, evaluated);
if (!lineGradientShaderGroup) {
continue;
}
// gradient line
propertiesAsUniforms.clear();
gfx::VertexAttributeArray vertexAttrs;
vertexAttrs.readDataDrivenPaintProperties<LineBlur, LineOpacity, LineGapWidth, LineOffset, LineWidth>(
paintPropertyBinders, evaluated, propertiesAsUniforms);
auto shader = lineGradientShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
if (!shader) {
continue;
}
if (layerTweaker) {
layerTweaker->setPropertiesAsUniforms(std::move(propertiesAsUniforms));
layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms);
}
auto builder = createLineBuilder("lineGradient", std::move(shader));
@@ -731,33 +742,25 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
}
}
}
} else {
// simple line
gfx::VertexAttributeArray vertexAttrs;
const auto propertiesAsUniforms = vertexAttrs.readDataDrivenPaintProperties<LineColor,
LineBlur,
LineOpacity,
LineGapWidth,
LineOffset,
LineWidth>(paintPropertyBinders,
evaluated);
assert(6 == propertiesAsUniforms.size());
assert(vertexAttrs.size() == (size_t)std::count_if(propertiesAsUniforms.begin(),
propertiesAsUniforms.end(),
[](const auto& s) { return s.empty(); }));
if (!lineShaderGroup) {
continue;
}
// simple line
propertiesAsUniforms.clear();
gfx::VertexAttributeArray vertexAttrs;
vertexAttrs
.readDataDrivenPaintProperties<LineColor, LineBlur, LineOpacity, LineGapWidth, LineOffset, LineWidth>(
paintPropertyBinders, evaluated, propertiesAsUniforms);
auto shader = lineShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
if (!shader) {
continue;
}
if (layerTweaker) {
layerTweaker->setPropertiesAsUniforms(std::move(propertiesAsUniforms));
layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms);
}
auto builder = createLineBuilder("line", std::move(shader));

View File

@@ -748,19 +748,21 @@ SymbolDrawableTilePropsUBO buildTileUBO(const SymbolBucket& bucket,
};
}
const StringIdentity idDataAttibName = stringIndexer().get("a_data");
const StringIdentity idPosOffsetAttribName = stringIndexer().get("a_pos_offset");
const StringIdentity idPixOffsetAttribName = stringIndexer().get("a_pixeloffset");
const StringIdentity idProjPosAttribName = stringIndexer().get("a_projected_pos");
const StringIdentity idFadeOpacityAttribName = stringIndexer().get("a_fade_opacity");
const StringIdentity idTexUniformName = stringIndexer().get("u_texture");
const StringIdentity idTexIconUniformName = stringIndexer().get("u_texture_icon");
const auto idDataAttibName = stringIndexer().get("a_data");
const auto posOffsetAttribName = "a_pos_offset";
const auto idPosOffsetAttribName = stringIndexer().get(posOffsetAttribName);
const auto idPixOffsetAttribName = stringIndexer().get("a_pixeloffset");
const auto idProjPosAttribName = stringIndexer().get("a_projected_pos");
const auto idFadeOpacityAttribName = stringIndexer().get("a_fade_opacity");
const auto idTexUniformName = stringIndexer().get("u_texture");
const auto 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) {
void updateTileAttributes(const SymbolBucket::Buffer& buffer,
const bool isText,
const SymbolBucket::PaintProperties& paintProps,
const SymbolPaintProperties::PossiblyEvaluated& evaluated,
gfx::VertexAttributeArray& attribs,
std::unordered_set<StringIdentity>& propertiesAsUniforms) {
if (const auto& attr = attribs.getOrAdd(idPosOffsetAttribName)) {
attr->setSharedRawData(buffer.sharedVertices,
offsetof(SymbolLayoutVertex, a1),
@@ -800,13 +802,13 @@ std::vector<std::string> updateTileAttributes(const SymbolBucket::Buffer& buffer
gfx::AttributeDataType::Float);
}
return isText
? attribs
.readDataDrivenPaintProperties<TextOpacity, TextColor, TextHaloColor, TextHaloWidth, TextHaloBlur>(
paintProps.textBinders, evaluated)
: attribs
.readDataDrivenPaintProperties<IconOpacity, IconColor, IconHaloColor, IconHaloWidth, IconHaloBlur>(
paintProps.iconBinders, evaluated);
if (isText) {
attribs.readDataDrivenPaintProperties<TextOpacity, TextColor, TextHaloColor, TextHaloWidth, TextHaloBlur>(
paintProps.textBinders, evaluated, propertiesAsUniforms);
} else {
attribs.readDataDrivenPaintProperties<IconOpacity, IconColor, IconHaloColor, IconHaloWidth, IconHaloBlur>(
paintProps.iconBinders, evaluated, propertiesAsUniforms);
}
}
void updateTileDrawable(gfx::Drawable& drawable,
@@ -816,7 +818,8 @@ void updateTileDrawable(gfx::Drawable& drawable,
const SymbolPaintProperties::PossiblyEvaluated& evaluated,
const TransformState& state,
gfx::UniformBufferPtr& textInterpUBO,
gfx::UniformBufferPtr& iconInterpUBO) {
gfx::UniformBufferPtr& iconInterpUBO,
std::unordered_set<StringIdentity>& propertiesAsUniforms) {
if (!drawable.getData()) {
return;
}
@@ -858,7 +861,7 @@ void updateTileDrawable(gfx::Drawable& drawable,
// See `Placement::updateBucketDynamicVertices`
gfx::VertexAttributeArray attribs;
updateTileAttributes(buffer, isText, paintProps, evaluated, attribs);
updateTileAttributes(buffer, isText, paintProps, evaluated, attribs, propertiesAsUniforms);
drawable.setVertexAttributes(std::move(attribs));
}
@@ -1085,6 +1088,7 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
collisionBuilder->setColorMode(gfx::ColorMode::alphaBlended());
collisionBuilder->setVertexAttrNameId(idCollisionPosAttribName);
std::unordered_set<StringIdentity> propertiesAsUniforms;
for (const RenderTile& tile : *renderTiles) {
const auto& tileID = tile.getOverscaledTileID();
@@ -1195,8 +1199,16 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
}
const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderData.layerProperties);
updateTileDrawable(
drawable, context, bucket, bucketPaintProperties, evaluated, state, textInterpUBO, iconInterpUBO);
propertiesAsUniforms.clear();
updateTileDrawable(drawable,
context,
bucket,
bucketPaintProperties,
evaluated,
state,
textInterpUBO,
iconInterpUBO,
propertiesAsUniforms);
});
// re-create collision drawables
@@ -1280,9 +1292,9 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
const auto vertexCount = buffer.vertices().elements();
propertiesAsUniforms.clear();
gfx::VertexAttributeArray attribs;
const auto propertiesAsUniforms = updateTileAttributes(
buffer, isText, bucketPaintProperties, evaluated, attribs);
updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, attribs, propertiesAsUniforms);
if (layerTweaker) {
layerTweaker->setPropertiesAsUniforms(propertiesAsUniforms);
}
@@ -1354,8 +1366,8 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
if (!shaderGroup) {
return;
}
const auto shader = std::static_pointer_cast<gfx::ShaderProgramBase>(shaderGroup->getOrCreateShader(
context, propertiesAsUniforms, stringIndexer().get(idPosOffsetAttribName)));
const auto shader = std::static_pointer_cast<gfx::ShaderProgramBase>(
shaderGroup->getOrCreateShader(context, propertiesAsUniforms, posOffsetAttribName));
if (!shader) {
return;
}

View File

@@ -19,6 +19,7 @@
#if MLN_RENDER_BACKEND_METAL
#include <mbgl/shaders/mtl/symbol_icon.hpp>
#include <mbgl/shaders/mtl/symbol_sdf.hpp>
#endif // MLN_RENDER_BACKEND_METAL
namespace mbgl {
@@ -92,11 +93,11 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup,
#if MLN_RENDER_BACKEND_METAL
if (permutationUpdated) {
const SymbolPermutationUBO permutationUBO = {
/* .fill_color = */ {/*.source=*/getAttributeSource("a_fill_color"), /*.expression=*/{}},
/* .halo_color = */ {/*.source=*/getAttributeSource("a_halo_color"), /*.expression=*/{}},
/* .opacity = */ {/*.source=*/getAttributeSource("a_opacity"), /*.expression=*/{}},
/* .halo_width = */ {/*.source=*/getAttributeSource("a_halo_width"), /*.expression=*/{}},
/* .halo_blur = */ {/*.source=*/getAttributeSource("a_halo_blur"), /*.expression=*/{}},
/* .fill_color = */ {/*.source=*/getAttributeSource<BuiltIn::SymbolSDFIconShader>(5), /*.expression=*/{}},
/* .halo_color = */ {/*.source=*/getAttributeSource<BuiltIn::SymbolSDFIconShader>(6), /*.expression=*/{}},
/* .opacity = */ {/*.source=*/getAttributeSource<BuiltIn::SymbolSDFIconShader>(7), /*.expression=*/{}},
/* .halo_width = */ {/*.source=*/getAttributeSource<BuiltIn::SymbolSDFIconShader>(8), /*.expression=*/{}},
/* .halo_blur = */ {/*.source=*/getAttributeSource<BuiltIn::SymbolSDFIconShader>(9), /*.expression=*/{}},
/* .overdrawInspector = */ overdrawInspector,
/* .pad = */ 0,
0,

View File

@@ -157,6 +157,24 @@ void PaintParameters::clearTileClippingMasks() {
}
}
#if MLN_RENDER_BACKEND_METAL
namespace {
const auto clipMaskStencilMode = gfx::StencilMode{
/*.test=*/gfx::StencilMode::Always(),
/*.ref=*/0,
/*.mask=*/0b11111111,
/*.fail=*/gfx::StencilOpType::Keep,
/*.depthFail=*/gfx::StencilOpType::Keep,
/*.pass=*/gfx::StencilOpType::Replace,
};
const auto clipMaskDepthMode = gfx::DepthMode{
/*.func=*/gfx::DepthFunctionType::Always,
/*.mask=*/gfx::DepthMaskType::ReadOnly,
/*.range=*/{0, 1},
};
} // namespace
#endif // MLN_RENDER_BACKEND_METAL
template <typename TIter>
void PaintParameters::renderTileClippingMasks(TIter beg, TIter end, GetTileIDFunc<TIter>&& f, bool clear) {
if (tileIDsIdentical(beg, end, f, tileClippingMaskIDs)) {
@@ -238,32 +256,13 @@ void PaintParameters::renderTileClippingMasks(TIter beg, TIter end, GetTileIDFun
// gfx::CullFaceMode::disabled();
encoder->setCullMode(MTL::CullModeNone);
auto stencilDescriptor = NS::TransferPtr(MTL::StencilDescriptor::alloc()->init());
if (!stencilDescriptor) {
if (auto depthStencilState = mtlContext.makeDepthStencilState(
clipMaskDepthMode, clipMaskStencilMode, mtlRenderPass)) {
encoder->setDepthStencilState(depthStencilState.get());
} else {
assert(!"Failed to create depth-stencil state");
return;
}
stencilDescriptor->setStencilCompareFunction(MTL::CompareFunction::CompareFunctionAlways);
stencilDescriptor->setStencilFailureOperation(MTL::StencilOperation::StencilOperationKeep);
stencilDescriptor->setDepthFailureOperation(MTL::StencilOperation::StencilOperationKeep);
stencilDescriptor->setDepthStencilPassOperation(MTL::StencilOperation::StencilOperationReplace);
stencilDescriptor->setReadMask(0);
stencilDescriptor->setWriteMask(0b11111111);
auto depthStencilDescriptor = NS::TransferPtr(MTL::DepthStencilDescriptor::alloc()->init());
if (!depthStencilDescriptor) {
return;
}
depthStencilDescriptor->setDepthCompareFunction(MTL::CompareFunction::CompareFunctionAlways);
depthStencilDescriptor->setDepthWriteEnabled(false);
depthStencilDescriptor->setFrontFaceStencil(stencilDescriptor.get());
depthStencilDescriptor->setBackFaceStencil(stencilDescriptor.get());
auto& device = mtlContext.getBackend().getDevice();
auto depthStencilState = NS::TransferPtr(device->newDepthStencilState(depthStencilDescriptor.get()));
if (!depthStencilState) {
return;
}
encoder->setDepthStencilState(depthStencilState.get());
// Create a render pipeline state, telling Metal how to render the primitives
const auto& renderPassDescriptor = mtlRenderPass.getDescriptor();

View File

@@ -392,10 +392,7 @@ void Renderer::Impl::render(const RenderTree& renderTree,
// Ends the RenderPass
parameters.renderPass.reset();
const bool isMapModeContinuous = renderTreeParameters.mapMode == MapMode::Continuous;
if (isMapModeContinuous) {
parameters.encoder->present(parameters.backend.getDefaultRenderable());
}
parameters.encoder->present(parameters.backend.getDefaultRenderable());
// CommandEncoder destructor submits render commands.
parameters.encoder.reset();

View File

@@ -24,11 +24,13 @@ void ImageSourceRenderData::upload(gfx::UploadPass& uploadPass) const {
bucket->upload(uploadPass);
}
#if MLN_LEGACY_RENDERER
if (!debugTexture) {
std::array<uint8_t, 4> data{{0, 0, 0, 0}};
static const PremultipliedImage emptyImage{Size(1, 1), data.data(), data.size()};
debugTexture = uploadPass.createTexture(emptyImage);
}
#endif
}
void ImageSourceRenderData::render(PaintParameters& parameters) const {

View File

@@ -0,0 +1,17 @@
#include <mbgl/shaders/mtl/background.hpp>
#include <mbgl/shaders/background_layer_ubo.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 1> ShaderSource<BuiltIn::BackgroundShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Float3, 1, "a_pos"},
};
const std::array<UniformBlockInfo, 2> ShaderSource<BuiltIn::BackgroundShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{1, true, true, sizeof(BackgroundLayerUBO), "BackgroundLayerUBO"},
UniformBlockInfo{2, true, false, sizeof(BackgroundDrawableUBO), "BackgroundDrawableUBO"},
};
const std::array<TextureInfo, 0> ShaderSource<BuiltIn::BackgroundShader, gfx::Backend::Type::Metal>::textures = {};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,14 @@
#include <mbgl/shaders/mtl/background_pattern.hpp>
namespace mbgl {
namespace shaders {
const std::array<UniformBlockInfo, 3>
ShaderSource<BuiltIn::BackgroundPatternShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{1, sizeof(BackgroundLayerUBO), true, false, "BackgroundLayerUBO"},
UniformBlockInfo{2, sizeof(BackgroundDrawableUBO), true, false, "BackgroundDrawableUBO"},
UniformBlockInfo{3, sizeof(BackgroundPatternLayerUBO), true, false, "BackgroundLayerUBO"},
};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,27 @@
#include <mbgl/shaders/mtl/circle.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 8> ShaderSource<BuiltIn::CircleShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
AttributeInfo{1, gfx::AttributeDataType::Float2, 1, "a_color"},
AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_radius"},
AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_blur"},
AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_opacity"},
AttributeInfo{5, gfx::AttributeDataType::Float4, 1, "a_stroke_color"},
AttributeInfo{6, gfx::AttributeDataType::Float2, 1, "a_stroke_width"},
AttributeInfo{7, gfx::AttributeDataType::Float2, 1, "a_stroke_opacity"},
};
const std::array<UniformBlockInfo, 6> ShaderSource<BuiltIn::CircleShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{8, true, false, sizeof(CircleDrawableUBO), "CircleDrawableUBO"},
UniformBlockInfo{9, true, true, sizeof(CirclePaintParamsUBO), "CirclePaintParamsUBO"},
UniformBlockInfo{10, true, true, sizeof(CircleEvaluatedPropsUBO), "CircleEvaluatedPropsUBO"},
UniformBlockInfo{11, true, false, sizeof(CircleInterpolateUBO), "CircleInterpolateUBO"},
UniformBlockInfo{12, true, true, sizeof(CirclePermutationUBO), "CirclePermutationUBO"},
UniformBlockInfo{13, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 0> ShaderSource<BuiltIn::CircleShader, gfx::Backend::Type::Metal>::textures = {};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,16 @@
#include <mbgl/shaders/mtl/clipping_mask.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 1> ShaderSource<BuiltIn::ClippingMaskProgram, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Float3, 1, "a_pos"},
};
const std::array<UniformBlockInfo, 1> ShaderSource<BuiltIn::ClippingMaskProgram, gfx::Backend::Type::Metal>::uniforms =
{
UniformBlockInfo{1, true, false, sizeof(ClipUBO), "ClipUBO"},
};
const std::array<TextureInfo, 0> ShaderSource<BuiltIn::ClippingMaskProgram, gfx::Backend::Type::Metal>::textures = {};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,19 @@
#include <mbgl/shaders/mtl/collision_box.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 5> ShaderSource<BuiltIn::CollisionBoxShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_anchor_pos"},
AttributeInfo{2, gfx::AttributeDataType::Short2, 1, "a_extrude"},
AttributeInfo{3, gfx::AttributeDataType::UByte2, 1, "a_placed"},
AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_shift"},
};
const std::array<UniformBlockInfo, 1> ShaderSource<BuiltIn::CollisionBoxShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{5, true, true, sizeof(CollisionUBO), "CollisionBoxUBO"},
};
const std::array<TextureInfo, 0> ShaderSource<BuiltIn::CollisionBoxShader, gfx::Backend::Type::Metal>::textures = {};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,20 @@
#include <mbgl/shaders/mtl/collision_circle.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 4> ShaderSource<BuiltIn::CollisionCircleShader, gfx::Backend::Type::Metal>::attributes =
{
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_anchor_pos"},
AttributeInfo{2, gfx::AttributeDataType::Short2, 1, "a_extrude"},
AttributeInfo{3, gfx::AttributeDataType::UByte2, 1, "a_placed"},
};
const std::array<UniformBlockInfo, 1>
ShaderSource<BuiltIn::CollisionCircleShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{5, true, true, sizeof(CollisionUBO), "CollisionCircleUBO"},
};
const std::array<TextureInfo, 0> ShaderSource<BuiltIn::CollisionCircleShader, gfx::Backend::Type::Metal>::textures = {};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,82 @@
#include <mbgl/shaders/mtl/fill.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 4> ShaderSource<BuiltIn::FillShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
AttributeInfo{1, gfx::AttributeDataType::Float2, 1, "a_color"},
AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_opacity"},
// This shader doesn't use it, but we need this so that the layer can assign the same
// attributes to all the drawables. If/When `VertexAttributeArray::resolve` allows it,
// this can be removed.
AttributeInfo{8, gfx::AttributeDataType::Float2, 1, "a_outline_color"},
};
const std::array<UniformBlockInfo, 5> ShaderSource<BuiltIn::FillShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{3, true, false, sizeof(FillDrawableUBO), "FillDrawableUBO"},
UniformBlockInfo{4, true, true, sizeof(FillEvaluatedPropsUBO), "FillEvaluatedPropsUBO"},
UniformBlockInfo{5, true, false, sizeof(FillInterpolateUBO), "FillInterpolateUBO"},
UniformBlockInfo{6, true, true, sizeof(FillPermutationUBO), "FillPermutationUBO"},
UniformBlockInfo{7, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 0> ShaderSource<BuiltIn::FillShader, gfx::Backend::Type::Metal>::textures = {};
const std::array<AttributeInfo, 4> ShaderSource<BuiltIn::FillOutlineShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
AttributeInfo{1, gfx::AttributeDataType::Float2, 1, "a_outline_color"},
AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_opacity"},
// See `a_outline_color` in FillShader
AttributeInfo{8, gfx::AttributeDataType::Float2, 1, "a_color"},
};
const std::array<UniformBlockInfo, 5> ShaderSource<BuiltIn::FillOutlineShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{3, true, false, sizeof(FillOutlineDrawableUBO), "FillOutlineDrawableUBO"},
UniformBlockInfo{4, true, true, sizeof(FillOutlineEvaluatedPropsUBO), "FillOutlineEvaluatedPropsUBO"},
UniformBlockInfo{5, true, false, sizeof(FillOutlineInterpolateUBO), "FillOutlineInterpolateUBO"},
UniformBlockInfo{6, true, true, sizeof(FillOutlinePermutationUBO), "FillOutlinePermutationUBO"},
UniformBlockInfo{7, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 0> ShaderSource<BuiltIn::FillOutlineShader, gfx::Backend::Type::Metal>::textures = {};
const std::array<AttributeInfo, 4> ShaderSource<BuiltIn::FillPatternShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"},
AttributeInfo{2, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"},
AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_opacity"},
};
const std::array<UniformBlockInfo, 6> ShaderSource<BuiltIn::FillPatternShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{4, true, true, sizeof(FillPatternDrawableUBO), "FillPatternDrawableUBO"},
UniformBlockInfo{5, true, false, sizeof(FillPatternTilePropsUBO), "FillPatternTilePropsUBO"},
UniformBlockInfo{6, true, true, sizeof(FillPatternEvaluatedPropsUBO), "FillPatternEvaluatedPropsUBO"},
UniformBlockInfo{7, true, false, sizeof(FillPatternInterpolateUBO), "FillPatternInterpolateUBO"},
UniformBlockInfo{8, true, true, sizeof(FillPatternPermutationUBO), "FillPatternPermutationUBO"},
UniformBlockInfo{9, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 1> ShaderSource<BuiltIn::FillPatternShader, gfx::Backend::Type::Metal>::textures = {
TextureInfo{0, "u_image"},
};
const std::array<AttributeInfo, 4>
ShaderSource<BuiltIn::FillOutlinePatternShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"},
AttributeInfo{2, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"},
AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_opacity"},
};
const std::array<UniformBlockInfo, 6> ShaderSource<BuiltIn::FillOutlinePatternShader,
gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{4, true, true, sizeof(FillOutlinePatternDrawableUBO), "FillOutlinePatternDrawableUBO"},
UniformBlockInfo{5, true, false, sizeof(FillOutlinePatternTilePropsUBO), "FillOutlinePatternTilePropsUBO"},
UniformBlockInfo{6, true, true, sizeof(FillOutlinePatternEvaluatedPropsUBO), "FillOutlinePatternEvaluatedPropsUBO"},
UniformBlockInfo{7, true, false, sizeof(FillOutlinePatternInterpolateUBO), "FillOutlinePatternInterpolateUBO"},
UniformBlockInfo{8, true, true, sizeof(FillOutlinePatternPermutationUBO), "FillOutlinePatternPermutationUBO"},
UniformBlockInfo{9, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 1> ShaderSource<BuiltIn::FillOutlinePatternShader, gfx::Backend::Type::Metal>::textures =
{
TextureInfo{0, "u_image"},
};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,24 @@
#include <mbgl/shaders/mtl/fill_extrusion.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 5> ShaderSource<BuiltIn::FillExtrusionShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
AttributeInfo{1, gfx::AttributeDataType::Short4, 1, "a_normal_ed"},
AttributeInfo{2, gfx::AttributeDataType::Float4, 1, "a_color"},
AttributeInfo{3, gfx::AttributeDataType::Float, 1, "a_base"},
AttributeInfo{4, gfx::AttributeDataType::Float, 1, "a_height"},
};
const std::array<UniformBlockInfo, 5> ShaderSource<BuiltIn::FillExtrusionShader, gfx::Backend::Type::Metal>::uniforms =
{
UniformBlockInfo{5, true, false, sizeof(FillExtrusionDrawableUBO), "FillExtrusionDrawableUBO"},
UniformBlockInfo{6, true, false, sizeof(FillExtrusionDrawablePropsUBO), "FillExtrusionDrawablePropsUBO"},
UniformBlockInfo{7, true, false, sizeof(FillExtrusionInterpolateUBO), "FillExtrusionInterpolateUBO"},
UniformBlockInfo{8, true, false, sizeof(FillExtrusionPermutationUBO), "FillExtrusionPermutationUBO"},
UniformBlockInfo{9, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 0> ShaderSource<BuiltIn::FillExtrusionShader, gfx::Backend::Type::Metal>::textures = {};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,14 @@
#include <mbgl/shaders/mtl/fill_extrusion_pattern.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 0>
ShaderSource<BuiltIn::FillExtrusionPatternShader, gfx::Backend::Type::Metal>::attributes = {};
const std::array<UniformBlockInfo, 0>
ShaderSource<BuiltIn::FillExtrusionPatternShader, gfx::Backend::Type::Metal>::uniforms = {};
const std::array<TextureInfo, 0>
ShaderSource<BuiltIn::FillExtrusionPatternShader, gfx::Backend::Type::Metal>::textures = {};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,21 @@
#include <mbgl/shaders/mtl/heatmap.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 3> ShaderSource<BuiltIn::HeatmapShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
AttributeInfo{1, gfx::AttributeDataType::Float2, 1, "a_weight"},
AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_radius"},
};
const std::array<UniformBlockInfo, 5> ShaderSource<BuiltIn::HeatmapShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{3, true, false, sizeof(HeatmapDrawableUBO), "HeatmapDrawableUBO"},
UniformBlockInfo{4, true, true, sizeof(HeatmapEvaluatedPropsUBO), "HeatmapEvaluatedPropsUBO"},
UniformBlockInfo{5, true, false, sizeof(HeatmapInterpolateUBO), "HeatmapInterpolateUBO"},
UniformBlockInfo{6, true, true, sizeof(HeatmapPermutationUBO), "HeatmapPermutationUBO"},
UniformBlockInfo{7, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 0> ShaderSource<BuiltIn::HeatmapShader, gfx::Backend::Type::Metal>::textures = {};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,20 @@
#include <mbgl/shaders/mtl/heatmap_texture.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 1> ShaderSource<BuiltIn::HeatmapTextureShader, gfx::Backend::Type::Metal>::attributes =
{
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
};
const std::array<UniformBlockInfo, 1> ShaderSource<BuiltIn::HeatmapTextureShader, gfx::Backend::Type::Metal>::uniforms =
{
UniformBlockInfo{1, true, true, sizeof(HeatmapTextureDrawableUBO), "HeatmapTextureDrawableUBO"},
};
const std::array<TextureInfo, 2> ShaderSource<BuiltIn::HeatmapTextureShader, gfx::Backend::Type::Metal>::textures = {
TextureInfo{0, "u_image"},
TextureInfo{1, "u_color_ramp"},
};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,19 @@
#include <mbgl/shaders/mtl/hillshade.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 2> ShaderSource<BuiltIn::HillshadeShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"},
};
const std::array<UniformBlockInfo, 2> ShaderSource<BuiltIn::HillshadeShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{2, true, true, sizeof(HillshadeDrawableUBO), "HillshadeDrawableUBO"},
UniformBlockInfo{3, false, true, sizeof(HillshadeEvaluatedPropsUBO), "HillshadeEvaluatedPropsUBO"},
};
const std::array<TextureInfo, 1> ShaderSource<BuiltIn::HillshadeShader, gfx::Backend::Type::Metal>::textures = {
TextureInfo{0, "u_image"},
};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,20 @@
#include <mbgl/shaders/mtl/hillshade_prepare.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 2>
ShaderSource<BuiltIn::HillshadePrepareShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"},
};
const std::array<UniformBlockInfo, 1>
ShaderSource<BuiltIn::HillshadePrepareShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{2, true, true, sizeof(HillshadePrepareDrawableUBO), "HillshadePrepareDrawableUBO"},
};
const std::array<TextureInfo, 1> ShaderSource<BuiltIn::HillshadePrepareShader, gfx::Backend::Type::Metal>::textures = {
TextureInfo{0, "u_image"},
};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,49 @@
#include <mbgl/shaders/mtl/line.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 8> ShaderSource<BuiltIn::LineShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"},
AttributeInfo{1, gfx::AttributeDataType::UByte4, 1, "a_data"},
AttributeInfo{2, gfx::AttributeDataType::Float4, 1, "a_color"},
AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_blur"},
AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_opacity"},
AttributeInfo{5, gfx::AttributeDataType::Float2, 1, "a_gapwidth"},
AttributeInfo{6, gfx::AttributeDataType::Float2, 1, "a_offset"},
AttributeInfo{7, gfx::AttributeDataType::Float2, 1, "a_width"},
};
const std::array<UniformBlockInfo, 5> ShaderSource<BuiltIn::LineShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{8, true, true, sizeof(LineUBO), "LineUBO"},
UniformBlockInfo{9, true, false, sizeof(LinePropertiesUBO), "LinePropertiesUBO"},
UniformBlockInfo{10, true, false, sizeof(LineInterpolationUBO), "LineInterpolationUBO"},
UniformBlockInfo{11, true, true, sizeof(LinePermutationUBO), "LinePermutationUBO"},
UniformBlockInfo{12, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 0> ShaderSource<BuiltIn::LineShader, gfx::Backend::Type::Metal>::textures = {};
const std::array<AttributeInfo, 9> ShaderSource<BuiltIn::LinePatternShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"},
AttributeInfo{1, gfx::AttributeDataType::UByte4, 1, "a_data"},
AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_blur"},
AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_opacity"},
AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_gapwidth"},
AttributeInfo{5, gfx::AttributeDataType::Float2, 1, "a_offset"},
AttributeInfo{6, gfx::AttributeDataType::Float2, 1, "a_width"},
AttributeInfo{7, gfx::AttributeDataType::UShort4, 1, "a_pattern_from"},
AttributeInfo{8, gfx::AttributeDataType::UShort4, 1, "a_pattern_to"},
};
const std::array<UniformBlockInfo, 6> ShaderSource<BuiltIn::LinePatternShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{9, true, true, sizeof(LinePatternUBO), "LinePatternUBO"},
UniformBlockInfo{10, true, false, sizeof(LinePatternPropertiesUBO), "LinePatternPropertiesUBO"},
UniformBlockInfo{11, true, false, sizeof(LinePatternInterpolationUBO), "LinePatternInterpolationUBO"},
UniformBlockInfo{12, true, false, sizeof(LinePatternTilePropertiesUBO), "LinePatternTilePropertiesUBO"},
UniformBlockInfo{13, true, true, sizeof(LinePermutationUBO), "LinePermutationUBO"},
UniformBlockInfo{14, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 1> ShaderSource<BuiltIn::LinePatternShader, gfx::Backend::Type::Metal>::textures = {
TextureInfo{0, "u_image"},
};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,27 @@
#include <mbgl/shaders/mtl/line_gradient.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 7> ShaderSource<BuiltIn::LineGradientShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos_normal"},
AttributeInfo{1, gfx::AttributeDataType::UByte4, 1, "a_data"},
AttributeInfo{2, gfx::AttributeDataType::Float2, 1, "a_blur"},
AttributeInfo{3, gfx::AttributeDataType::Float2, 1, "a_opacity"},
AttributeInfo{4, gfx::AttributeDataType::Float2, 1, "a_gapwidth"},
AttributeInfo{5, gfx::AttributeDataType::Float2, 1, "a_offset"},
AttributeInfo{6, gfx::AttributeDataType::Float2, 1, "a_width"},
};
const std::array<UniformBlockInfo, 5> ShaderSource<BuiltIn::LineGradientShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{7, true, true, sizeof(LineGradientUBO), "LineGradientUBO"},
UniformBlockInfo{8, true, false, sizeof(LineGradientPropertiesUBO), "LineGradientPropertiesUBO"},
UniformBlockInfo{9, true, false, sizeof(LineGradientInterpolationUBO), "LineGradientInterpolationUBO"},
UniformBlockInfo{10, true, true, sizeof(LinePermutationUBO), "LinePermutationUBO"},
UniformBlockInfo{11, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 1> ShaderSource<BuiltIn::LineGradientShader, gfx::Backend::Type::Metal>::textures = {
TextureInfo{0, "u_image"},
};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,19 @@
#include <mbgl/shaders/mtl/raster.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 2> ShaderSource<BuiltIn::RasterShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
AttributeInfo{1, gfx::AttributeDataType::Short2, 1, "a_texture_pos"},
};
const std::array<UniformBlockInfo, 1> ShaderSource<BuiltIn::RasterShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{2, true, true, sizeof(RasterDrawableUBO), "RasterDrawableUBO"},
};
const std::array<TextureInfo, 2> ShaderSource<BuiltIn::RasterShader, gfx::Backend::Type::Metal>::textures = {
TextureInfo{0, "u_image0"},
TextureInfo{1, "u_image1"},
};
} // namespace shaders
} // namespace mbgl

View File

@@ -22,8 +22,32 @@
using namespace std::string_literals;
namespace mbgl {
namespace mtl {
shaders::AttributeInfo::AttributeInfo(std::size_t index_,
gfx::AttributeDataType dataType_,
std::size_t count_,
std::string_view name_)
: index(index_),
dataType(dataType_),
count(count_),
name(name_),
nameID(stringIndexer().get(name_)) {}
shaders::UniformBlockInfo::UniformBlockInfo(
std::size_t index_, bool vertex_, bool fragment_, std::size_t size_, std::string_view name_)
: index(index_),
vertex(vertex_),
fragment(fragment_),
size(size_),
name(name_),
nameID(stringIndexer().get(name_)) {}
shaders::TextureInfo::TextureInfo(std::size_t index_, std::string_view name_)
: index(index_),
name(name_),
nameID(stringIndexer().get(name_)) {}
namespace mtl {
namespace {
MTL::BlendOperation metalBlendOperation(const gfx::ColorBlendEquationType& colorBlend) {
switch (colorBlend) {

View File

@@ -0,0 +1,30 @@
#include <mbgl/shaders/mtl/symbol_icon.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 6> ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::Metal>::attributes = {
// always attributes
AttributeInfo{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"},
AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_data"},
AttributeInfo{2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"},
AttributeInfo{3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"},
AttributeInfo{4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"},
// sometimes uniforms
AttributeInfo{5, gfx::AttributeDataType::Float, 1, "a_opacity"},
};
const std::array<UniformBlockInfo, 6> ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{8, true, true, sizeof(SymbolDrawableUBO), "SymbolDrawableUBO"},
UniformBlockInfo{9, true, true, sizeof(SymbolDrawablePaintUBO), "SymbolDrawablePaintUBO"},
UniformBlockInfo{10, true, false, sizeof(SymbolDrawableTilePropsUBO), "SymbolDrawableTilePropsUBO"},
UniformBlockInfo{11, true, false, sizeof(SymbolDrawableInterpolateUBO), "SymbolDrawableInterpolateUBO"},
UniformBlockInfo{12, true, true, sizeof(SymbolPermutationUBO), "SymbolPermutationUBO"},
UniformBlockInfo{13, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 1> ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::Metal>::textures = {
TextureInfo{0, "u_texture"},
};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,36 @@
#include <mbgl/shaders/mtl/symbol_sdf.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 10> ShaderSource<BuiltIn::SymbolSDFIconShader, gfx::Backend::Type::Metal>::attributes =
{
// always attributes
AttributeInfo{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"},
AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_data"},
AttributeInfo{2, gfx::AttributeDataType::Short4, 1, "a_pixeloffset"},
AttributeInfo{3, gfx::AttributeDataType::Float3, 1, "a_projected_pos"},
AttributeInfo{4, gfx::AttributeDataType::Float, 1, "a_fade_opacity"},
// sometimes uniforms
AttributeInfo{5, gfx::AttributeDataType::Float4, 1, "a_fill_color"},
AttributeInfo{6, gfx::AttributeDataType::Float4, 1, "a_halo_color"},
AttributeInfo{7, gfx::AttributeDataType::Float, 1, "a_opacity"},
AttributeInfo{8, gfx::AttributeDataType::Float, 1, "a_halo_width"},
AttributeInfo{9, gfx::AttributeDataType::Float, 1, "a_halo_blur"},
};
const std::array<UniformBlockInfo, 6> ShaderSource<BuiltIn::SymbolSDFIconShader, gfx::Backend::Type::Metal>::uniforms =
{
UniformBlockInfo{10, true, true, sizeof(SymbolDrawableUBO), "SymbolDrawableUBO"},
UniformBlockInfo{11, true, false, sizeof(SymbolDrawablePaintUBO), "SymbolDrawablePaintUBO"},
UniformBlockInfo{12, true, true, sizeof(SymbolDrawableTilePropsUBO), "SymbolDrawableTilePropsUBO"},
UniformBlockInfo{13, true, false, sizeof(SymbolDrawableInterpolateUBO), "SymbolDrawableInterpolateUBO"},
UniformBlockInfo{14, true, true, sizeof(SymbolPermutationUBO), "SymbolPermutationUBO"},
UniformBlockInfo{15, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 1> ShaderSource<BuiltIn::SymbolSDFIconShader, gfx::Backend::Type::Metal>::textures = {
TextureInfo{0, "u_texture"},
};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,36 @@
#include <mbgl/shaders/mtl/symbol_text_and_icon.hpp>
namespace mbgl {
namespace shaders {
const std::array<AttributeInfo, 9>
ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Metal>::attributes = {
// always attributes
AttributeInfo{0, gfx::AttributeDataType::Short4, 1, "a_pos_offset"},
AttributeInfo{1, gfx::AttributeDataType::UShort4, 1, "a_data"},
AttributeInfo{2, gfx::AttributeDataType::Float3, 1, "a_projected_pos"},
AttributeInfo{3, gfx::AttributeDataType::Float, 1, "a_fade_opacity"},
// sometimes uniforms
AttributeInfo{4, gfx::AttributeDataType::Float4, 1, "a_fill_color"},
AttributeInfo{5, gfx::AttributeDataType::Float4, 1, "a_halo_color"},
AttributeInfo{6, gfx::AttributeDataType::Float, 1, "a_opacity"},
AttributeInfo{7, gfx::AttributeDataType::Float, 1, "a_halo_width"},
AttributeInfo{8, gfx::AttributeDataType::Float, 1, "a_halo_blur"},
};
const std::array<UniformBlockInfo, 6>
ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{9, true, true, sizeof(SymbolDrawableUBO), "SymbolDrawableUBO"},
UniformBlockInfo{10, true, false, sizeof(SymbolDrawablePaintUBO), "SymbolDrawablePaintUBO"},
UniformBlockInfo{11, true, true, sizeof(SymbolDrawableTilePropsUBO), "SymbolDrawableTilePropsUBO"},
UniformBlockInfo{12, true, false, sizeof(SymbolDrawableInterpolateUBO), "SymbolDrawableInterpolateUBO"},
UniformBlockInfo{13, true, true, sizeof(SymbolPermutationUBO), "SymbolPermutationUBO"},
UniformBlockInfo{14, true, false, sizeof(ExpressionInputsUBO), "ExpressionInputsUBO"},
};
const std::array<TextureInfo, 2> ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Metal>::textures = {
TextureInfo{0, "u_texture"},
TextureInfo{1, "u_texture_icon"},
};
} // namespace shaders
} // namespace mbgl

View File

@@ -3,6 +3,7 @@
#include <mbgl/util/ignore.hpp>
#include <functional>
#include <type_traits>
namespace mbgl {
namespace util {
@@ -19,5 +20,24 @@ std::size_t hash(Args&&... args) {
return seed;
}
namespace detail {
template <typename TIter>
using TIterVal = std::enable_if_t<std::is_integral<typename TIter::value_type>::value, typename TIter::value_type>;
} // namespace detail
/// Generate a hash key from a collection of integer values which doesn't depend on their order.
/// Adapted from https://stackoverflow.com/a/76993810/135138
/// Default factor prime value from 64-bit FNV hash.
template <typename TIter, typename TKey = detail::TIterVal<TIter>, TKey factor = 1099511628211LL>
TKey order_independent_hash(TIter cur, const TIter end) {
detail::TIterVal<TIter> sum = 0, product = 1;
for (; cur != end; ++cur) {
const auto& value = *cur;
sum += value;
product *= (1 + value) * factor;
}
return sum ^ product;
}
} // namespace util
} // namespace mbgl

View File

@@ -88,6 +88,7 @@ add_library(
${PROJECT_SOURCE_DIR}/test/util/dtoa.test.cpp
${PROJECT_SOURCE_DIR}/test/util/geo.test.cpp
${PROJECT_SOURCE_DIR}/test/util/grid_index.test.cpp
${PROJECT_SOURCE_DIR}/test/util/hash.test.cpp
${PROJECT_SOURCE_DIR}/test/util/http_timeout.test.cpp
${PROJECT_SOURCE_DIR}/test/util/image.test.cpp
${PROJECT_SOURCE_DIR}/test/util/mapbox.test.cpp
@@ -128,6 +129,7 @@ if(MLN_WITH_OPENGL)
PRIVATE
${PROJECT_SOURCE_DIR}/test/api/custom_layer.test.cpp
${PROJECT_SOURCE_DIR}/test/gl/bucket.test.cpp
${PROJECT_SOURCE_DIR}/test/gl/enum.test.cpp
${PROJECT_SOURCE_DIR}/test/gl/context.test.cpp
${PROJECT_SOURCE_DIR}/test/gl/gl_functions.test.cpp
${PROJECT_SOURCE_DIR}/test/gl/object.test.cpp
@@ -236,4 +238,4 @@ if (CMAKE_SYSTEM_NAME STREQUAL Linux)
mbgl-test
PRIVATE USE_CPP_TEST_SERVER
)
endif()
endif()

View File

@@ -9,6 +9,7 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/map_options.hpp>
#include <mbgl/platform/gl_functions.hpp>
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
@@ -114,6 +115,9 @@ TEST(GLContextMode, Shared) {
MBGL_CHECK_ERROR(glEnableVertexAttribArray(paintShader.a_pos));
MBGL_CHECK_ERROR(glVertexAttribPointer(paintShader.a_pos, 2, GL_FLOAT, GL_FALSE, 0, nullptr));
MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 3));
frontend.getRenderer()->reduceMemoryUse();
ASSERT_TRUE(static_cast<gl::Context&>(frontend.getBackend()->getContext()).empty());
}
test::checkImage("test/fixtures/shared_context", frontend.render(map).image, 0.5, 0.1);

178
test/gl/enum.test.cpp Normal file
View File

@@ -0,0 +1,178 @@
#include <mbgl/gfx/gfx_types.hpp>
#include <mbgl/gfx/types.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/gl/enum.hpp>
#include <mbgl/test/util.hpp>
using namespace mbgl;
using namespace mbgl::gfx;
using namespace mbgl::gl;
TEST(GL, DrawModeType) {
ASSERT_EQ(GL_POINTS, Enum<DrawModeType>::to(DrawModeType::Points));
ASSERT_EQ(GL_LINES, Enum<DrawModeType>::to(DrawModeType::Lines));
ASSERT_EQ(GL_LINE_LOOP, Enum<DrawModeType>::to(DrawModeType::LineLoop));
ASSERT_EQ(GL_LINE_STRIP, Enum<DrawModeType>::to(DrawModeType::LineStrip));
ASSERT_EQ(GL_TRIANGLES, Enum<DrawModeType>::to(DrawModeType::Triangles));
ASSERT_EQ(GL_TRIANGLE_STRIP, Enum<DrawModeType>::to(DrawModeType::TriangleStrip));
ASSERT_EQ(GL_TRIANGLE_FAN, Enum<DrawModeType>::to(DrawModeType::TriangleFan));
ASSERT_EQ(GL_INVALID_ENUM, Enum<DrawModeType>::to(static_cast<DrawModeType>(-1)));
}
namespace {
template <typename T>
auto enumIdentity(T x) {
return Enum<T>::from(Enum<T>::to(x));
}
} // namespace
TEST(GL, ColorBlendEquationType) {
// const auto identity = [](auto x){ return Enum<ColorBlendEquationType>::from(Enum<ColorBlendEquationType>::to(x));
// };
ASSERT_EQ(ColorBlendEquationType::Add, enumIdentity(ColorBlendEquationType::Add));
ASSERT_EQ(ColorBlendEquationType::Subtract, enumIdentity(ColorBlendEquationType::Subtract));
ASSERT_EQ(ColorBlendEquationType::ReverseSubtract, enumIdentity(ColorBlendEquationType::ReverseSubtract));
ASSERT_EQ(GL_INVALID_ENUM, Enum<ColorBlendEquationType>::to(static_cast<ColorBlendEquationType>(-1)));
ASSERT_EQ(ColorBlendEquationType{}, Enum<ColorBlendEquationType>::from(GL_RGBA8));
}
TEST(GL, ColorBlendFactorType) {
ASSERT_EQ(ColorBlendFactorType::Zero, enumIdentity(ColorBlendFactorType::Zero));
ASSERT_EQ(ColorBlendFactorType::One, enumIdentity(ColorBlendFactorType::One));
ASSERT_EQ(ColorBlendFactorType::SrcColor, enumIdentity(ColorBlendFactorType::SrcColor));
ASSERT_EQ(ColorBlendFactorType::OneMinusSrcColor, enumIdentity(ColorBlendFactorType::OneMinusSrcColor));
ASSERT_EQ(ColorBlendFactorType::DstColor, enumIdentity(ColorBlendFactorType::DstColor));
ASSERT_EQ(ColorBlendFactorType::OneMinusDstColor, enumIdentity(ColorBlendFactorType::OneMinusDstColor));
ASSERT_EQ(ColorBlendFactorType::SrcAlpha, enumIdentity(ColorBlendFactorType::SrcAlpha));
ASSERT_EQ(ColorBlendFactorType::OneMinusSrcAlpha, enumIdentity(ColorBlendFactorType::OneMinusSrcAlpha));
ASSERT_EQ(ColorBlendFactorType::DstAlpha, enumIdentity(ColorBlendFactorType::DstAlpha));
ASSERT_EQ(ColorBlendFactorType::OneMinusDstAlpha, enumIdentity(ColorBlendFactorType::OneMinusDstAlpha));
ASSERT_EQ(ColorBlendFactorType::ConstantColor, enumIdentity(ColorBlendFactorType::ConstantColor));
ASSERT_EQ(ColorBlendFactorType::OneMinusConstantColor, enumIdentity(ColorBlendFactorType::OneMinusConstantColor));
ASSERT_EQ(ColorBlendFactorType::ConstantAlpha, enumIdentity(ColorBlendFactorType::ConstantAlpha));
ASSERT_EQ(ColorBlendFactorType::OneMinusConstantAlpha, enumIdentity(ColorBlendFactorType::OneMinusConstantAlpha));
ASSERT_EQ(ColorBlendFactorType::SrcAlphaSaturate, enumIdentity(ColorBlendFactorType::SrcAlphaSaturate));
ASSERT_EQ(GL_INVALID_ENUM, Enum<ColorBlendFactorType>::to(static_cast<ColorBlendFactorType>(-1)));
ASSERT_EQ(ColorBlendFactorType{}, Enum<ColorBlendFactorType>::from(GL_RGBA8));
}
TEST(GL, DepthFunctionType) {
ASSERT_EQ(DepthFunctionType::Never, enumIdentity(DepthFunctionType::Never));
ASSERT_EQ(DepthFunctionType::Less, enumIdentity(DepthFunctionType::Less));
ASSERT_EQ(DepthFunctionType::Equal, enumIdentity(DepthFunctionType::Equal));
ASSERT_EQ(DepthFunctionType::LessEqual, enumIdentity(DepthFunctionType::LessEqual));
ASSERT_EQ(DepthFunctionType::Greater, enumIdentity(DepthFunctionType::Greater));
ASSERT_EQ(DepthFunctionType::NotEqual, enumIdentity(DepthFunctionType::NotEqual));
ASSERT_EQ(DepthFunctionType::GreaterEqual, enumIdentity(DepthFunctionType::GreaterEqual));
ASSERT_EQ(DepthFunctionType::Always, enumIdentity(DepthFunctionType::Always));
ASSERT_EQ(GL_INVALID_ENUM, Enum<DepthFunctionType>::to(static_cast<DepthFunctionType>(-1)));
ASSERT_EQ(DepthFunctionType{}, Enum<DepthFunctionType>::from(GL_RGBA8));
}
TEST(GL, DepthMaskType) {
ASSERT_EQ(DepthMaskType::ReadOnly, enumIdentity(DepthMaskType::ReadOnly));
ASSERT_EQ(DepthMaskType::ReadWrite, enumIdentity(DepthMaskType::ReadWrite));
// anything non-zero is true, there's no way to represent invalid
ASSERT_EQ(GL_TRUE, Enum<DepthMaskType>::to(static_cast<DepthMaskType>(-1)));
}
TEST(GL, StencilFunctionType) {
ASSERT_EQ(StencilFunctionType::Never, enumIdentity(StencilFunctionType::Never));
ASSERT_EQ(StencilFunctionType::Less, enumIdentity(StencilFunctionType::Less));
ASSERT_EQ(StencilFunctionType::Equal, enumIdentity(StencilFunctionType::Equal));
ASSERT_EQ(StencilFunctionType::LessEqual, enumIdentity(StencilFunctionType::LessEqual));
ASSERT_EQ(StencilFunctionType::Greater, enumIdentity(StencilFunctionType::Greater));
ASSERT_EQ(StencilFunctionType::NotEqual, enumIdentity(StencilFunctionType::NotEqual));
ASSERT_EQ(StencilFunctionType::GreaterEqual, enumIdentity(StencilFunctionType::GreaterEqual));
ASSERT_EQ(StencilFunctionType::Always, enumIdentity(StencilFunctionType::Always));
ASSERT_EQ(GL_INVALID_ENUM, Enum<StencilFunctionType>::to(static_cast<StencilFunctionType>(-1)));
ASSERT_EQ(StencilFunctionType{}, Enum<StencilFunctionType>::from(GL_RGBA8));
}
TEST(GL, StencilOpType) {
ASSERT_EQ(StencilOpType::Keep, enumIdentity(StencilOpType::Keep));
ASSERT_EQ(StencilOpType::Zero, enumIdentity(StencilOpType::Zero));
ASSERT_EQ(StencilOpType::Replace, enumIdentity(StencilOpType::Replace));
ASSERT_EQ(StencilOpType::Increment, enumIdentity(StencilOpType::Increment));
ASSERT_EQ(StencilOpType::IncrementWrap, enumIdentity(StencilOpType::IncrementWrap));
ASSERT_EQ(StencilOpType::Decrement, enumIdentity(StencilOpType::Decrement));
ASSERT_EQ(StencilOpType::DecrementWrap, enumIdentity(StencilOpType::DecrementWrap));
ASSERT_EQ(StencilOpType::Invert, enumIdentity(StencilOpType::Invert));
ASSERT_EQ(GL_INVALID_ENUM, Enum<StencilOpType>::to(static_cast<StencilOpType>(-1)));
ASSERT_EQ(StencilOpType{}, Enum<StencilOpType>::from(GL_RGBA8));
}
TEST(GL, CullFaceSideType) {
ASSERT_EQ(CullFaceSideType::Front, enumIdentity(CullFaceSideType::Front));
ASSERT_EQ(CullFaceSideType::Back, enumIdentity(CullFaceSideType::Back));
ASSERT_EQ(CullFaceSideType::FrontAndBack, enumIdentity(CullFaceSideType::FrontAndBack));
ASSERT_EQ(GL_INVALID_ENUM, Enum<CullFaceSideType>::to(static_cast<CullFaceSideType>(-1)));
ASSERT_EQ(CullFaceSideType{}, Enum<CullFaceSideType>::from(GL_RGBA8));
}
TEST(GL, CullFaceWindingType) {
ASSERT_EQ(CullFaceWindingType::Clockwise, enumIdentity(CullFaceWindingType::Clockwise));
ASSERT_EQ(CullFaceWindingType::CounterClockwise, enumIdentity(CullFaceWindingType::CounterClockwise));
ASSERT_EQ(GL_INVALID_ENUM, Enum<CullFaceWindingType>::to(static_cast<CullFaceWindingType>(-1)));
ASSERT_EQ(CullFaceWindingType{}, Enum<CullFaceWindingType>::from(GL_RGBA8));
}
TEST(GL, BufferUsageType) {
ASSERT_EQ(BufferUsageType::StreamDraw, enumIdentity(BufferUsageType::StreamDraw));
ASSERT_EQ(BufferUsageType::StaticDraw, enumIdentity(BufferUsageType::StaticDraw));
ASSERT_EQ(BufferUsageType::DynamicDraw, enumIdentity(BufferUsageType::DynamicDraw));
ASSERT_EQ(GL_INVALID_ENUM, Enum<BufferUsageType>::to(static_cast<BufferUsageType>(-1)));
ASSERT_EQ(BufferUsageType{}, Enum<BufferUsageType>::from(GL_RGBA8));
}
TEST(GL, TexturePixelType) {
ASSERT_EQ(TexturePixelType::RGBA, enumIdentity(TexturePixelType::RGBA));
ASSERT_EQ(TexturePixelType::Alpha, enumIdentity(TexturePixelType::Alpha));
ASSERT_EQ(TexturePixelType::Stencil, enumIdentity(TexturePixelType::Stencil));
ASSERT_EQ(TexturePixelType::Depth, enumIdentity(TexturePixelType::Depth));
ASSERT_EQ(TexturePixelType::Luminance, enumIdentity(TexturePixelType::Luminance));
ASSERT_EQ(GL_INVALID_ENUM, Enum<TexturePixelType>::to(static_cast<TexturePixelType>(-1)));
ASSERT_EQ(TexturePixelType{}, Enum<TexturePixelType>::from(GL_RGBA8));
}
TEST(GL, TextureChannelDataType) {
ASSERT_EQ(TextureChannelDataType::UnsignedByte, enumIdentity(TextureChannelDataType::UnsignedByte));
ASSERT_EQ(TextureChannelDataType::HalfFloat, enumIdentity(TextureChannelDataType::HalfFloat));
ASSERT_EQ(TextureChannelDataType::Float, enumIdentity(TextureChannelDataType::Float));
ASSERT_EQ(GL_INVALID_ENUM, Enum<TextureChannelDataType>::to(static_cast<TextureChannelDataType>(-1)));
ASSERT_EQ(TextureChannelDataType{}, Enum<TextureChannelDataType>::from(GL_RGBA8));
}
TEST(GL, RenderbufferPixelType) {
ASSERT_EQ(RenderbufferPixelType::RGBA, enumIdentity(RenderbufferPixelType::RGBA));
ASSERT_EQ(RenderbufferPixelType::Depth, enumIdentity(RenderbufferPixelType::Depth));
ASSERT_EQ(RenderbufferPixelType::DepthStencil, enumIdentity(RenderbufferPixelType::DepthStencil));
ASSERT_EQ(GL_INVALID_ENUM, Enum<RenderbufferPixelType>::to(static_cast<RenderbufferPixelType>(-1)));
ASSERT_EQ(RenderbufferPixelType{}, Enum<RenderbufferPixelType>::from(GL_RGBA8));
}
TEST(GL, sizedFor) {
ASSERT_EQ(GL_RGBA,
Enum<gfx::TexturePixelType>::sizedFor(TexturePixelType::RGBA, TextureChannelDataType::UnsignedByte));
ASSERT_EQ(GL_RGBA16F,
Enum<gfx::TexturePixelType>::sizedFor(TexturePixelType::RGBA, TextureChannelDataType::HalfFloat));
ASSERT_EQ(GL_INVALID_ENUM,
Enum<gfx::TexturePixelType>::sizedFor(TexturePixelType::Alpha, TextureChannelDataType::HalfFloat));
ASSERT_EQ(GL_RGBA32F, Enum<gfx::TexturePixelType>::sizedFor(TexturePixelType::RGBA, TextureChannelDataType::Float));
ASSERT_EQ(GL_INVALID_ENUM,
Enum<gfx::TexturePixelType>::sizedFor(TexturePixelType::Alpha, TextureChannelDataType::Float));
ASSERT_EQ(GL_INVALID_ENUM,
Enum<gfx::TexturePixelType>::sizedFor(TexturePixelType::RGBA, static_cast<TextureChannelDataType>(-1)));
}

View File

@@ -207,7 +207,11 @@ TEST(ShaderRegistry, NamedReplace) {
}
// Test replacing an actual program instance with a similar instance
#if MLN_LEGACY_RENDERER
TEST(ShaderRegistry, GLSLReplacement_NoOp) {
#else
TEST(ShaderRegistry, DISABLED_GLSLReplacement_NoOp) {
#endif
MapInstance::ShaderAndStyleObserver observer;
util::RunLoop runLoop;
auto map = MapInstance(1.0f, observer);
@@ -233,7 +237,11 @@ TEST(ShaderRegistry, DISABLED_GLSLReplacement_NoOp) {
// Test replacing an actual program with a similar instance using a different
// fragment shader
#if MLN_LEGACY_RENDERER
TEST(ShaderRegistry, GLSLReplacement1) {
#else
TEST(ShaderRegistry, DISABLED_GLSLReplacement1) {
#endif
MapInstance::ShaderAndStyleObserver observer;
util::RunLoop runLoop;
auto map = MapInstance(1.0f, observer);
@@ -267,7 +275,11 @@ void main() {
// Test replacing an actual program with a similar instance using a different
// fragment shader
#if MLN_LEGACY_RENDERER
TEST(ShaderRegistry, GLSLReplacement2) {
#else
TEST(ShaderRegistry, DISABLED_GLSLReplacement2) {
#endif
MapInstance::ShaderAndStyleObserver observer;
util::RunLoop runLoop;
auto map = MapInstance(1.0f, observer);

Some files were not shown because too many files have changed in this diff Show More