GPU Expressions (#2202)

This commit is contained in:
Tim Sylvester
2024-05-17 07:30:55 -07:00
committed by GitHub
parent b812e97aaf
commit 33a1e162bc
64 changed files with 2336 additions and 318 deletions

View File

@@ -154,12 +154,12 @@ jobs:
run: xvfb-run -a build/mbgl-render-test-runner --manifestPath=metrics/linux-${{ matrix.renderer }}.json
- name: Upload render test result
if: always() && steps.render_test.outcome == 'failure' && matrix.renderer == 'drawable'
if: always() && steps.render_test.outcome == 'failure'
uses: actions/upload-artifact@v4
with:
name: render-test-result
name: render-test-result-${{ matrix.renderer }}
path: |
metrics/linux-drawable.html
metrics/linux-${{ matrix.renderer }}.html
# expression tests

View File

@@ -149,6 +149,7 @@ if(MLN_DRAWABLE_RENDERER)
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_tweaker.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_atlases_tweaker.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_custom_layer_host_tweaker.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/gpu_expression.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/uniform_block.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/uniform_buffer.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/vertex_attribute.hpp
@@ -177,6 +178,7 @@ if(MLN_DRAWABLE_RENDERER)
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_builder_impl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_atlases_tweaker.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_custom_layer_host_tweaker.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/gpu_expression.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/hillshade_prepare_drawable_data.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/image_drawable_data.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/line_drawable_data.hpp

View File

@@ -922,6 +922,7 @@ MLN_DRAWABLES_SOURCE = [
"src/mbgl/gfx/drawable_builder_impl.cpp",
"src/mbgl/gfx/drawable_atlases_tweaker.cpp",
"src/mbgl/gfx/drawable_custom_layer_host_tweaker.cpp",
"src/mbgl/gfx/gpu_expression.cpp",
"src/mbgl/gfx/hillshade_prepare_drawable_data.hpp",
"src/mbgl/gfx/image_drawable_data.hpp",
"src/mbgl/gfx/line_drawable_data.hpp",
@@ -976,6 +977,7 @@ MLN_DRAWABLES_HEADERS = [
"include/mbgl/gfx/drawable_tweaker.hpp",
"include/mbgl/gfx/drawable_atlases_tweaker.hpp",
"include/mbgl/gfx/drawable_custom_layer_host_tweaker.hpp",
"include/mbgl/gfx/gpu_expression.hpp",
"include/mbgl/gfx/uniform_block.hpp",
"include/mbgl/gfx/uniform_buffer.hpp",
"include/mbgl/gfx/vertex_attribute.hpp",

View File

@@ -31,6 +31,9 @@ public:
static Type GetType() { return Value(DefaultType); }
static bool getEnableGPUExpressionEval() { return enableGPUExpressionEval; }
static void setEnableGPUExpressionEval(bool value) { enableGPUExpressionEval = value; }
template <typename T, typename... Args>
static std::unique_ptr<T> Create(Args... args) {
#if MLN_RENDER_BACKEND_METAL
@@ -48,6 +51,8 @@ private:
static const Type type = value;
return type;
}
static bool enableGPUExpressionEval;
};
} // namespace gfx

View File

@@ -0,0 +1,108 @@
#pragma once
#include <mbgl/util/color.hpp>
#include <mbgl/util/variant.hpp>
#include <optional>
#if MLN_DRAWABLE_RENDERER
namespace mbgl {
namespace style {
namespace expression {
class Expression;
class Interpolate;
class Step;
} // namespace expression
using ZoomCurvePtr = variant<std::nullptr_t, const expression::Interpolate*, const expression::Step*>;
} // namespace style
namespace gfx {
enum class GPUInterpType : std::uint16_t {
Step,
Linear,
Exponential,
Bezier
};
enum class GPUOutputType : std::uint16_t {
Float,
Color,
};
enum class GPUOptions : std::uint16_t {
None = 0,
IntegerZoom = 1 << 0,
Transitioning = 1 << 1,
};
class GPUExpression;
using UniqueGPUExpression = std::unique_ptr<GPUExpression>;
class alignas(16) GPUExpression {
public:
static constexpr std::size_t maxStops = 16;
GPUExpression() = delete;
GPUExpression(GPUOutputType type, uint16_t count)
: outputType(type),
stopCount(count) {}
GPUExpression(GPUExpression&&) = default;
GPUExpression(const GPUExpression&) = default;
GPUExpression(const GPUExpression* ptr)
: GPUExpression(ptr ? *ptr : empty) {}
GPUExpression& operator=(GPUExpression&&) = delete;
GPUExpression& operator=(const GPUExpression&) = delete;
/* 0 */ const GPUOutputType outputType;
/* 2 */ const std::uint16_t stopCount;
/* 4 */ GPUOptions options;
/* 6 */ GPUInterpType interpolation;
/* 8 */ union InterpOptions {
struct Exponential {
float base;
} exponential;
struct Bezier {
float x1;
float y1;
float x2;
float y2;
} bezier;
} interpOptions;
/* 24 */ float inputs[maxStops];
/* 24 + (4 * maxStops) = 88 */ union Stops {
float floats[maxStops];
float colors[2 * maxStops];
} stops;
static UniqueGPUExpression create(GPUOutputType, std::uint16_t stopCount);
static UniqueGPUExpression create(const style::expression::Expression&, const style::ZoomCurvePtr&, bool intZoom);
float evaluateFloat(const float zoom) const;
Color evaluateColor(const float zoom) const;
template <typename T>
auto evaluate(const float zoom) const;
Color getColor(std::size_t index) const;
static const GPUExpression empty;
};
static_assert(sizeof(GPUExpression) == 32 + (4 + 8) * GPUExpression::maxStops);
static_assert(sizeof(GPUExpression) % 16 == 0);
template <>
inline auto GPUExpression::evaluate<Color>(const float zoom) const {
return evaluateColor(zoom);
}
template <>
inline auto GPUExpression::evaluate<float>(const float zoom) const {
return evaluateFloat(zoom);
}
} // namespace gfx
} // namespace mbgl
#endif

View File

@@ -44,7 +44,8 @@ struct alignas(16) GlobalPaintParamsUBO {
float symbol_fade_change;
float aspect_ratio;
float pixel_ratio;
float pad1, pad2;
float zoom;
float pad1;
};
static_assert(sizeof(GlobalPaintParamsUBO) == 3 * 16);

View File

@@ -1,10 +1,27 @@
#pragma once
#include <mbgl/shaders/layer_ubo.hpp>
#include <mbgl/style/property_expression.hpp>
#include <mbgl/util/bitmask_operations.hpp>
#if MLN_DRAWABLE_RENDERER
#include <mbgl/gfx/gpu_expression.hpp>
#endif // MLN_DRAWABLE_RENDERER
namespace mbgl {
namespace shaders {
enum class LineExpressionMask : uint32_t {
None = 0,
Color = 1 << 0,
Opacity = 1 << 1,
Blur = 1 << 2,
Width = 1 << 3,
GapWidth = 1 << 4,
FloorWidth = 1 << 5,
Offset = 1 << 6,
};
//
// Line
@@ -26,6 +43,17 @@ struct alignas(16) LineInterpolationUBO {
};
static_assert(sizeof(LineInterpolationUBO) % 16 == 0);
struct alignas(16) LineExpressionUBO {
gfx::GPUExpression color;
gfx::GPUExpression blur;
gfx::GPUExpression opacity;
gfx::GPUExpression gapwidth;
gfx::GPUExpression offset;
gfx::GPUExpression width;
gfx::GPUExpression floorWidth;
};
static_assert(sizeof(LineExpressionUBO) % 16 == 0);
//
// Line gradient
@@ -110,7 +138,8 @@ struct alignas(16) LineEvaluatedPropsUBO {
float offset;
float width;
float floorwidth;
float pad1, pad2;
LineExpressionMask expressionMask;
float pad1;
};
static_assert(sizeof(LineEvaluatedPropsUBO) % 16 == 0);
@@ -119,6 +148,7 @@ enum {
idLineInterpolationUBO,
idLineTilePropertiesUBO,
idLineEvaluatedPropsUBO,
idLineExpressionUBO,
lineUBOCount
};

View File

@@ -54,6 +54,191 @@ float4 unpack_mix_color(const float4 packedColors, const float t) {
decode_color(float2(packedColors[2], packedColors[3])), t);
}
template<class ForwardIt, class T>
ForwardIt upper_bound(ForwardIt first, ForwardIt last, thread const T& value)
{
size_t count = last - first;
while (count > 0)
{
ForwardIt it = first;
const size_t step = count / 2;
it += step;
if (!(value < *it))
{
first = ++it;
count -= step + 1;
}
else {
count = step;
}
}
return first;
}
float interpolationFactor(float base, float rangeMin, float rangeMax, float z) {
const float zoomDiff = rangeMax - rangeMin;
const float zoomProgress = z - rangeMin;
if (zoomDiff == 0) {
return 0;
} else if (base == 1.0f) {
return zoomProgress / zoomDiff;
} else {
return (pow(base, zoomProgress) - 1) / (pow(base, zoomDiff) - 1);
}
}
enum class GPUInterpType : uint16_t {
Step,
Linear,
Exponential,
Bezier
};
enum class GPUOutputType : uint16_t {
Float,
Color,
};
enum class GPUOptions : uint16_t {
None = 0,
IntegerZoom = 1 << 0,
Transitioning = 1 << 1,
};
bool operator&(GPUOptions a, GPUOptions b) { return (uint16_t)a & (uint16_t)b; }
constant const int maxExprStops = 16;
struct alignas(16) GPUExpression {
GPUOutputType outputType;
uint16_t stopCount;
GPUOptions options;
GPUInterpType interpolation;
union InterpOptions {
struct Exponential {
float base;
} exponential;
struct Bezier {
float x1;
float y1;
float x2;
float y2;
} bezier;
} interpOptions;
float inputs[maxExprStops];
union Stops {
float floats[maxExprStops];
float2 colors[maxExprStops];
} stops;
float eval(float zoom) device const {
const auto effectiveZoom = (options & GPUOptions::IntegerZoom) ? floor(zoom) : zoom;
const auto index = find(effectiveZoom);
if (index == 0) {
return stops.floats[0];
} else if (index == stopCount) {
return stops.floats[stopCount - 1];
}
switch (interpolation) {
case GPUInterpType::Step: return stops.floats[index - 1];
default: assert(false);
[[fallthrough]];
case GPUInterpType::Linear: assert(interpOptions.exponential.base == 1.0f);
[[fallthrough]];
case GPUInterpType::Exponential: {
const float rangeBeg = inputs[index - 1];
const float rangeEnd = inputs[index];
const auto t = interpolationFactor(interpOptions.exponential.base, rangeBeg, rangeEnd, effectiveZoom);
return mix(stops.floats[index - 1], stops.floats[index], t);
}
case GPUInterpType::Bezier:
assert(false);
return stops.floats[0];
}
}
float4 evalColor(float zoom) device const {
const auto effectiveZoom = (options & GPUOptions::IntegerZoom) ? floor(zoom) : zoom;
const auto index = find(effectiveZoom);
if (index == 0) {
return getColor(0);
} else if (index == stopCount) {
return getColor(stopCount - 1);
}
switch (interpolation) {
case GPUInterpType::Step:
return getColor(index - 1);
default:
assert(false);
[[fallthrough]];
case GPUInterpType::Linear:
assert(interpOptions.exponential.base == 1.0f);
[[fallthrough]];
case GPUInterpType::Exponential: {
const float rangeBeg = inputs[index - 1];
const float rangeEnd = inputs[index];
const auto t = interpolationFactor(interpOptions.exponential.base, rangeBeg, rangeEnd, effectiveZoom);
return mix(getColor(index - 1), getColor(index), clamp(t, 0.0, 1.0));
}
case GPUInterpType::Bezier:
assert(false);
return getColor(0);
}
}
/// Get the index of the entry to use from the zoom level
size_t find(float zoom) device const {
return upper_bound(&inputs[0], &inputs[stopCount], zoom) - &inputs[0];
}
float4 getColor(size_t index) device const { return decode_color(stops.colors[index]); }
};
static_assert(sizeof(GPUExpression) == 32 + (4 + 8) * maxExprStops, "wrong alignment");
static_assert(sizeof(GPUExpression) % 16 == 0, "wrong alignment");
enum {
idGlobalPaintParamsUBO,
globalUBOCount
};
enum {
idLineDrawableUBO = globalUBOCount,
idLineInterpolationUBO,
idLineTilePropertiesUBO,
idLineEvaluatedPropsUBO,
idLineExpressionUBO,
lineUBOCount
};
enum class LineExpressionMask : uint32_t {
None = 0,
Color = 1 << 0,
Opacity = 1 << 1,
Blur = 1 << 2,
Width = 1 << 3,
GapWidth = 1 << 4,
FloorWidth = 1 << 5,
Offset = 1 << 6,
};
bool operator&(LineExpressionMask a, LineExpressionMask b) { return (uint32_t)a & (uint32_t)b; }
struct alignas(16) LineExpressionUBO {
GPUExpression color;
GPUExpression blur;
GPUExpression opacity;
GPUExpression gapwidth;
GPUExpression offset;
GPUExpression width;
GPUExpression floorwidth;
};
static_assert(sizeof(LineExpressionUBO) % 16 == 0, "wrong alignment");
struct alignas(16) GlobalPaintParamsUBO {
/* 0 */ float2 pattern_atlas_texsize;
/* 8 */ float2 units_to_pixels;
@@ -62,7 +247,8 @@ struct alignas(16) GlobalPaintParamsUBO {
/* 28 */ float symbol_fade_change;
/* 32 */ float aspect_ratio;
/* 36 */ float pixel_ratio;
/* 40 */ float pad1, pad2;
/* 40 */ float zoom;
/* 44 */ float pad1;
/* 48 */
};
static_assert(sizeof(GlobalPaintParamsUBO) == 3 * 16, "unexpected padding");
@@ -129,7 +315,8 @@ struct alignas(16) LineEvaluatedPropsUBO {
float offset;
float width;
float floorwidth;
float pad1, pad2;
LineExpressionMask expressionMask;
float pad1;
};
struct alignas(16) SymbolDrawableUBO {

View File

@@ -14,33 +14,33 @@ struct ShaderSource<BuiltIn::LineShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static const std::array<UniformBlockInfo, 4> uniforms;
static const std::array<UniformBlockInfo, 5> uniforms;
static const std::array<AttributeInfo, 8> attributes;
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
static const std::array<TextureInfo, 0> textures;
static constexpr auto source = R"(
struct VertexStage {
short2 pos_normal [[attribute(5)]];
uchar4 data [[attribute(6)]];
short2 pos_normal [[attribute(lineUBOCount + 0)]];
uchar4 data [[attribute(lineUBOCount + 1)]];
#if !defined(HAS_UNIFORM_u_color)
float4 color [[attribute(7)]];
float4 color [[attribute(lineUBOCount + 2)]];
#endif
#if !defined(HAS_UNIFORM_u_blur)
float2 blur [[attribute(8)]];
float2 blur [[attribute(lineUBOCount + 3)]];
#endif
#if !defined(HAS_UNIFORM_u_opacity)
float2 opacity [[attribute(9)]];
float2 opacity [[attribute(lineUBOCount + 4)]];
#endif
#if !defined(HAS_UNIFORM_u_gapwidth)
float2 gapwidth [[attribute(10)]];
float2 gapwidth [[attribute(lineUBOCount + 5)]];
#endif
#if !defined(HAS_UNIFORM_u_offset)
float2 offset [[attribute(11)]];
float2 offset [[attribute(lineUBOCount + 6)]];
#endif
#if !defined(HAS_UNIFORM_u_width)
float2 width [[attribute(12)]];
float2 width [[attribute(lineUBOCount + 7)]];
#endif
};
@@ -78,23 +78,29 @@ struct alignas(16) LineInterpolationUBO {
};
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
device const GlobalPaintParamsUBO& paintParams [[buffer(0)]],
device const LineDrawableUBO& drawable [[buffer(1)]],
device const LineInterpolationUBO& interp [[buffer(2)]],
device const LineEvaluatedPropsUBO& props [[buffer(4)]]) {
device const GlobalPaintParamsUBO& paintParams [[buffer(idGlobalPaintParamsUBO)]],
device const LineDrawableUBO& drawable [[buffer(idLineDrawableUBO)]],
device const LineInterpolationUBO& interp [[buffer(idLineInterpolationUBO)]],
device const LineEvaluatedPropsUBO& props [[buffer(idLineEvaluatedPropsUBO)]],
device const LineExpressionUBO& expr [[buffer(idLineExpressionUBO)]]) {
#if defined(HAS_UNIFORM_u_gapwidth)
const auto gapwidth = props.gapwidth / 2;
const auto exprGapWidth = (props.expressionMask & LineExpressionMask::GapWidth);
const auto gapwidth = (exprGapWidth ? expr.gapwidth.eval(paintParams.zoom) : props.gapwidth) / 2;
#else
const auto gapwidth = unpack_mix_float(vertx.gapwidth, interp.gapwidth_t) / 2;
#endif
#if defined(HAS_UNIFORM_u_offset)
const auto offset = props.offset * -1;
const auto exprOffset = (props.expressionMask & LineExpressionMask::Offset);
const auto offset = (exprOffset ? expr.offset.eval(paintParams.zoom) : props.offset) * -1;
#else
const auto offset = unpack_mix_float(vertx.offset, interp.offset_t) * -1;
#endif
#if defined(HAS_UNIFORM_u_width)
const auto width = props.width;
const auto exprWidth = (props.expressionMask & LineExpressionMask::Width);
const auto width = exprWidth ? expr.width.eval(paintParams.zoom) : props.width;
#else
const auto width = unpack_mix_float(vertx.width, interp.width_t);
#endif
@@ -154,23 +160,30 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
}
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
device const LineEvaluatedPropsUBO& props [[buffer(4)]]) {
device const GlobalPaintParamsUBO& paintParams [[buffer(idGlobalPaintParamsUBO)]],
device const LineEvaluatedPropsUBO& props [[buffer(idLineEvaluatedPropsUBO)]],
device const LineExpressionUBO& expr [[buffer(idLineExpressionUBO)]]) {
#if defined(OVERDRAW_INSPECTOR)
return half4(1.0);
#endif
#if defined(HAS_UNIFORM_u_color)
const float4 color = props.color;
const auto exprColor = (props.expressionMask & LineExpressionMask::Color);
const auto color = exprColor ? expr.color.evalColor(paintParams.zoom) : props.color;
#else
const float4 color = in.color;
#endif
#if defined(HAS_UNIFORM_u_blur)
const float blur = props.blur;
const auto exprBlur = (props.expressionMask & LineExpressionMask::Blur);
const float blur = exprBlur ? expr.blur.eval(paintParams.zoom) : props.blur;
#else
const float blur = in.blur;
#endif
#if defined(HAS_UNIFORM_u_opacity)
const float opacity = props.opacity;
const auto exprOpacity = (props.expressionMask & LineExpressionMask::Opacity);
const float opacity = exprOpacity ? expr.opacity.eval(paintParams.zoom) : props.opacity;
#else
const float opacity = in.opacity;
#endif
@@ -201,13 +214,23 @@ struct ShaderSource<BuiltIn::LineGradientShader, gfx::Backend::Type::Metal> {
static constexpr auto source = R"(
struct VertexStage {
short2 pos_normal [[attribute(5)]];
uchar4 data [[attribute(6)]];
float2 blur [[attribute(7)]];
float2 opacity [[attribute(8)]];
float2 gapwidth [[attribute(9)]];
float2 offset [[attribute(10)]];
float2 width [[attribute(11)]];
short2 pos_normal [[attribute(lineUBOCount + 0)]];
uchar4 data [[attribute(lineUBOCount + 1)]];
#if !defined(HAS_UNIFORM_u_blur)
float2 blur [[attribute(lineUBOCount + 2)]];
#endif
#if !defined(HAS_UNIFORM_u_opacity)
float2 opacity [[attribute(lineUBOCount + 3)]];
#endif
#if !defined(HAS_UNIFORM_u_gapwidth)
float2 gapwidth [[attribute(lineUBOCount + 4)]];
#endif
#if !defined(HAS_UNIFORM_u_offset)
float2 offset [[attribute(lineUBOCount + 5)]];
#endif
#if !defined(HAS_UNIFORM_u_width)
float2 width [[attribute(lineUBOCount + 6)]];
#endif
};
struct FragmentStage {
@@ -241,10 +264,11 @@ struct alignas(16) LineGradientInterpolationUBO {
};
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
device const GlobalPaintParamsUBO& paintParams [[buffer(0)]],
device const LineGradientDrawableUBO& drawable [[buffer(1)]],
device const LineGradientInterpolationUBO& interp [[buffer(2)]],
device const LineEvaluatedPropsUBO& props [[buffer(4)]]) {
device const GlobalPaintParamsUBO& paintParams [[buffer(idGlobalPaintParamsUBO)]],
device const LineGradientDrawableUBO& drawable [[buffer(idLineDrawableUBO)]],
device const LineGradientInterpolationUBO& interp [[buffer(idLineInterpolationUBO)]],
device const LineEvaluatedPropsUBO& props [[buffer(idLineEvaluatedPropsUBO)]],
device const LineExpressionUBO& expr [[buffer(idLineExpressionUBO)]]) {
#if !defined(HAS_UNIFORM_u_blur)
const auto blur = unpack_mix_float(vertx.blur, interp.blur_t);
@@ -253,12 +277,12 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
const auto opacity = unpack_mix_float(vertx.opacity, interp.opacity_t);
#endif
#if defined(HAS_UNIFORM_u_gapwidth)
const auto gapwidth = props.gapwidth;
const auto gapwidth = props.gapwidth / 2;
#else
const auto gapwidth = unpack_mix_float(vertx.gapwidth, interp.gapwidth_t) / 2;
#endif
#if defined(HAS_UNIFORM_u_offset)
const auto offset = props.offset;
const auto offset = props.offset * -1;
#else
const auto offset = unpack_mix_float(vertx.offset, interp.offset_t) * -1;
#endif
@@ -322,7 +346,8 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
}
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
device const LineEvaluatedPropsUBO& props [[buffer(4)]],
device const LineEvaluatedPropsUBO& props [[buffer(idLineEvaluatedPropsUBO)]],
device const LineExpressionUBO& expr [[buffer(idLineExpressionUBO)]],
texture2d<float, access::sample> gradientTexture [[texture(0)]]) {
#if defined(OVERDRAW_INSPECTOR)
return half4(1.0);
@@ -363,36 +388,36 @@ struct ShaderSource<BuiltIn::LinePatternShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static const std::array<UniformBlockInfo, 5> uniforms;
static const std::array<UniformBlockInfo, 6> uniforms;
static const std::array<AttributeInfo, 9> attributes;
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
static const std::array<TextureInfo, 1> textures;
static constexpr auto source = R"(
struct VertexStage {
short2 pos_normal [[attribute(5)]];
uchar4 data [[attribute(6)]];
short2 pos_normal [[attribute(lineUBOCount + 0)]];
uchar4 data [[attribute(lineUBOCount + 1)]];
#if !defined(HAS_UNIFORM_u_blur)
float2 blur [[attribute(7)]];
float2 blur [[attribute(lineUBOCount + 2)]];
#endif
#if !defined(HAS_UNIFORM_u_opacity)
float2 opacity [[attribute(8)]];
float2 opacity [[attribute(lineUBOCount + 3)]];
#endif
#if !defined(HAS_UNIFORM_u_gapwidth)
float2 gapwidth [[attribute(9)]];
float2 gapwidth [[attribute(lineUBOCount + 4)]];
#endif
#if !defined(HAS_UNIFORM_u_offset)
float2 offset [[attribute(10)]];
float2 offset [[attribute(lineUBOCount + 5)]];
#endif
#if !defined(HAS_UNIFORM_u_width)
float2 width [[attribute(11)]];
float2 width [[attribute(lineUBOCount + 6)]];
#endif
#if !defined(HAS_UNIFORM_u_pattern_from)
ushort4 pattern_from [[attribute(12)]];
ushort4 pattern_from [[attribute(lineUBOCount + 7)]];
#endif
#if !defined(HAS_UNIFORM_u_pattern_to)
ushort4 pattern_to [[attribute(13)]];
ushort4 pattern_to [[attribute(lineUBOCount + 8)]];
#endif
};
@@ -442,26 +467,32 @@ struct alignas(16) LinePatternTilePropertiesUBO {
};
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
device const GlobalPaintParamsUBO& paintParams [[buffer(0)]],
device const LinePatternDrawableUBO& drawable [[buffer(1)]],
device const LinePatternInterpolationUBO& interp [[buffer(2)]],
device const LinePatternTilePropertiesUBO& tileProps [[buffer(3)]],
device const LineEvaluatedPropsUBO& props [[buffer(4)]]) {
device const GlobalPaintParamsUBO& paintParams [[buffer(idGlobalPaintParamsUBO)]],
device const LinePatternDrawableUBO& drawable [[buffer(idLineDrawableUBO)]],
device const LinePatternInterpolationUBO& interp [[buffer(idLineInterpolationUBO)]],
device const LinePatternTilePropertiesUBO& tileProps [[buffer(idLineTilePropertiesUBO)]],
device const LineEvaluatedPropsUBO& props [[buffer(idLineEvaluatedPropsUBO)]],
device const LineExpressionUBO& expr [[buffer(idLineExpressionUBO)]]) {
#if defined(HAS_UNIFORM_u_gapwidth)
const auto gapwidth = props.gapwidth / 2;
const auto exprGapWidth = (props.expressionMask & LineExpressionMask::GapWidth);
const auto gapwidth = (exprGapWidth ? expr.gapwidth.eval(paintParams.zoom) : props.gapwidth) / 2;
#else
const auto gapwidth = unpack_mix_float(vertx.gapwidth, interp.gapwidth_t) / 2;
#endif
#if defined(HAS_UNIFORM_u_offset)
const auto offset = props.offset * -1;
const auto exprOffset = (props.expressionMask & LineExpressionMask::Offset);
const auto offset = (exprOffset ? expr.offset.eval(paintParams.zoom) : props.offset) * -1;
#else
const auto offset = unpack_mix_float(vertx.offset, interp.offset_t) * -1;
const auto offset = unpack_mix_float(vertx.offset, interp.offset_t) * -1;
#endif
#if defined(HAS_UNIFORM_u_width)
const auto width = props.width;
const auto exprWidth = (props.expressionMask & LineExpressionMask::Width);
const auto width = exprWidth ? expr.width.eval(paintParams.zoom) : props.width;
#else
const auto width = unpack_mix_float(vertx.width, interp.width_t);
const auto width = unpack_mix_float(vertx.width, interp.width_t);
#endif
// the distance over which the line edge fades out.
@@ -525,9 +556,11 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
}
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
device const LinePatternDrawableUBO& drawable [[buffer(1)]],
device const LinePatternTilePropertiesUBO& tileProps [[buffer(3)]],
device const LineEvaluatedPropsUBO& props [[buffer(4)]],
device const GlobalPaintParamsUBO& paintParams [[buffer(idGlobalPaintParamsUBO)]],
device const LinePatternDrawableUBO& drawable [[buffer(idLineDrawableUBO)]],
device const LinePatternTilePropertiesUBO& tileProps [[buffer(idLineTilePropertiesUBO)]],
device const LineEvaluatedPropsUBO& props [[buffer(idLineEvaluatedPropsUBO)]],
device const LineExpressionUBO& expr [[buffer(idLineExpressionUBO)]],
texture2d<float, access::sample> image0 [[texture(0)]],
sampler image0_sampler [[sampler(0)]]) {
#if defined(OVERDRAW_INSPECTOR)
@@ -535,20 +568,25 @@ half4 fragment fragmentMain(FragmentStage in [[stage_in]],
#endif
#if defined(HAS_UNIFORM_u_blur)
const half blur = props.blur;
const auto exprBlur = (props.expressionMask & LineExpressionMask::Blur);
const float blur = exprBlur ? expr.blur.eval(paintParams.zoom) : props.blur;
#else
const half blur = in.blur;
const float blur = in.blur;
#endif
#if defined(HAS_UNIFORM_u_opacity)
const half opacity = props.opacity;
const auto exprOpacity = (props.expressionMask & LineExpressionMask::Opacity);
const float opacity = exprOpacity ? expr.opacity.eval(paintParams.zoom) : props.opacity;
#else
const half opacity = in.opacity;
const float opacity = in.opacity;
#endif
#if defined(HAS_UNIFORM_u_pattern_from)
const auto pattern_from = float4(tileProps.pattern_from);
#else
const auto pattern_from = float4(in.pattern_from);
#endif
#if defined(HAS_UNIFORM_u_pattern_to)
const auto pattern_to = float4(tileProps.pattern_to);
#else
@@ -606,36 +644,36 @@ struct ShaderSource<BuiltIn::LineSDFShader, gfx::Backend::Type::Metal> {
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static const std::array<UniformBlockInfo, 4> uniforms;
static const std::array<UniformBlockInfo, 5> uniforms;
static const std::array<AttributeInfo, 9> attributes;
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
static const std::array<TextureInfo, 1> textures;
static constexpr auto source = R"(
struct VertexStage {
short2 pos_normal [[attribute(5)]];
uchar4 data [[attribute(6)]];
short2 pos_normal [[attribute(lineUBOCount + 0)]];
uchar4 data [[attribute(lineUBOCount + 1)]];
#if !defined(HAS_UNIFORM_u_color)
float4 color [[attribute(7)]];
float4 color [[attribute(lineUBOCount + 2)]];
#endif
#if !defined(HAS_UNIFORM_u_blur)
float2 blur [[attribute(8)]];
float2 blur [[attribute(lineUBOCount + 3)]];
#endif
#if !defined(HAS_UNIFORM_u_opacity)
float2 opacity [[attribute(9)]];
float2 opacity [[attribute(lineUBOCount + 4)]];
#endif
#if !defined(HAS_UNIFORM_u_gapwidth)
float2 gapwidth [[attribute(10)]];
float2 gapwidth [[attribute(lineUBOCount + 5)]];
#endif
#if !defined(HAS_UNIFORM_u_offset)
float2 offset [[attribute(11)]];
float2 offset [[attribute(lineUBOCount + 6)]];
#endif
#if !defined(HAS_UNIFORM_u_width)
float2 width [[attribute(12)]];
float2 width [[attribute(lineUBOCount + 7)]];
#endif
#if !defined(HAS_UNIFORM_u_floorwidth)
float2 floorwidth [[attribute(13)]];
float2 floorwidth [[attribute(lineUBOCount + 8)]];
#endif
};
@@ -685,28 +723,36 @@ struct alignas(16) LineSDFInterpolationUBO {
};
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
device const GlobalPaintParamsUBO& paintParams [[buffer(0)]],
device const LineSDFDrawableUBO& drawable [[buffer(1)]],
device const LineSDFInterpolationUBO& interp [[buffer(2)]],
device const LineEvaluatedPropsUBO& props [[buffer(4)]]) {
device const GlobalPaintParamsUBO& paintParams [[buffer(idGlobalPaintParamsUBO)]],
device const LineSDFDrawableUBO& drawable [[buffer(idLineDrawableUBO)]],
device const LineSDFInterpolationUBO& interp [[buffer(idLineInterpolationUBO)]],
device const LineEvaluatedPropsUBO& props [[buffer(idLineEvaluatedPropsUBO)]],
device const LineExpressionUBO& expr [[buffer(idLineExpressionUBO)]]) {
#if defined(HAS_UNIFORM_u_gapwidth)
const auto gapwidth = props.gapwidth / 2;
const auto exprGapWidth = (props.expressionMask & LineExpressionMask::GapWidth);
const auto gapwidth = (exprGapWidth ? expr.gapwidth.eval(paintParams.zoom) : props.gapwidth) / 2;
#else
const auto gapwidth = unpack_mix_float(vertx.gapwidth, interp.gapwidth_t) / 2;
const auto gapwidth = unpack_mix_float(vertx.gapwidth, interp.gapwidth_t) / 2;
#endif
#if defined(HAS_UNIFORM_u_offset)
const auto offset = props.offset * -1;
const auto exprOffset = (props.expressionMask & LineExpressionMask::Offset);
const auto offset = (exprOffset ? expr.offset.eval(paintParams.zoom) : props.offset) * -1;
#else
const auto offset = unpack_mix_float(vertx.offset, interp.offset_t) * -1;
const auto offset = unpack_mix_float(vertx.offset, interp.offset_t) * -1;
#endif
#if defined(HAS_UNIFORM_u_width)
const auto width = props.width;
const auto exprWidth = (props.expressionMask & LineExpressionMask::Width);
const auto width = exprWidth ? expr.width.eval(paintParams.zoom) : props.width;
#else
const auto width = unpack_mix_float(vertx.width, interp.width_t);
const auto width = unpack_mix_float(vertx.width, interp.width_t);
#endif
#if defined(HAS_UNIFORM_u_floorwidth)
const auto floorwidth = props.floorwidth;
const auto exprFloorWidth = (props.expressionMask & LineExpressionMask::FloorWidth);
const auto floorwidth = exprFloorWidth ? expr.floorwidth.eval(paintParams.zoom) : props.floorwidth;
#else
const auto floorwidth = unpack_mix_float(vertx.floorwidth, interp.floorwidth_t);
#endif
@@ -773,8 +819,10 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
}
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
device const LineSDFDrawableUBO& drawable [[buffer(1)]],
device const LineEvaluatedPropsUBO& props [[buffer(4)]],
device const GlobalPaintParamsUBO& paintParams [[buffer(idGlobalPaintParamsUBO)]],
device const LineSDFDrawableUBO& drawable [[buffer(idLineDrawableUBO)]],
device const LineEvaluatedPropsUBO& props [[buffer(idLineEvaluatedPropsUBO)]],
device const LineExpressionUBO& expr [[buffer(idLineExpressionUBO)]],
texture2d<float, access::sample> image0 [[texture(0)]],
sampler image0_sampler [[sampler(0)]]) {
#if defined(OVERDRAW_INSPECTOR)
@@ -782,24 +830,31 @@ half4 fragment fragmentMain(FragmentStage in [[stage_in]],
#endif
#if defined(HAS_UNIFORM_u_color)
const float4 color = props.color;
const auto exprColor = (props.expressionMask & LineExpressionMask::Color);
const auto color = exprColor ? expr.color.evalColor(paintParams.zoom) : props.color;
#else
const float4 color = in.color;
#endif
#if defined(HAS_UNIFORM_u_blur)
const float blur = props.blur;
const auto exprBlur = (props.expressionMask & LineExpressionMask::Blur);
const float blur = exprBlur ? expr.blur.eval(paintParams.zoom) : props.blur;
#else
const float blur = in.blur;
#endif
#if defined(HAS_UNIFORM_u_opacity)
const float opacity = props.opacity;
const auto exprOpacity = (props.expressionMask & LineExpressionMask::Opacity);
const float opacity = exprOpacity ? expr.opacity.eval(paintParams.zoom) : props.opacity;
#else
const float opacity = in.opacity;
#endif
#if defined(HAS_UNIFORM_u_floorwidth)
const float floorwidth = props.floorwidth;
const auto exprFloorWidth = (props.expressionMask & LineExpressionMask::FloorWidth);
const auto floorwidth = exprFloorWidth ? expr.floorwidth.eval(paintParams.zoom) : props.floorwidth;
#else
const float floorwidth = in.floorwidth;
const auto floorwidth = in.floorwidth;
#endif
// Calculate the antialiasing fade factor. This is either when fading in the

View File

@@ -4,6 +4,7 @@
#include <mbgl/style/expression/type.hpp>
#include <mbgl/style/expression/value.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/util/bitmask_operations.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/traits.hpp>
#include <mbgl/util/variant.hpp>
@@ -202,17 +203,14 @@ enum class Dependency : uint32_t {
Var = 1 << 5, // Use variable binding
Override = 1 << 6, // Property override
MaskCount = 7,
All = (1 << MaskCount) - 1,
};
inline constexpr static Dependency operator|(Dependency x, Dependency y) noexcept {
return Dependency{mbgl::underlying_type(x) | mbgl::underlying_type(y)};
}
inline constexpr static Dependency operator&(Dependency x, Dependency y) noexcept {
return Dependency{mbgl::underlying_type(x) & mbgl::underlying_type(y)};
}
inline static Dependency& operator|=(Dependency& target, Dependency source) noexcept {
target = target | source;
return target;
}
class Interpolate;
class Step;
using ZoomCurveOrError = std::optional<variant<const Interpolate*, const Step*, ParsingError>>;
using ZoomCurvePtr = variant<std::nullptr_t, const Interpolate*, const Step*>;
class Expression {
public:
@@ -264,6 +262,9 @@ public:
const Dependency dependencies;
/// Test the expression's dependencies for any of one or more values
bool has(Dependency dep) const { return (dependencies & dep); }
protected:
template <typename T>
static bool childrenEqual(const T& lhs, const T& rhs) noexcept {

View File

@@ -11,9 +11,18 @@ namespace mbgl {
namespace style {
namespace expression {
std::optional<variant<const Interpolate*, const Step*, ParsingError>> findZoomCurve(const expression::Expression*);
using ZoomCurveOrError = std::optional<variant<const Interpolate*, const Step*, ParsingError>>;
using ZoomCurvePtr = variant<std::nullptr_t, const Interpolate*, const Step*>;
variant<std::nullptr_t, const Interpolate*, const Step*> findZoomCurveChecked(const expression::Expression&);
/// Find a zoom curve in the expression tree.
/// @param expr Expression root
/// @return The relevant step or interpolate item, or the error if the expression represents an error
ZoomCurveOrError findZoomCurve(const expression::Expression&);
/// Find a zoom curve in the expression tree.
/// @param expr Expression root
/// @return The relevant step or interpolate item, or null if the expression represents an error
ZoomCurvePtr findZoomCurveChecked(const expression::Expression& expr);
} // namespace expression
} // namespace style

View File

@@ -34,6 +34,8 @@ public:
}
}
std::size_t getStopCount() const { return stops.size(); }
void eachStop(const std::function<void(double, const Expression&)>& visit) const {
for (const auto& stop : stops) {
visit(stop.first, *stop.second);

View File

@@ -17,7 +17,8 @@ public:
using Bindings = std::map<std::string, std::shared_ptr<Expression>>;
Let(Bindings bindings_, std::unique_ptr<Expression> result_)
: Expression(Kind::Let, result_->getType(), collectDependencies(bindings_) | Dependency::Bind),
: Expression(
Kind::Let, result_->getType(), collectDependencies(bindings_) | depsOf(result_) | Dependency::Bind),
bindings(std::move(bindings_)),
result(std::move(result_)) {}

View File

@@ -20,6 +20,8 @@ public:
EvaluationResult evaluate(const EvaluationContext& params) const override;
void eachChild(const std::function<void(const Expression&)>& visit) const override;
std::size_t getStopCount() const { return stops.size(); }
void eachStop(const std::function<void(double, const Expression&)>& visit) const;
const std::unique_ptr<Expression>& getInput() const noexcept { return input; }

View File

@@ -5,45 +5,75 @@
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/step.hpp>
#include <mbgl/style/expression/find_zoom_curve.hpp>
#include <mbgl/util/bitmask_operations.hpp>
#include <mbgl/util/range.hpp>
#if MLN_DRAWABLE_RENDERER
#include <mbgl/gfx/gpu_expression.hpp>
#endif // MLN_DRAWABLE_RENDERER
#include <optional>
namespace mbgl {
namespace gfx {
class GPUExpression;
using UniqueGPUExpression = std::unique_ptr<GPUExpression>;
} // namespace gfx
namespace style {
class PropertyExpressionBase {
public:
explicit PropertyExpressionBase(std::unique_ptr<expression::Expression>) noexcept;
using Expression = expression::Expression;
using Dependency = expression::Dependency;
using ZoomCurvePtr = expression::ZoomCurvePtr;
PropertyExpressionBase(PropertyExpressionBase&&);
PropertyExpressionBase(const PropertyExpressionBase&);
explicit PropertyExpressionBase(std::unique_ptr<Expression>);
virtual ~PropertyExpressionBase() = default;
PropertyExpressionBase& operator=(PropertyExpressionBase&&);
PropertyExpressionBase& operator=(const PropertyExpressionBase&);
bool isZoomConstant() const noexcept { return isZoomConstant_; }
bool isFeatureConstant() const noexcept { return isFeatureConstant_; }
bool isRuntimeConstant() const noexcept { return isRuntimeConstant_; }
float interpolationFactor(const Range<float>&, float) const noexcept;
Range<float> getCoveringStops(float, float) const noexcept;
const expression::Expression& getExpression() const noexcept;
const Expression& getExpression() const noexcept;
/// Can be used for aggregating property expressions from multiple
/// properties(layers) into single match / case expression. Method may
/// be removed if a better way of aggregation is found.
std::shared_ptr<const expression::Expression> getSharedExpression() const noexcept;
bool isGPUCapable() const { return isGPUCapable_; }
bool useIntegerZoom = false;
bool getUseIntegerZoom() const { return useIntegerZoom_; }
void setUseIntegerZoom(bool value) { useIntegerZoom_ = value; }
using Dependency = expression::Dependency;
Dependency getDependencies() const noexcept {
auto v = expression ? expression->dependencies : Dependency::None;
assert(isZoomConstant_ == !(underlying_type(v) & underlying_type(Dependency::Zoom)));
assert(isFeatureConstant_ == !(underlying_type(v) & underlying_type(Dependency::Feature)));
return v;
}
/// Can be used for aggregating property expressions from multiple properties(layers) into single match / case
/// expression. May be removed if a better way of aggregation is found.
std::shared_ptr<const Expression> getSharedExpression() const noexcept;
#if MLN_DRAWABLE_RENDERER
/// Build a cached GPU representation of the expression, with the same lifetime as this object.
gfx::UniqueGPUExpression getGPUExpression(bool intZoom) const;
#endif // MLN_DRAWABLE_RENDERER
Dependency getDependencies() const noexcept { return expression ? expression->dependencies : Dependency::None; }
const ZoomCurvePtr& getZoomCurve() const { return zoomCurve; }
protected:
std::shared_ptr<const expression::Expression> expression;
std::shared_ptr<const Expression> expression;
ZoomCurvePtr zoomCurve;
bool useIntegerZoom_ = false;
bool isZoomConstant_;
bool isFeatureConstant_;
bool isRuntimeConstant_;
variant<std::nullptr_t, const expression::Interpolate*, const expression::Step*> zoomCurve;
// If the expression depends on zoom and nothing else, and produces
// a number or color, we can potentially evaluate it on the GPU
bool isGPUCapable_;
};
template <class T>
@@ -52,8 +82,7 @@ class PropertyExpression final : public PropertyExpressionBase {
public:
// Second parameter to be used only for conversions from legacy functions.
PropertyExpression(std::unique_ptr<expression::Expression> expression_,
std::optional<T> defaultValue_ = std::nullopt) noexcept
PropertyExpression(std::unique_ptr<Expression> expression_, std::optional<T> defaultValue_ = std::nullopt)
: PropertyExpressionBase(std::move(expression_)),
defaultValue(std::move(defaultValue_)) {}

View File

@@ -49,6 +49,7 @@ public:
const T& asConstant() const noexcept { return value.template get<T>(); }
PropertyExpression<T>& asExpression() noexcept { return value.template get<PropertyExpression<T>>(); }
const PropertyExpression<T>& asExpression() const noexcept { return value.template get<PropertyExpression<T>>(); }
template <class... Ts>

View File

@@ -27,6 +27,8 @@ public:
assert(a_ >= 0.0f);
assert(a_ <= 1.0f);
}
Color(const float rgba[4])
: Color(rgba[0], rgba[1], rgba[2], rgba[3]) {}
float r = 0.0f;
float g = 0.0f;

View File

@@ -5,6 +5,7 @@
#include <algorithm>
#include <array>
#include <cstddef>
#include <tuple>
#include <type_traits>
namespace mbgl {
@@ -24,5 +25,12 @@ constexpr std::array<To, Size> cast(const std::array<From, Size>& from) {
return to;
}
/// Convert an `N`-tuple of all `T`s to `array<T,N>`
template <typename... Ts>
inline constexpr auto to_array(std::tuple<Ts...>&& tuple) {
return std::apply([](auto&&... x) { return std::array{std::forward<decltype(x)>(x)...}; },
std::forward<std::tuple<Ts...>>(tuple));
}
} // namespace util
} // namespace mbgl

View File

@@ -1,5 +1,7 @@
#pragma once
#include <mbgl/util/traits.hpp>
#include <algorithm>
#include <cassert>
#include <string>

View File

@@ -30,31 +30,36 @@ public:
static_assert(sizeof...(Is) == sizeof...(Ts), "IndexedTuple size mismatch");
template <class I>
auto& get() {
return std::get<TypeIndex<I, Is...>::value>(*this);
static constexpr std::size_t getIndex() {
return TypeIndex<I, Is...>::value;
}
template <class I>
const auto& get() const {
return std::get<TypeIndex<I, Is...>::value>(*this);
constexpr auto& get() {
return std::get<getIndex<I>()>(*this);
}
template <class I>
constexpr const auto& get() const {
return std::get<getIndex<I>()>(*this);
}
template <class... Us>
IndexedTuple(Us&&... other)
constexpr IndexedTuple(Us&&... other)
: std::tuple<Ts...>(std::forward<Us>(other)...) {}
template <class... Js, class... Us>
IndexedTuple<TypeList<Is..., Js...>, TypeList<Ts..., Us...>> concat(
constexpr IndexedTuple<TypeList<Is..., Js...>, TypeList<Ts..., Us...>> concat(
const IndexedTuple<TypeList<Js...>, TypeList<Us...>>& other) const {
return IndexedTuple<TypeList<Is..., Js...>, TypeList<Ts..., Us...>>{get<Is>()..., other.template get<Js>()...};
}
// Help out MSVC++
bool operator==(const IndexedTuple<TypeList<Is...>, TypeList<Ts...>>& other) const {
constexpr bool operator==(const IndexedTuple<TypeList<Is...>, TypeList<Ts...>>& other) const {
return static_cast<const std::tuple<Ts...>&>(*this) == static_cast<const std::tuple<Ts...>&>(other);
}
bool operator!=(const IndexedTuple<TypeList<Is...>, TypeList<Ts...>>& other) const noexcept {
constexpr bool operator!=(const IndexedTuple<TypeList<Is...>, TypeList<Ts...>>& other) const {
return !(*this == other);
}
};

View File

@@ -11,10 +11,18 @@ struct SuppressCopies {
SuppressCopies(SuppressCopies const&) noexcept {}
SuppressCopies(SuppressCopies&& other)
: value(std::forward<T>(other.value)) noexcept {}
SuppressCopies& operator=(SuppressCopies o) noexcept {
SuppressCopies& operator=(T&& o) {
value = std::move(o);
return *this;
}
SuppressCopies& operator=(SuppressCopies o) {
std::swap(value, o.value);
return *this;
}
T& operator->() noexcept { return value; }
const T& operator->() const noexcept { return value; }
operator T&() noexcept { return value; }
T& get() noexcept { return value; }

View File

@@ -9,6 +9,7 @@ template <class... Ts>
struct TypeList {
template <template <class...> class T, class... Ps>
using ExpandInto = T<Ps..., Ts...>;
static constexpr std::size_t TypeCount = sizeof...(Ts);
};
namespace detail {

View File

@@ -3,6 +3,8 @@
namespace mbgl {
namespace gfx {
bool Backend::enableGPUExpressionEval = false;
HeadlessBackend::HeadlessBackend(Size size_)
: mbgl::gfx::Renderable(size_, nullptr) {}

View File

@@ -229,7 +229,10 @@ ios_application(
infoplists = ["//platform/ios/benchmark:info_benchmark_plist"],
minimum_os_version = "12.0",
provisioning_profile = "xcode_profile",
resources = ["//platform/ios/benchmark:bundle_resources"],
resources = [
"//platform/ios/benchmark:bundle_resources",
"//platform/ios/benchmark/assets:benchmark_assets",
],
visibility = ["//visibility:public"],
deps = [
"//platform:ios-benchapp",

View File

@@ -26,8 +26,6 @@ filegroup(
srcs = glob([
"*.lproj/**",
"Assets.xcassets/**",
"assets/**/*.json",
"assets/**/*.png",
]),
visibility = ["//platform/ios:__pkg__"],
)

View File

@@ -0,0 +1,14 @@
load("@build_bazel_rules_apple//apple:resources.bzl", "apple_resource_group")
apple_resource_group(
name = "benchmark_assets",
structured_resources = glob(
[
"**/*.json",
"**/*.png",
"**/*.pbf",
],
allow_empty = True,
),
visibility = ["//platform/ios:__pkg__"],
)

316
platform/ios/benchmark/assets/glyphs/download.sh Normal file → Executable file
View File

@@ -3,36 +3,300 @@
set -u
LIST=(
"Noto%20Sans%20Regular/0-255.pbf"
"Roboto%20Condensed%20Italic,Noto%20Sans%20Italic/0-255.pbf"
"Roboto%20Condensed%20Italic,Noto%20Sans%20Italic/256-511.pbf"
"Roboto%20Medium,Noto%20Sans%20Regular/0-255.pbf"
"Roboto%20Medium,Noto%20Sans%20Regular/65024-65279.pbf"
"Roboto%20Medium,Noto%20Sans%20Regular/11520-11775.pbf"
"Roboto%20Regular,Noto%20Sans%20Regular/0-255.pbf"
"Roboto%20Regular,Noto%20Sans%20Regular/256-511.pbf"
"Roboto%20Regular,Noto%20Sans%20Regular/512-767.pbf"
"Roboto%20Regular,Noto%20Sans%20Regular/768-1023.pbf"
"Roboto%20Regular,Noto%20Sans%20Regular/1024-1279.pbf"
"Roboto%20Regular,Noto%20Sans%20Regular/8192-8447.pbf"
"Roboto%20Medium,Noto%20Sans%20Regular/256-511.pbf"
"Roboto%20Medium,Noto%20Sans%20Regular/512-767.pbf"
"Roboto%20Medium,Noto%20Sans%20Regular/768-1023.pbf"
"Roboto%20Medium,Noto%20Sans%20Regular/1024-1279.pbf"
"Noto Sans Regular/0-255.pbf"
"Roboto Condensed Italic,Noto Sans Italic/0-255.pbf"
"Roboto Condensed Italic,Noto Sans Italic/256-511.pbf"
"Roboto Medium,Noto Sans Regular/0-255.pbf"
"Roboto Medium,Noto Sans Regular/65024-65279.pbf"
"Roboto Medium,Noto Sans Regular/11520-11775.pbf"
"Roboto Regular,Noto Sans Regular/0-255.pbf"
"Roboto Regular,Noto Sans Regular/256-511.pbf"
"Roboto Regular,Noto Sans Regular/512-767.pbf"
"Roboto Regular,Noto Sans Regular/768-1023.pbf"
"Roboto Regular,Noto Sans Regular/1024-1279.pbf"
"Roboto Regular,Noto Sans Regular/8192-8447.pbf"
"Roboto Medium,Noto Sans Regular/256-511.pbf"
"Roboto Medium,Noto Sans Regular/512-767.pbf"
"Roboto Medium,Noto Sans Regular/768-1023.pbf"
"Roboto Medium,Noto Sans Regular/1024-1279.pbf"
# Observed from dynamic benchmark
"Noto Sans Regular/19968-20223.pbf"
"Noto Sans Regular/22016-22271.pbf"
"Noto Sans Regular/22272-22527.pbf"
"Noto Sans Regular/26368-26623.pbf"
"Noto Sans Regular/26624-26879.pbf"
"Noto Sans Regular/27904-28159.pbf"
"Noto Sans Regular/34304-34559.pbf"
"Noto Sans Regular/38400-38655.pbf"
"Roboto Condensed Italic,Noto Sans Italic/512-767.pbf"
"Roboto Condensed Italic,Noto Sans Italic/7680-7935.pbf"
"Roboto Condensed Italic,Noto Sans Italic/8192-8447.pbf"
"Roboto Condensed Italic,Noto Sans Italic/19968-20223.pbf"
"Roboto Condensed Italic,Noto Sans Italic/20224-20479.pbf"
"Roboto Condensed Italic,Noto Sans Italic/20480-20735.pbf"
"Roboto Condensed Italic,Noto Sans Italic/20736-20991.pbf"
"Roboto Condensed Italic,Noto Sans Italic/20992-21247.pbf"
"Roboto Condensed Italic,Noto Sans Italic/21248-21503.pbf"
"Roboto Condensed Italic,Noto Sans Italic/21504-21759.pbf"
"Roboto Condensed Italic,Noto Sans Italic/22016-22271.pbf"
"Roboto Condensed Italic,Noto Sans Italic/22272-22527.pbf"
"Roboto Condensed Italic,Noto Sans Italic/22528-22783.pbf"
"Roboto Condensed Italic,Noto Sans Italic/22784-23039.pbf"
"Roboto Condensed Italic,Noto Sans Italic/23296-23551.pbf"
"Roboto Condensed Italic,Noto Sans Italic/23552-23807.pbf"
"Roboto Condensed Italic,Noto Sans Italic/23808-24063.pbf"
"Roboto Condensed Italic,Noto Sans Italic/24064-24319.pbf"
"Roboto Condensed Italic,Noto Sans Italic/24320-24575.pbf"
"Roboto Condensed Italic,Noto Sans Italic/25088-25343.pbf"
"Roboto Condensed Italic,Noto Sans Italic/25344-25599.pbf"
"Roboto Condensed Italic,Noto Sans Italic/25856-26111.pbf"
"Roboto Condensed Italic,Noto Sans Italic/26112-26367.pbf"
"Roboto Condensed Italic,Noto Sans Italic/26368-26623.pbf"
"Roboto Condensed Italic,Noto Sans Italic/26624-26879.pbf"
"Roboto Condensed Italic,Noto Sans Italic/26880-27135.pbf"
"Roboto Condensed Italic,Noto Sans Italic/27136-27391.pbf"
"Roboto Condensed Italic,Noto Sans Italic/27392-27647.pbf"
"Roboto Condensed Italic,Noto Sans Italic/27648-27903.pbf"
"Roboto Condensed Italic,Noto Sans Italic/27904-28159.pbf"
"Roboto Condensed Italic,Noto Sans Italic/28160-28415.pbf"
"Roboto Condensed Italic,Noto Sans Italic/28416-28671.pbf"
"Roboto Condensed Italic,Noto Sans Italic/29184-29439.pbf"
"Roboto Condensed Italic,Noto Sans Italic/29440-29695.pbf"
"Roboto Condensed Italic,Noto Sans Italic/29696-29951.pbf"
"Roboto Condensed Italic,Noto Sans Italic/29952-30207.pbf"
"Roboto Condensed Italic,Noto Sans Italic/30208-30463.pbf"
"Roboto Condensed Italic,Noto Sans Italic/30464-30719.pbf"
"Roboto Condensed Italic,Noto Sans Italic/30720-30975.pbf"
"Roboto Condensed Italic,Noto Sans Italic/30976-31231.pbf"
"Roboto Condensed Italic,Noto Sans Italic/31232-31487.pbf"
"Roboto Condensed Italic,Noto Sans Italic/31488-31743.pbf"
"Roboto Condensed Italic,Noto Sans Italic/31744-31999.pbf"
"Roboto Condensed Italic,Noto Sans Italic/32000-32255.pbf"
"Roboto Condensed Italic,Noto Sans Italic/32256-32511.pbf"
"Roboto Condensed Italic,Noto Sans Italic/32512-32767.pbf"
"Roboto Condensed Italic,Noto Sans Italic/32768-33023.pbf"
"Roboto Condensed Italic,Noto Sans Italic/33280-33535.pbf"
"Roboto Condensed Italic,Noto Sans Italic/33536-33791.pbf"
"Roboto Condensed Italic,Noto Sans Italic/34304-34559.pbf"
"Roboto Condensed Italic,Noto Sans Italic/34816-35071.pbf"
"Roboto Condensed Italic,Noto Sans Italic/35072-35327.pbf"
"Roboto Condensed Italic,Noto Sans Italic/35584-35839.pbf"
"Roboto Condensed Italic,Noto Sans Italic/35840-36095.pbf"
"Roboto Condensed Italic,Noto Sans Italic/36096-36351.pbf"
"Roboto Condensed Italic,Noto Sans Italic/36608-36863.pbf"
"Roboto Condensed Italic,Noto Sans Italic/36864-37119.pbf"
"Roboto Condensed Italic,Noto Sans Italic/37120-37375.pbf"
"Roboto Condensed Italic,Noto Sans Italic/37888-38143.pbf"
"Roboto Condensed Italic,Noto Sans Italic/38144-38399.pbf"
"Roboto Condensed Italic,Noto Sans Italic/38400-38655.pbf"
"Roboto Condensed Italic,Noto Sans Italic/38656-38911.pbf"
"Roboto Condensed Italic,Noto Sans Italic/38912-39167.pbf"
"Roboto Condensed Italic,Noto Sans Italic/39168-39423.pbf"
"Roboto Condensed Italic,Noto Sans Italic/39424-39679.pbf"
"Roboto Condensed Italic,Noto Sans Italic/39936-40191.pbf"
"Roboto Condensed Italic,Noto Sans Italic/40448-40703.pbf"
"Roboto Condensed Italic,Noto Sans Italic/40704-40959.pbf"
"Roboto Medium,Noto Sans Regular/1536-1791.pbf"
"Roboto Medium,Noto Sans Regular/1792-2047.pbf"
"Roboto Medium,Noto Sans Regular/2304-2559.pbf"
"Roboto Medium,Noto Sans Regular/2816-3071.pbf"
"Roboto Medium,Noto Sans Regular/3584-3839.pbf"
"Roboto Medium,Noto Sans Regular/3840-4095.pbf"
"Roboto Medium,Noto Sans Regular/4096-4351.pbf"
"Roboto Medium,Noto Sans Regular/5888-6143.pbf"
"Roboto Medium,Noto Sans Regular/6144-6399.pbf"
"Roboto Medium,Noto Sans Regular/7680-7935.pbf"
"Roboto Medium,Noto Sans Regular/8192-8447.pbf"
"Roboto Medium,Noto Sans Regular/19968-20223.pbf"
"Roboto Medium,Noto Sans Regular/20224-20479.pbf"
"Roboto Medium,Noto Sans Regular/20736-20991.pbf"
"Roboto Medium,Noto Sans Regular/20992-21247.pbf"
"Roboto Medium,Noto Sans Regular/21248-21503.pbf"
"Roboto Medium,Noto Sans Regular/21504-21759.pbf"
"Roboto Medium,Noto Sans Regular/21760-22015.pbf"
"Roboto Medium,Noto Sans Regular/22016-22271.pbf"
"Roboto Medium,Noto Sans Regular/22272-22527.pbf"
"Roboto Medium,Noto Sans Regular/22528-22783.pbf"
"Roboto Medium,Noto Sans Regular/22784-23039.pbf"
"Roboto Medium,Noto Sans Regular/23040-23295.pbf"
"Roboto Medium,Noto Sans Regular/23296-23551.pbf"
"Roboto Medium,Noto Sans Regular/23552-23807.pbf"
"Roboto Medium,Noto Sans Regular/23808-24063.pbf"
"Roboto Medium,Noto Sans Regular/24064-24319.pbf"
"Roboto Medium,Noto Sans Regular/24320-24575.pbf"
"Roboto Medium,Noto Sans Regular/24576-24831.pbf"
"Roboto Medium,Noto Sans Regular/24832-25087.pbf"
"Roboto Medium,Noto Sans Regular/25088-25343.pbf"
"Roboto Medium,Noto Sans Regular/25856-26111.pbf"
"Roboto Medium,Noto Sans Regular/26112-26367.pbf"
"Roboto Medium,Noto Sans Regular/26368-26623.pbf"
"Roboto Medium,Noto Sans Regular/26624-26879.pbf"
"Roboto Medium,Noto Sans Regular/26880-27135.pbf"
"Roboto Medium,Noto Sans Regular/27136-27391.pbf"
"Roboto Medium,Noto Sans Regular/27392-27647.pbf"
"Roboto Medium,Noto Sans Regular/27648-27903.pbf"
"Roboto Medium,Noto Sans Regular/27904-28159.pbf"
"Roboto Medium,Noto Sans Regular/28160-28415.pbf"
"Roboto Medium,Noto Sans Regular/28416-28671.pbf"
"Roboto Medium,Noto Sans Regular/28672-28927.pbf"
"Roboto Medium,Noto Sans Regular/28928-29183.pbf"
"Roboto Medium,Noto Sans Regular/29184-29439.pbf"
"Roboto Medium,Noto Sans Regular/29440-29695.pbf"
"Roboto Medium,Noto Sans Regular/29696-29951.pbf"
"Roboto Medium,Noto Sans Regular/29952-30207.pbf"
"Roboto Medium,Noto Sans Regular/30208-30463.pbf"
"Roboto Medium,Noto Sans Regular/30464-30719.pbf"
"Roboto Medium,Noto Sans Regular/30976-31231.pbf"
"Roboto Medium,Noto Sans Regular/31232-31487.pbf"
"Roboto Medium,Noto Sans Regular/32256-32511.pbf"
"Roboto Medium,Noto Sans Regular/32512-32767.pbf"
"Roboto Medium,Noto Sans Regular/32768-33023.pbf"
"Roboto Medium,Noto Sans Regular/33024-33279.pbf"
"Roboto Medium,Noto Sans Regular/33280-33535.pbf"
"Roboto Medium,Noto Sans Regular/33536-33791.pbf"
"Roboto Medium,Noto Sans Regular/33792-34047.pbf"
"Roboto Medium,Noto Sans Regular/34048-34303.pbf"
"Roboto Medium,Noto Sans Regular/34304-34559.pbf"
"Roboto Medium,Noto Sans Regular/34816-35071.pbf"
"Roboto Medium,Noto Sans Regular/35072-35327.pbf"
"Roboto Medium,Noto Sans Regular/35584-35839.pbf"
"Roboto Medium,Noto Sans Regular/36096-36351.pbf"
"Roboto Medium,Noto Sans Regular/36608-36863.pbf"
"Roboto Medium,Noto Sans Regular/36864-37119.pbf"
"Roboto Medium,Noto Sans Regular/37120-37375.pbf"
"Roboto Medium,Noto Sans Regular/37888-38143.pbf"
"Roboto Medium,Noto Sans Regular/38144-38399.pbf"
"Roboto Medium,Noto Sans Regular/38400-38655.pbf"
"Roboto Medium,Noto Sans Regular/38656-38911.pbf"
"Roboto Medium,Noto Sans Regular/38912-39167.pbf"
"Roboto Medium,Noto Sans Regular/39168-39423.pbf"
"Roboto Medium,Noto Sans Regular/39424-39679.pbf"
"Roboto Medium,Noto Sans Regular/40448-40703.pbf"
"Roboto Medium,Noto Sans Regular/40704-40959.pbf"
"Roboto Medium,Noto Sans Regular/40960-41215.pbf"
"Roboto Medium,Noto Sans Regular/41728-41983.pbf"
"Roboto Medium,Noto Sans Regular/44032-44287.pbf"
"Roboto Medium,Noto Sans Regular/44288-44543.pbf"
"Roboto Medium,Noto Sans Regular/44544-44799.pbf"
"Roboto Medium,Noto Sans Regular/45056-45311.pbf"
"Roboto Medium,Noto Sans Regular/45824-46079.pbf"
"Roboto Medium,Noto Sans Regular/46848-47103.pbf"
"Roboto Medium,Noto Sans Regular/47616-47871.pbf"
"Roboto Medium,Noto Sans Regular/48384-48639.pbf"
"Roboto Medium,Noto Sans Regular/49152-49407.pbf"
"Roboto Medium,Noto Sans Regular/49408-49663.pbf"
"Roboto Medium,Noto Sans Regular/49664-49919.pbf"
"Roboto Medium,Noto Sans Regular/50432-50687.pbf"
"Roboto Medium,Noto Sans Regular/50688-50943.pbf"
"Roboto Medium,Noto Sans Regular/50944-51199.pbf"
"Roboto Medium,Noto Sans Regular/51200-51455.pbf"
"Roboto Medium,Noto Sans Regular/52224-52479.pbf"
"Roboto Medium,Noto Sans Regular/54016-54271.pbf"
"Roboto Medium,Noto Sans Regular/54528-54783.pbf"
"Roboto Medium,Noto Sans Regular/54784-55039.pbf"
"Roboto Medium,Noto Sans Regular/55040-55295.pbf"
"Roboto Medium,Noto Sans Regular/64256-64511.pbf"
"Roboto Regular,Noto Sans Regular/2816-3071.pbf"
"Roboto Regular,Noto Sans Regular/3072-3327.pbf"
"Roboto Regular,Noto Sans Regular/7680-7935.pbf"
"Roboto Regular,Noto Sans Regular/12288-12543.pbf"
"Roboto Regular,Noto Sans Regular/19968-20223.pbf"
"Roboto Regular,Noto Sans Regular/20224-20479.pbf"
"Roboto Regular,Noto Sans Regular/20480-20735.pbf"
"Roboto Regular,Noto Sans Regular/20736-20991.pbf"
"Roboto Regular,Noto Sans Regular/20992-21247.pbf"
"Roboto Regular,Noto Sans Regular/21248-21503.pbf"
"Roboto Regular,Noto Sans Regular/21504-21759.pbf"
"Roboto Regular,Noto Sans Regular/21760-22015.pbf"
"Roboto Regular,Noto Sans Regular/22016-22271.pbf"
"Roboto Regular,Noto Sans Regular/22272-22527.pbf"
"Roboto Regular,Noto Sans Regular/22528-22783.pbf"
"Roboto Regular,Noto Sans Regular/22784-23039.pbf"
"Roboto Regular,Noto Sans Regular/23040-23295.pbf"
"Roboto Regular,Noto Sans Regular/23296-23551.pbf"
"Roboto Regular,Noto Sans Regular/23552-23807.pbf"
"Roboto Regular,Noto Sans Regular/23808-24063.pbf"
"Roboto Regular,Noto Sans Regular/24064-24319.pbf"
"Roboto Regular,Noto Sans Regular/24320-24575.pbf"
"Roboto Regular,Noto Sans Regular/24576-24831.pbf"
"Roboto Regular,Noto Sans Regular/24832-25087.pbf"
"Roboto Regular,Noto Sans Regular/25088-25343.pbf"
"Roboto Regular,Noto Sans Regular/25344-25599.pbf"
"Roboto Regular,Noto Sans Regular/25856-26111.pbf"
"Roboto Regular,Noto Sans Regular/26112-26367.pbf"
"Roboto Regular,Noto Sans Regular/26368-26623.pbf"
"Roboto Regular,Noto Sans Regular/26624-26879.pbf"
"Roboto Regular,Noto Sans Regular/26880-27135.pbf"
"Roboto Regular,Noto Sans Regular/27136-27391.pbf"
"Roboto Regular,Noto Sans Regular/27392-27647.pbf"
"Roboto Regular,Noto Sans Regular/27648-27903.pbf"
"Roboto Regular,Noto Sans Regular/27904-28159.pbf"
"Roboto Regular,Noto Sans Regular/28160-28415.pbf"
"Roboto Regular,Noto Sans Regular/28416-28671.pbf"
"Roboto Regular,Noto Sans Regular/28672-28927.pbf"
"Roboto Regular,Noto Sans Regular/28928-29183.pbf"
"Roboto Regular,Noto Sans Regular/29184-29439.pbf"
"Roboto Regular,Noto Sans Regular/29440-29695.pbf"
"Roboto Regular,Noto Sans Regular/29696-29951.pbf"
"Roboto Regular,Noto Sans Regular/29952-30207.pbf"
"Roboto Regular,Noto Sans Regular/30208-30463.pbf"
"Roboto Regular,Noto Sans Regular/30464-30719.pbf"
"Roboto Regular,Noto Sans Regular/30720-30975.pbf"
"Roboto Regular,Noto Sans Regular/30976-31231.pbf"
"Roboto Regular,Noto Sans Regular/31232-31487.pbf"
"Roboto Regular,Noto Sans Regular/31488-31743.pbf"
"Roboto Regular,Noto Sans Regular/31744-31999.pbf"
"Roboto Regular,Noto Sans Regular/32000-32255.pbf"
"Roboto Regular,Noto Sans Regular/32256-32511.pbf"
"Roboto Regular,Noto Sans Regular/32512-32767.pbf"
"Roboto Regular,Noto Sans Regular/32768-33023.pbf"
"Roboto Regular,Noto Sans Regular/33024-33279.pbf"
"Roboto Regular,Noto Sans Regular/33280-33535.pbf"
"Roboto Regular,Noto Sans Regular/33536-33791.pbf"
"Roboto Regular,Noto Sans Regular/33792-34047.pbf"
"Roboto Regular,Noto Sans Regular/34048-34303.pbf"
"Roboto Regular,Noto Sans Regular/34304-34559.pbf"
"Roboto Regular,Noto Sans Regular/34560-34815.pbf"
"Roboto Regular,Noto Sans Regular/34816-35071.pbf"
"Roboto Regular,Noto Sans Regular/35072-35327.pbf"
"Roboto Regular,Noto Sans Regular/35584-35839.pbf"
"Roboto Regular,Noto Sans Regular/35840-36095.pbf"
"Roboto Regular,Noto Sans Regular/36096-36351.pbf"
"Roboto Regular,Noto Sans Regular/36608-36863.pbf"
"Roboto Regular,Noto Sans Regular/36864-37119.pbf"
"Roboto Regular,Noto Sans Regular/37120-37375.pbf"
"Roboto Regular,Noto Sans Regular/37888-38143.pbf"
"Roboto Regular,Noto Sans Regular/38144-38399.pbf"
"Roboto Regular,Noto Sans Regular/38400-38655.pbf"
"Roboto Regular,Noto Sans Regular/38656-38911.pbf"
"Roboto Regular,Noto Sans Regular/38912-39167.pbf"
"Roboto Regular,Noto Sans Regular/39168-39423.pbf"
"Roboto Regular,Noto Sans Regular/39424-39679.pbf"
"Roboto Regular,Noto Sans Regular/39936-40191.pbf"
"Roboto Regular,Noto Sans Regular/40448-40703.pbf"
"Roboto Regular,Noto Sans Regular/40704-40959.pbf"
"Roboto Regular,Noto Sans Regular/45824-46079.pbf"
"Roboto Regular,Noto Sans Regular/50432-50687.pbf"
"Roboto Regular,Noto Sans Regular/50688-50943.pbf"
"Roboto Regular,Noto Sans Regular/50944-51199.pbf"
"Roboto Regular,Noto Sans Regular/51200-51455.pbf"
"Roboto Regular,Noto Sans Regular/65024-65279.pbf"
"Roboto Regular,Noto Sans Regular/65280-65535.pbf"
)
# from https://gist.github.com/cdown/1163649
urldecode() {
local url_encoded="${1//+/ }"
printf '%b' "${url_encoded//%/\\x}"
urlencode() {
echo $(sed -E "s/ /%20/g" <<< """$1""")
}
for i in ${LIST[@]} ; do
OUTPUT=`urldecode "$i"`
if [ ! -f "${OUTPUT}" ] ; then
mkdir -p "`dirname "${OUTPUT}"`"
echo "Downloading glyph '${OUTPUT}'"
curl --compressed --progress-bar --output "${OUTPUT}" "https://api.maptiler.com/fonts/${i}?key=${MLN_API_KEY}"
for i in "${LIST[@]}" ; do
INPUT=$(urlencode "$i")
OUTPUT="$i"
OUTDIR=$(dirname "$OUTPUT")
if [ ! -f "$OUTPUT" ] ; then
mkdir -p "$OUTDIR"
echo "Downloading glyph '$OUTPUT' from '$INPUT'"
curl --compressed --progress-bar --output "${OUTPUT}" "https://api.maptiler.com/fonts/${INPUT}?key=${MLN_API_KEY}"
fi
done

683
platform/ios/benchmark/assets/tiles/download.sh Normal file → Executable file
View File

@@ -85,6 +85,689 @@ LIST=(
"tiles/v3/6/34/20.pbf"
"tiles/v3/6/33/20.pbf"
"tiles/v3/6/32/20.pbf"
# observed from dynamic benchmark
"tiles/v3/0/0/0.pbf"
"tiles/v3/1/0/0.pbf"
"tiles/v3/1/0/1.pbf"
"tiles/v3/1/1/0.pbf"
"tiles/v3/1/1/1.pbf"
"tiles/v3/2/0/0.pbf"
"tiles/v3/2/0/1.pbf"
"tiles/v3/2/0/2.pbf"
"tiles/v3/2/0/3.pbf"
"tiles/v3/2/1/0.pbf"
"tiles/v3/2/1/1.pbf"
"tiles/v3/2/1/2.pbf"
"tiles/v3/2/1/3.pbf"
"tiles/v3/2/2/0.pbf"
"tiles/v3/2/2/1.pbf"
"tiles/v3/2/2/2.pbf"
"tiles/v3/2/3/0.pbf"
"tiles/v3/2/3/1.pbf"
"tiles/v3/2/3/2.pbf"
"tiles/v3/3/0/2.pbf"
"tiles/v3/3/0/3.pbf"
"tiles/v3/3/0/4.pbf"
"tiles/v3/3/1/2.pbf"
"tiles/v3/3/1/3.pbf"
"tiles/v3/3/1/4.pbf"
"tiles/v3/3/1/5.pbf"
"tiles/v3/3/2/1.pbf"
"tiles/v3/3/2/2.pbf"
"tiles/v3/3/2/3.pbf"
"tiles/v3/3/2/4.pbf"
"tiles/v3/3/2/5.pbf"
"tiles/v3/3/3/1.pbf"
"tiles/v3/3/3/2.pbf"
"tiles/v3/3/3/3.pbf"
"tiles/v3/3/3/4.pbf"
"tiles/v3/3/3/5.pbf"
"tiles/v3/3/4/1.pbf"
"tiles/v3/3/4/2.pbf"
"tiles/v3/3/4/3.pbf"
"tiles/v3/3/4/4.pbf"
"tiles/v3/3/5/1.pbf"
"tiles/v3/3/5/2.pbf"
"tiles/v3/3/5/3.pbf"
"tiles/v3/3/5/4.pbf"
"tiles/v3/3/6/2.pbf"
"tiles/v3/3/6/3.pbf"
"tiles/v3/3/6/4.pbf"
"tiles/v3/3/7/2.pbf"
"tiles/v3/3/7/3.pbf"
"tiles/v3/3/7/4.pbf"
"tiles/v3/4/1/5.pbf"
"tiles/v3/4/1/6.pbf"
"tiles/v3/4/1/7.pbf"
"tiles/v3/4/10/6.pbf"
"tiles/v3/4/10/7.pbf"
"tiles/v3/4/10/8.pbf"
"tiles/v3/4/11/6.pbf"
"tiles/v3/4/11/7.pbf"
"tiles/v3/4/11/8.pbf"
"tiles/v3/4/12/5.pbf"
"tiles/v3/4/12/6.pbf"
"tiles/v3/4/12/7.pbf"
"tiles/v3/4/12/8.pbf"
"tiles/v3/4/13/5.pbf"
"tiles/v3/4/13/6.pbf"
"tiles/v3/4/13/7.pbf"
"tiles/v3/4/14/5.pbf"
"tiles/v3/4/14/6.pbf"
"tiles/v3/4/14/7.pbf"
"tiles/v3/4/2/5.pbf"
"tiles/v3/4/2/6.pbf"
"tiles/v3/4/2/7.pbf"
"tiles/v3/4/3/5.pbf"
"tiles/v3/4/3/6.pbf"
"tiles/v3/4/3/7.pbf"
"tiles/v3/4/3/8.pbf"
"tiles/v3/4/3/9.pbf"
"tiles/v3/4/4/5.pbf"
"tiles/v3/4/4/6.pbf"
"tiles/v3/4/4/7.pbf"
"tiles/v3/4/4/8.pbf"
"tiles/v3/4/4/9.pbf"
"tiles/v3/4/5/5.pbf"
"tiles/v3/4/5/6.pbf"
"tiles/v3/4/5/7.pbf"
"tiles/v3/4/5/8.pbf"
"tiles/v3/4/5/9.pbf"
"tiles/v3/4/6/4.pbf"
"tiles/v3/4/6/5.pbf"
"tiles/v3/4/6/6.pbf"
"tiles/v3/4/6/7.pbf"
"tiles/v3/4/6/8.pbf"
"tiles/v3/4/7/4.pbf"
"tiles/v3/4/7/5.pbf"
"tiles/v3/4/7/6.pbf"
"tiles/v3/4/8/3.pbf"
"tiles/v3/4/8/4.pbf"
"tiles/v3/4/8/5.pbf"
"tiles/v3/4/8/6.pbf"
"tiles/v3/4/9/3.pbf"
"tiles/v3/4/9/4.pbf"
"tiles/v3/4/9/5.pbf"
"tiles/v3/4/9/6.pbf"
"tiles/v3/5/10/15.pbf"
"tiles/v3/5/10/16.pbf"
"tiles/v3/5/10/17.pbf"
"tiles/v3/5/10/18.pbf"
"tiles/v3/5/15/10.pbf"
"tiles/v3/5/15/11.pbf"
"tiles/v3/5/15/9.pbf"
"tiles/v3/5/16/10.pbf"
"tiles/v3/5/16/11.pbf"
"tiles/v3/5/16/9.pbf"
"tiles/v3/5/17/10.pbf"
"tiles/v3/5/17/11.pbf"
"tiles/v3/5/17/8.pbf"
"tiles/v3/5/17/9.pbf"
"tiles/v3/5/18/10.pbf"
"tiles/v3/5/18/8.pbf"
"tiles/v3/5/18/9.pbf"
"tiles/v3/5/21/13.pbf"
"tiles/v3/5/21/14.pbf"
"tiles/v3/5/21/15.pbf"
"tiles/v3/5/22/13.pbf"
"tiles/v3/5/22/14.pbf"
"tiles/v3/5/22/15.pbf"
"tiles/v3/5/23/13.pbf"
"tiles/v3/5/23/14.pbf"
"tiles/v3/5/23/15.pbf"
"tiles/v3/5/25/12.pbf"
"tiles/v3/5/25/13.pbf"
"tiles/v3/5/25/14.pbf"
"tiles/v3/5/26/12.pbf"
"tiles/v3/5/26/13.pbf"
"tiles/v3/5/26/14.pbf"
"tiles/v3/5/27/12.pbf"
"tiles/v3/5/27/13.pbf"
"tiles/v3/5/27/14.pbf"
"tiles/v3/5/4/11.pbf"
"tiles/v3/5/4/12.pbf"
"tiles/v3/5/4/13.pbf"
"tiles/v3/5/5/11.pbf"
"tiles/v3/5/5/12.pbf"
"tiles/v3/5/5/13.pbf"
"tiles/v3/5/8/15.pbf"
"tiles/v3/5/8/16.pbf"
"tiles/v3/5/8/17.pbf"
"tiles/v3/5/8/18.pbf"
"tiles/v3/5/9/15.pbf"
"tiles/v3/5/9/16.pbf"
"tiles/v3/5/9/17.pbf"
"tiles/v3/5/9/18.pbf"
"tiles/v3/6/10/23.pbf"
"tiles/v3/6/10/24.pbf"
"tiles/v3/6/10/25.pbf"
"tiles/v3/6/17/23.pbf"
"tiles/v3/6/17/24.pbf"
"tiles/v3/6/17/25.pbf"
"tiles/v3/6/18/23.pbf"
"tiles/v3/6/18/24.pbf"
"tiles/v3/6/18/25.pbf"
"tiles/v3/6/18/33.pbf"
"tiles/v3/6/18/34.pbf"
"tiles/v3/6/18/35.pbf"
"tiles/v3/6/19/23.pbf"
"tiles/v3/6/19/24.pbf"
"tiles/v3/6/19/25.pbf"
"tiles/v3/6/19/33.pbf"
"tiles/v3/6/19/34.pbf"
"tiles/v3/6/19/35.pbf"
"tiles/v3/6/33/19.pbf"
"tiles/v3/6/34/19.pbf"
"tiles/v3/6/35/17.pbf"
"tiles/v3/6/35/18.pbf"
"tiles/v3/6/35/19.pbf"
"tiles/v3/6/35/20.pbf"
"tiles/v3/6/35/21.pbf"
"tiles/v3/6/35/22.pbf"
"tiles/v3/6/36/17.pbf"
"tiles/v3/6/36/18.pbf"
"tiles/v3/6/36/19.pbf"
"tiles/v3/6/37/17.pbf"
"tiles/v3/6/37/18.pbf"
"tiles/v3/6/37/19.pbf"
"tiles/v3/6/44/28.pbf"
"tiles/v3/6/44/29.pbf"
"tiles/v3/6/44/30.pbf"
"tiles/v3/6/45/28.pbf"
"tiles/v3/6/45/29.pbf"
"tiles/v3/6/45/30.pbf"
"tiles/v3/6/46/28.pbf"
"tiles/v3/6/46/29.pbf"
"tiles/v3/6/46/30.pbf"
"tiles/v3/6/52/25.pbf"
"tiles/v3/6/52/26.pbf"
"tiles/v3/6/52/27.pbf"
"tiles/v3/6/53/25.pbf"
"tiles/v3/6/53/26.pbf"
"tiles/v3/6/53/27.pbf"
"tiles/v3/6/54/25.pbf"
"tiles/v3/6/54/26.pbf"
"tiles/v3/6/54/27.pbf"
"tiles/v3/6/9/23.pbf"
"tiles/v3/6/9/24.pbf"
"tiles/v3/6/9/25.pbf"
"tiles/v3/7/106/51.pbf"
"tiles/v3/7/106/52.pbf"
"tiles/v3/7/106/53.pbf"
"tiles/v3/7/107/51.pbf"
"tiles/v3/7/107/52.pbf"
"tiles/v3/7/107/53.pbf"
"tiles/v3/7/19/48.pbf"
"tiles/v3/7/19/49.pbf"
"tiles/v3/7/19/50.pbf"
"tiles/v3/7/20/48.pbf"
"tiles/v3/7/20/49.pbf"
"tiles/v3/7/20/50.pbf"
"tiles/v3/7/21/48.pbf"
"tiles/v3/7/21/49.pbf"
"tiles/v3/7/21/50.pbf"
"tiles/v3/7/35/47.pbf"
"tiles/v3/7/35/48.pbf"
"tiles/v3/7/35/49.pbf"
"tiles/v3/7/36/47.pbf"
"tiles/v3/7/36/48.pbf"
"tiles/v3/7/36/49.pbf"
"tiles/v3/7/36/67.pbf"
"tiles/v3/7/36/68.pbf"
"tiles/v3/7/36/69.pbf"
"tiles/v3/7/37/47.pbf"
"tiles/v3/7/37/48.pbf"
"tiles/v3/7/37/49.pbf"
"tiles/v3/7/37/67.pbf"
"tiles/v3/7/37/68.pbf"
"tiles/v3/7/37/69.pbf"
"tiles/v3/7/38/67.pbf"
"tiles/v3/7/38/68.pbf"
"tiles/v3/7/38/69.pbf"
"tiles/v3/7/64/41.pbf"
"tiles/v3/7/64/42.pbf"
"tiles/v3/7/64/43.pbf"
"tiles/v3/7/65/41.pbf"
"tiles/v3/7/65/42.pbf"
"tiles/v3/7/65/43.pbf"
"tiles/v3/7/66/41.pbf"
"tiles/v3/7/66/42.pbf"
"tiles/v3/7/66/43.pbf"
"tiles/v3/7/67/41.pbf"
"tiles/v3/7/67/42.pbf"
"tiles/v3/7/67/43.pbf"
"tiles/v3/7/68/40.pbf"
"tiles/v3/7/68/41.pbf"
"tiles/v3/7/68/42.pbf"
"tiles/v3/7/68/43.pbf"
"tiles/v3/7/69/40.pbf"
"tiles/v3/7/69/41.pbf"
"tiles/v3/7/69/42.pbf"
"tiles/v3/7/69/43.pbf"
"tiles/v3/7/72/36.pbf"
"tiles/v3/7/72/37.pbf"
"tiles/v3/7/72/38.pbf"
"tiles/v3/7/73/36.pbf"
"tiles/v3/7/73/37.pbf"
"tiles/v3/7/73/38.pbf"
"tiles/v3/7/90/58.pbf"
"tiles/v3/7/90/59.pbf"
"tiles/v3/7/90/60.pbf"
"tiles/v3/7/91/58.pbf"
"tiles/v3/7/91/59.pbf"
"tiles/v3/7/91/60.pbf"
"tiles/v3/7/92/58.pbf"
"tiles/v3/7/92/59.pbf"
"tiles/v3/7/92/60.pbf"
"tiles/v3/8/130/83.pbf"
"tiles/v3/8/130/84.pbf"
"tiles/v3/8/130/85.pbf"
"tiles/v3/8/131/83.pbf"
"tiles/v3/8/131/84.pbf"
"tiles/v3/8/131/85.pbf"
"tiles/v3/8/132/83.pbf"
"tiles/v3/8/132/84.pbf"
"tiles/v3/8/132/85.pbf"
"tiles/v3/8/136/82.pbf"
"tiles/v3/8/136/83.pbf"
"tiles/v3/8/136/84.pbf"
"tiles/v3/8/137/82.pbf"
"tiles/v3/8/137/83.pbf"
"tiles/v3/8/137/84.pbf"
"tiles/v3/8/138/82.pbf"
"tiles/v3/8/138/83.pbf"
"tiles/v3/8/138/84.pbf"
"tiles/v3/8/144/73.pbf"
"tiles/v3/8/144/74.pbf"
"tiles/v3/8/144/75.pbf"
"tiles/v3/8/145/73.pbf"
"tiles/v3/8/145/74.pbf"
"tiles/v3/8/145/75.pbf"
"tiles/v3/8/146/73.pbf"
"tiles/v3/8/146/74.pbf"
"tiles/v3/8/146/75.pbf"
"tiles/v3/8/182/117.pbf"
"tiles/v3/8/182/118.pbf"
"tiles/v3/8/182/119.pbf"
"tiles/v3/8/183/117.pbf"
"tiles/v3/8/183/118.pbf"
"tiles/v3/8/183/119.pbf"
"tiles/v3/8/213/103.pbf"
"tiles/v3/8/213/104.pbf"
"tiles/v3/8/213/105.pbf"
"tiles/v3/8/214/103.pbf"
"tiles/v3/8/214/104.pbf"
"tiles/v3/8/214/105.pbf"
"tiles/v3/8/215/103.pbf"
"tiles/v3/8/215/104.pbf"
"tiles/v3/8/215/105.pbf"
"tiles/v3/8/40/97.pbf"
"tiles/v3/8/40/98.pbf"
"tiles/v3/8/40/99.pbf"
"tiles/v3/8/41/97.pbf"
"tiles/v3/8/41/98.pbf"
"tiles/v3/8/41/99.pbf"
"tiles/v3/8/72/96.pbf"
"tiles/v3/8/72/97.pbf"
"tiles/v3/8/72/98.pbf"
"tiles/v3/8/73/96.pbf"
"tiles/v3/8/73/97.pbf"
"tiles/v3/8/73/98.pbf"
"tiles/v3/8/74/136.pbf"
"tiles/v3/8/74/137.pbf"
"tiles/v3/8/74/138.pbf"
"tiles/v3/8/75/136.pbf"
"tiles/v3/8/75/137.pbf"
"tiles/v3/8/75/138.pbf"
"tiles/v3/9/145/194.pbf"
"tiles/v3/9/145/195.pbf"
"tiles/v3/9/145/196.pbf"
"tiles/v3/9/146/194.pbf"
"tiles/v3/9/146/195.pbf"
"tiles/v3/9/146/196.pbf"
"tiles/v3/9/147/194.pbf"
"tiles/v3/9/147/195.pbf"
"tiles/v3/9/147/196.pbf"
"tiles/v3/9/149/273.pbf"
"tiles/v3/9/149/274.pbf"
"tiles/v3/9/149/275.pbf"
"tiles/v3/9/150/273.pbf"
"tiles/v3/9/150/274.pbf"
"tiles/v3/9/150/275.pbf"
"tiles/v3/9/151/273.pbf"
"tiles/v3/9/151/274.pbf"
"tiles/v3/9/151/275.pbf"
"tiles/v3/9/262/167.pbf"
"tiles/v3/9/262/168.pbf"
"tiles/v3/9/262/169.pbf"
"tiles/v3/9/263/167.pbf"
"tiles/v3/9/263/168.pbf"
"tiles/v3/9/263/169.pbf"
"tiles/v3/9/274/166.pbf"
"tiles/v3/9/274/167.pbf"
"tiles/v3/9/274/168.pbf"
"tiles/v3/9/275/166.pbf"
"tiles/v3/9/275/167.pbf"
"tiles/v3/9/275/168.pbf"
"tiles/v3/9/290/147.pbf"
"tiles/v3/9/290/148.pbf"
"tiles/v3/9/290/149.pbf"
"tiles/v3/9/291/147.pbf"
"tiles/v3/9/291/148.pbf"
"tiles/v3/9/291/149.pbf"
"tiles/v3/9/292/147.pbf"
"tiles/v3/9/292/148.pbf"
"tiles/v3/9/292/149.pbf"
"tiles/v3/9/365/236.pbf"
"tiles/v3/9/365/237.pbf"
"tiles/v3/9/365/238.pbf"
"tiles/v3/9/366/236.pbf"
"tiles/v3/9/366/237.pbf"
"tiles/v3/9/366/238.pbf"
"tiles/v3/9/367/236.pbf"
"tiles/v3/9/367/237.pbf"
"tiles/v3/9/367/238.pbf"
"tiles/v3/9/428/208.pbf"
"tiles/v3/9/428/209.pbf"
"tiles/v3/9/428/210.pbf"
"tiles/v3/9/429/208.pbf"
"tiles/v3/9/429/209.pbf"
"tiles/v3/9/429/210.pbf"
"tiles/v3/9/81/196.pbf"
"tiles/v3/9/81/197.pbf"
"tiles/v3/9/81/198.pbf"
"tiles/v3/9/82/196.pbf"
"tiles/v3/9/82/197.pbf"
"tiles/v3/9/82/198.pbf"
"tiles/v3/10/163/394.pbf"
"tiles/v3/10/163/395.pbf"
"tiles/v3/10/163/396.pbf"
"tiles/v3/10/164/394.pbf"
"tiles/v3/10/164/395.pbf"
"tiles/v3/10/164/396.pbf"
"tiles/v3/10/292/390.pbf"
"tiles/v3/10/292/391.pbf"
"tiles/v3/10/292/392.pbf"
"tiles/v3/10/293/390.pbf"
"tiles/v3/10/293/391.pbf"
"tiles/v3/10/293/392.pbf"
"tiles/v3/10/300/548.pbf"
"tiles/v3/10/300/549.pbf"
"tiles/v3/10/300/550.pbf"
"tiles/v3/10/301/548.pbf"
"tiles/v3/10/301/549.pbf"
"tiles/v3/10/301/550.pbf"
"tiles/v3/10/525/335.pbf"
"tiles/v3/10/525/336.pbf"
"tiles/v3/10/525/337.pbf"
"tiles/v3/10/526/335.pbf"
"tiles/v3/10/526/336.pbf"
"tiles/v3/10/526/337.pbf"
"tiles/v3/10/549/334.pbf"
"tiles/v3/10/549/335.pbf"
"tiles/v3/10/549/336.pbf"
"tiles/v3/10/550/334.pbf"
"tiles/v3/10/550/335.pbf"
"tiles/v3/10/550/336.pbf"
"tiles/v3/10/582/295.pbf"
"tiles/v3/10/582/296.pbf"
"tiles/v3/10/582/297.pbf"
"tiles/v3/10/583/295.pbf"
"tiles/v3/10/583/296.pbf"
"tiles/v3/10/583/297.pbf"
"tiles/v3/10/731/473.pbf"
"tiles/v3/10/731/474.pbf"
"tiles/v3/10/731/475.pbf"
"tiles/v3/10/732/473.pbf"
"tiles/v3/10/732/474.pbf"
"tiles/v3/10/732/475.pbf"
"tiles/v3/10/733/473.pbf"
"tiles/v3/10/733/474.pbf"
"tiles/v3/10/733/475.pbf"
"tiles/v3/10/856/417.pbf"
"tiles/v3/10/856/418.pbf"
"tiles/v3/10/856/419.pbf"
"tiles/v3/10/857/417.pbf"
"tiles/v3/10/857/418.pbf"
"tiles/v3/10/857/419.pbf"
"tiles/v3/10/858/417.pbf"
"tiles/v3/10/858/418.pbf"
"tiles/v3/10/858/419.pbf"
"tiles/v3/11/1051/672.pbf"
"tiles/v3/11/1051/673.pbf"
"tiles/v3/11/1051/674.pbf"
"tiles/v3/11/1052/672.pbf"
"tiles/v3/11/1052/673.pbf"
"tiles/v3/11/1052/674.pbf"
"tiles/v3/11/1099/670.pbf"
"tiles/v3/11/1099/671.pbf"
"tiles/v3/11/1099/672.pbf"
"tiles/v3/11/1100/670.pbf"
"tiles/v3/11/1100/671.pbf"
"tiles/v3/11/1100/672.pbf"
"tiles/v3/11/1101/670.pbf"
"tiles/v3/11/1101/671.pbf"
"tiles/v3/11/1101/672.pbf"
"tiles/v3/11/1165/591.pbf"
"tiles/v3/11/1165/592.pbf"
"tiles/v3/11/1165/593.pbf"
"tiles/v3/11/1166/591.pbf"
"tiles/v3/11/1166/592.pbf"
"tiles/v3/11/1166/593.pbf"
"tiles/v3/11/1464/948.pbf"
"tiles/v3/11/1464/949.pbf"
"tiles/v3/11/1464/950.pbf"
"tiles/v3/11/1465/948.pbf"
"tiles/v3/11/1465/949.pbf"
"tiles/v3/11/1465/950.pbf"
"tiles/v3/11/1466/948.pbf"
"tiles/v3/11/1466/949.pbf"
"tiles/v3/11/1466/950.pbf"
"tiles/v3/11/1714/835.pbf"
"tiles/v3/11/1714/836.pbf"
"tiles/v3/11/1714/837.pbf"
"tiles/v3/11/1715/835.pbf"
"tiles/v3/11/1715/836.pbf"
"tiles/v3/11/1715/837.pbf"
"tiles/v3/11/326/790.pbf"
"tiles/v3/11/326/791.pbf"
"tiles/v3/11/326/792.pbf"
"tiles/v3/11/327/790.pbf"
"tiles/v3/11/327/791.pbf"
"tiles/v3/11/327/792.pbf"
"tiles/v3/11/328/790.pbf"
"tiles/v3/11/328/791.pbf"
"tiles/v3/11/328/792.pbf"
"tiles/v3/11/585/782.pbf"
"tiles/v3/11/585/783.pbf"
"tiles/v3/11/585/784.pbf"
"tiles/v3/11/584/782.pbf"
"tiles/v3/11/584/783.pbf"
"tiles/v3/11/584/784.pbf"
"tiles/v3/11/586/782.pbf"
"tiles/v3/11/586/783.pbf"
"tiles/v3/11/586/784.pbf"
"tiles/v3/11/601/1098.pbf"
"tiles/v3/11/601/1099.pbf"
"tiles/v3/11/601/1100.pbf"
"tiles/v3/11/602/1098.pbf"
"tiles/v3/11/602/1099.pbf"
"tiles/v3/11/602/1100.pbf"
"tiles/v3/12/1170/1565.pbf"
"tiles/v3/12/1170/1566.pbf"
"tiles/v3/12/1170/1567.pbf"
"tiles/v3/12/1171/1565.pbf"
"tiles/v3/12/1171/1566.pbf"
"tiles/v3/12/1171/1567.pbf"
"tiles/v3/12/1172/1565.pbf"
"tiles/v3/12/1172/1566.pbf"
"tiles/v3/12/1172/1567.pbf"
"tiles/v3/12/1202/2198.pbf"
"tiles/v3/12/1202/2199.pbf"
"tiles/v3/12/1202/2200.pbf"
"tiles/v3/12/1203/2198.pbf"
"tiles/v3/12/1203/2199.pbf"
"tiles/v3/12/1203/2200.pbf"
"tiles/v3/12/1204/2198.pbf"
"tiles/v3/12/1204/2199.pbf"
"tiles/v3/12/1204/2200.pbf"
"tiles/v3/12/2102/1345.pbf"
"tiles/v3/12/2102/1346.pbf"
"tiles/v3/12/2102/1347.pbf"
"tiles/v3/12/2103/1345.pbf"
"tiles/v3/12/2103/1346.pbf"
"tiles/v3/12/2103/1347.pbf"
"tiles/v3/12/2104/1345.pbf"
"tiles/v3/12/2104/1346.pbf"
"tiles/v3/12/2104/1347.pbf"
"tiles/v3/12/2199/1342.pbf"
"tiles/v3/12/2199/1343.pbf"
"tiles/v3/12/2199/1344.pbf"
"tiles/v3/12/2200/1342.pbf"
"tiles/v3/12/2200/1343.pbf"
"tiles/v3/12/2200/1344.pbf"
"tiles/v3/12/2201/1342.pbf"
"tiles/v3/12/2201/1343.pbf"
"tiles/v3/12/2201/1344.pbf"
"tiles/v3/12/2330/1184.pbf"
"tiles/v3/12/2330/1185.pbf"
"tiles/v3/12/2330/1186.pbf"
"tiles/v3/12/2331/1184.pbf"
"tiles/v3/12/2331/1185.pbf"
"tiles/v3/12/2331/1186.pbf"
"tiles/v3/12/2332/1184.pbf"
"tiles/v3/12/2332/1185.pbf"
"tiles/v3/12/2332/1186.pbf"
"tiles/v3/12/2930/1898.pbf"
"tiles/v3/12/2930/1899.pbf"
"tiles/v3/12/2930/1900.pbf"
"tiles/v3/12/2931/1898.pbf"
"tiles/v3/12/2931/1899.pbf"
"tiles/v3/12/2931/1900.pbf"
"tiles/v3/12/3429/1672.pbf"
"tiles/v3/12/3429/1673.pbf"
"tiles/v3/12/3429/1674.pbf"
"tiles/v3/12/3430/1672.pbf"
"tiles/v3/12/3430/1673.pbf"
"tiles/v3/12/3430/1674.pbf"
"tiles/v3/12/654/1582.pbf"
"tiles/v3/12/654/1583.pbf"
"tiles/v3/12/654/1584.pbf"
"tiles/v3/12/655/1582.pbf"
"tiles/v3/12/655/1583.pbf"
"tiles/v3/12/655/1584.pbf"
"tiles/v3/13/1309/3165.pbf"
"tiles/v3/13/1309/3166.pbf"
"tiles/v3/13/1309/3167.pbf"
"tiles/v3/13/1310/3165.pbf"
"tiles/v3/13/1310/3166.pbf"
"tiles/v3/13/1310/3167.pbf"
"tiles/v3/13/1311/3165.pbf"
"tiles/v3/13/1311/3166.pbf"
"tiles/v3/13/1311/3167.pbf"
"tiles/v3/13/2342/3132.pbf"
"tiles/v3/13/2342/3133.pbf"
"tiles/v3/13/2342/3134.pbf"
"tiles/v3/13/2343/3132.pbf"
"tiles/v3/13/2343/3133.pbf"
"tiles/v3/13/2343/3134.pbf"
"tiles/v3/13/2406/4397.pbf"
"tiles/v3/13/2406/4398.pbf"
"tiles/v3/13/2406/4399.pbf"
"tiles/v3/13/2407/4397.pbf"
"tiles/v3/13/2407/4398.pbf"
"tiles/v3/13/2407/4399.pbf"
"tiles/v3/13/4206/2691.pbf"
"tiles/v3/13/4206/2692.pbf"
"tiles/v3/13/4206/2693.pbf"
"tiles/v3/13/4207/2691.pbf"
"tiles/v3/13/4207/2692.pbf"
"tiles/v3/13/4207/2693.pbf"
"tiles/v3/13/4208/2691.pbf"
"tiles/v3/13/4208/2692.pbf"
"tiles/v3/13/4208/2693.pbf"
"tiles/v3/13/4400/2685.pbf"
"tiles/v3/13/4400/2686.pbf"
"tiles/v3/13/4400/2687.pbf"
"tiles/v3/13/4401/2685.pbf"
"tiles/v3/13/4401/2686.pbf"
"tiles/v3/13/4401/2687.pbf"
"tiles/v3/13/4662/2370.pbf"
"tiles/v3/13/4662/2371.pbf"
"tiles/v3/13/4662/2372.pbf"
"tiles/v3/13/4663/2370.pbf"
"tiles/v3/13/4663/2371.pbf"
"tiles/v3/13/4663/2372.pbf"
"tiles/v3/13/4664/2370.pbf"
"tiles/v3/13/4664/2371.pbf"
"tiles/v3/13/4664/2372.pbf"
"tiles/v3/13/5860/3797.pbf"
"tiles/v3/13/5860/3798.pbf"
"tiles/v3/13/5860/3799.pbf"
"tiles/v3/13/5861/3797.pbf"
"tiles/v3/13/5861/3798.pbf"
"tiles/v3/13/5861/3799.pbf"
"tiles/v3/13/5862/3797.pbf"
"tiles/v3/13/5862/3798.pbf"
"tiles/v3/13/5862/3799.pbf"
"tiles/v3/13/6859/3346.pbf"
"tiles/v3/13/6859/3347.pbf"
"tiles/v3/13/6859/3348.pbf"
"tiles/v3/13/6860/3346.pbf"
"tiles/v3/13/6860/3347.pbf"
"tiles/v3/13/6860/3348.pbf"
"tiles/v3/14/2619/6331.pbf"
"tiles/v3/14/2620/6331.pbf"
"tiles/v3/14/2621/6331.pbf"
"tiles/v3/14/4685/6266.pbf"
"tiles/v3/14/4685/6267.pbf"
"tiles/v3/14/4685/6268.pbf"
"tiles/v3/14/4686/6266.pbf"
"tiles/v3/14/4686/6267.pbf"
"tiles/v3/14/4686/6268.pbf"
"tiles/v3/14/4813/8795.pbf"
"tiles/v3/14/4813/8796.pbf"
"tiles/v3/14/4813/8797.pbf"
"tiles/v3/14/4814/8795.pbf"
"tiles/v3/14/4814/8796.pbf"
"tiles/v3/14/4814/8797.pbf"
"tiles/v3/14/8414/5383.pbf"
"tiles/v3/14/8414/5384.pbf"
"tiles/v3/14/8414/5385.pbf"
"tiles/v3/14/8415/5383.pbf"
"tiles/v3/14/8415/5384.pbf"
"tiles/v3/14/8415/5385.pbf"
"tiles/v3/14/8801/5372.pbf"
"tiles/v3/14/8801/5373.pbf"
"tiles/v3/14/8801/5374.pbf"
"tiles/v3/14/8802/5372.pbf"
"tiles/v3/14/8802/5373.pbf"
"tiles/v3/14/8802/5374.pbf"
"tiles/v3/14/9326/4741.pbf"
"tiles/v3/14/9326/4742.pbf"
"tiles/v3/14/9326/4743.pbf"
"tiles/v3/14/9327/4741.pbf"
"tiles/v3/14/9327/4742.pbf"
"tiles/v3/14/9327/4743.pbf"
"tiles/v3/14/11722/7595.pbf"
"tiles/v3/14/11722/7596.pbf"
"tiles/v3/14/11722/7597.pbf"
"tiles/v3/14/11723/7595.pbf"
"tiles/v3/14/11723/7596.pbf"
"tiles/v3/14/11723/7597.pbf"
"tiles/v3/14/11724/7595.pbf"
"tiles/v3/14/11724/7596.pbf"
"tiles/v3/14/11724/7597.pbf"
"tiles/v3/14/13719/6693.pbf"
"tiles/v3/14/13719/6694.pbf"
"tiles/v3/14/13719/6695.pbf"
"tiles/v3/14/13720/6693.pbf"
"tiles/v3/14/13720/6694.pbf"
"tiles/v3/14/13720/6695.pbf"
"tiles/v3/14/13721/6693.pbf"
"tiles/v3/14/13721/6694.pbf"
"tiles/v3/14/13721/6695.pbf"
)
for OUTPUT in ${LIST[@]} ; do

View File

@@ -14,6 +14,10 @@
#include "parser.hpp"
#include "runner.hpp"
#if MLN_RENDER_BACKEND_METAL
#include <mbgl/gfx/backend.hpp>
#endif // MLN_RENDER_BACKEND_METAL
#ifdef SHOW_ANSI_COLORS
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
@@ -159,6 +163,11 @@ int runRenderTests(int argc, char** argv, std::function<void()> testStatus) {
NetworkStatus::Set(online ? NetworkStatus::Status::Online : NetworkStatus::Status::Offline);
#if MLN_RENDER_BACKEND_METAL
printf(ANSI_COLOR_YELLOW "Using GPU Expression Evaluation" ANSI_COLOR_RESET "\n");
mbgl::gfx::Backend::setEnableGPUExpressionEval(true);
#endif // MLN_RENDER_BACKEND_METAL
const auto& manifest = runner.getManifest();
const auto& ignores = manifest.getIgnores();
const auto& testPaths = manifest.getTestPaths();

View File

@@ -0,0 +1,183 @@
#include <mbgl/gfx/gpu_expression.hpp>
#include <mbgl/renderer/paint_property_binder.hpp>
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/step.hpp>
#include <mbgl/style/expression/value.hpp>
namespace mbgl {
namespace gfx {
using namespace style::expression;
namespace {
inline GPUOutputType getOutputType(const Expression& expression) {
if (expression.getType().is<type::NumberType>()) {
return GPUOutputType::Float;
} else {
return GPUOutputType::Color;
}
}
inline GPUInterpType getInterpType(const Interpolator& interp) {
return interp.match(
[&](const ExponentialInterpolator& exp) {
return (exp.base == 1.0f) ? GPUInterpType::Linear : GPUInterpType::Exponential;
},
[&](const CubicBezierInterpolator&) { return GPUInterpType::Bezier; });
}
inline float getInterpBase(const Interpolator& interp) {
return interp.match([&](const ExponentialInterpolator& exp) { return static_cast<float>(exp.base); },
[&](const CubicBezierInterpolator&) { return 0.0f; });
}
// Produce a function for `eachStop` that extracts a single stop into the target expression
auto addStop(UniqueGPUExpression& expr, GPUOutputType outType, std::size_t& index) {
return [&, outType](double input, const Expression& output) {
if (expr) {
if (const auto result = output.evaluate(EvaluationContext{/*zoom=*/0.0f})) {
const style::expression::Value& value = *result;
expr->inputs[index] = static_cast<float>(input);
if (outType == GPUOutputType::Float) {
assert(value.is<double>());
if (value.is<double>()) {
expr->stops.floats[index++] = static_cast<float>(value.get<double>());
} else {
// Evaluation error, cancel
expr.reset();
}
} else if (outType == GPUOutputType::Color) {
assert(value.is<Color>());
if (value.is<Color>()) {
const auto& color = attributeValue(value.get<Color>());
std::copy(color.begin(), color.end(), &expr->stops.colors[2 * index++]);
} else {
// Evaluation error, cancel
expr.reset();
}
}
}
}
};
};
} // namespace
const GPUExpression GPUExpression::empty = {GPUOutputType::Float, 0};
UniqueGPUExpression GPUExpression::create(GPUOutputType type, std::uint16_t count) {
if (1 < count && count <= maxStops) {
return std::make_unique<GPUExpression>(type, count);
}
return {};
}
UniqueGPUExpression GPUExpression::create(const Expression& expression, const ZoomCurvePtr& zoomCurve, bool intZoom) {
std::size_t index = 0;
const auto outType = getOutputType(expression);
const auto options = (intZoom ? GPUOptions::IntegerZoom : GPUOptions::None);
return zoomCurve.match(
[&](const Step* step) {
if (step->getStopCount() > maxStops) {
return UniqueGPUExpression{};
}
auto expr = GPUExpression::create(outType, step->getStopCount());
expr->options = options;
expr->interpolation = GPUInterpType::Step;
step->eachStop(addStop(expr, outType, index));
return expr;
},
[&](const Interpolate* interp) {
if (interp->getStopCount() > maxStops) {
return UniqueGPUExpression{};
}
auto expr = GPUExpression::create(outType, interp->getStopCount());
expr->options = options;
expr->interpolation = getInterpType(interp->getInterpolator());
expr->interpOptions.exponential.base = getInterpBase(interp->getInterpolator());
interp->eachStop(addStop(expr, outType, index));
return expr;
},
[](std::nullptr_t) { return UniqueGPUExpression{}; });
}
float GPUExpression::evaluateFloat(const float zoom) const {
const auto index = std::distance(&inputs[0], std::upper_bound(&inputs[0], &inputs[stopCount], zoom));
if (index == 0) {
return stops.floats[0];
} else if (index == stopCount) {
return stops.floats[stopCount - 1];
}
switch (interpolation) {
case GPUInterpType::Step:
return stops.floats[index - 1];
default:
assert(false);
[[fallthrough]];
case GPUInterpType::Linear:
assert(interpOptions.exponential.base == 1.0f);
[[fallthrough]];
case GPUInterpType::Exponential: {
const Range<double> range{inputs[index - 1], inputs[index]};
const ExponentialInterpolator interpolator{interpOptions.exponential.base};
const auto t = interpolator.interpolationFactor(range, zoom);
return util::Interpolator<float>()(stops.floats[index - 1], stops.floats[index], t);
}
case GPUInterpType::Bezier:
assert(false);
return stops.floats[0];
}
}
namespace {
std::tuple<float, float> unpack_float(const float packedValue) {
const int packedIntValue = int(packedValue);
const int v0 = packedIntValue / 256;
return {static_cast<float>(v0) / 255, static_cast<float>(packedIntValue - v0 * 256) / 255};
}
std::tuple<float, float, float, float> decode_color(const float encoded[2]) {
return std::tuple_cat(unpack_float(encoded[0]), unpack_float(encoded[1]));
}
Color toColor(std::tuple<float, float, float, float> rgba) {
return {std::get<0>(rgba), std::get<1>(rgba), std::get<2>(rgba), std::get<3>(rgba)};
}
} // namespace
Color GPUExpression::getColor(std::size_t index) const {
return toColor(decode_color(&stops.colors[2 * index]));
}
Color GPUExpression::evaluateColor(const float zoom) const {
const auto index = std::distance(&inputs[0], std::upper_bound(&inputs[0], &inputs[stopCount], zoom));
if (index == 0) {
return getColor(0);
} else if (index == stopCount) {
return getColor(stopCount - 1);
}
switch (interpolation) {
case GPUInterpType::Step:
return getColor(index - 1);
default:
assert(false);
[[fallthrough]];
case GPUInterpType::Linear:
assert(interpOptions.exponential.base == 1.0f);
[[fallthrough]];
case GPUInterpType::Exponential: {
const Range<double> range{inputs[index - 1], inputs[index]};
const ExponentialInterpolator interpolator{interpOptions.exponential.base};
const auto t = interpolator.interpolationFactor(range, zoom);
return util::Interpolator<Color>()(getColor(index - 1), getColor(index), t);
break;
}
case GPUInterpType::Bezier:
assert(false);
return getColor(0);
}
}
} // namespace gfx
} // namespace mbgl

View File

@@ -57,23 +57,44 @@ RenderingStats& RenderingStats::operator+=(const RenderingStats& r) {
}
#if !defined(NDEBUG)
template <typename T>
std::ostream& optionalStatLine(std::ostream& stream, T value, std::string_view label, std::string_view sep) {
if (value) {
stream << label << " = " << value << sep;
}
return stream;
}
std::string RenderingStats::toString(std::string_view sep) const {
std::stringstream ss;
ss << "numFrames = " << numFrames << sep << "numDrawCalls = " << numDrawCalls << sep
<< "totalDrawCalls = " << totalDrawCalls << sep << "numCreatedTextures = " << numCreatedTextures << sep
<< "numActiveTextures = " << numActiveTextures << sep << "numTextureBindings = " << numTextureBindings << sep
<< "numTextureUpdates = " << numTextureUpdates << sep << "textureUpdateBytes = " << textureUpdateBytes << sep
<< "totalBuffers = " << totalBuffers << sep << "totalBufferObjs = " << totalBufferObjs << sep
<< "bufferUpdates = " << bufferUpdates << sep << "bufferObjUpdates = " << bufferObjUpdates << sep
<< "bufferUpdateBytes = " << bufferUpdateBytes << sep << "numBuffers = " << numBuffers << sep
<< "numFrameBuffers = " << numFrameBuffers << sep << "numIndexBuffers = " << numIndexBuffers << sep
<< "indexUpdateBytes = " << indexUpdateBytes << sep << "numVertexBuffers = " << numVertexBuffers << sep
<< "vertexUpdateBytes = " << vertexUpdateBytes << sep << "numUniformBuffers = " << numUniformBuffers << sep
<< "numUniformUpdates = " << numUniformUpdates << sep << "uniformUpdateBytes = " << uniformUpdateBytes << sep
<< "memTextures = " << memTextures << sep << "memBuffers = " << memBuffers << sep
<< "memIndexBuffers = " << memIndexBuffers << sep << "memVertexBuffers = " << memVertexBuffers << sep
<< "memUniformBuffers = " << memUniformBuffers << sep << "stencilClears = " << stencilClears << sep
<< "stencilUpdates = " << stencilUpdates << sep;
optionalStatLine(ss, numFrames, "numFrames", sep);
optionalStatLine(ss, numDrawCalls, "numDrawCalls", sep);
optionalStatLine(ss, totalDrawCalls, "totalDrawCalls", sep);
optionalStatLine(ss, numCreatedTextures, "numCreatedTextures", sep);
optionalStatLine(ss, numActiveTextures, "numActiveTextures", sep);
optionalStatLine(ss, numTextureBindings, "numTextureBindings", sep);
optionalStatLine(ss, numTextureUpdates, "numTextureUpdates", sep);
optionalStatLine(ss, textureUpdateBytes, "textureUpdateBytes", sep);
optionalStatLine(ss, totalBuffers, "totalBuffers", sep);
optionalStatLine(ss, totalBufferObjs, "totalBufferObjs", sep);
optionalStatLine(ss, bufferUpdates, "bufferUpdates", sep);
optionalStatLine(ss, bufferObjUpdates, "bufferObjUpdates", sep);
optionalStatLine(ss, bufferUpdateBytes, "bufferUpdateBytes", sep);
optionalStatLine(ss, numBuffers, "numBuffers", sep);
optionalStatLine(ss, numFrameBuffers, "numFrameBuffers", sep);
optionalStatLine(ss, numIndexBuffers, "numIndexBuffers", sep);
optionalStatLine(ss, indexUpdateBytes, "indexUpdateBytes", sep);
optionalStatLine(ss, numVertexBuffers, "numVertexBuffers", sep);
optionalStatLine(ss, vertexUpdateBytes, "vertexUpdateBytes", sep);
optionalStatLine(ss, numUniformBuffers, "numUniformBuffers", sep);
optionalStatLine(ss, numUniformUpdates, "numUniformUpdates", sep);
optionalStatLine(ss, uniformUpdateBytes, "uniformUpdateBytes", sep);
optionalStatLine(ss, memTextures, "memTextures", sep);
optionalStatLine(ss, memBuffers, "memBuffers", sep);
optionalStatLine(ss, memIndexBuffers, "memIndexBuffers", sep);
optionalStatLine(ss, memVertexBuffers, "memVertexBuffers", sep);
optionalStatLine(ss, memUniformBuffers, "memUniformBuffers", sep);
optionalStatLine(ss, stencilClears, "stencilClears", sep);
optionalStatLine(ss, stencilUpdates, "stencilUpdates", sep);
return ss.str();
}
#endif

View File

@@ -22,8 +22,7 @@ void logStyleDependencies(EventSeverity severity, Event event, const style::Styl
counts[0]++;
} else {
for (size_t i = 0; i < maskCount; ++i) {
const auto mask = Dependency{1u << i};
if ((deps & mask) == mask) {
if (deps & Dependency{1u << i}) {
counts[i + 1]++;
}
}
@@ -33,7 +32,9 @@ void logStyleDependencies(EventSeverity severity, Event event, const style::Styl
ss << "Style '" << style.getName() << "' has " << layers.size() << " layers:\n";
ss << " " << Dependency::None << ": " << counts[0] << "\n";
for (size_t i = 0; i < maskCount; ++i) {
ss << " " << Dependency{1u << i} << ": " << counts[i + 1] << "\n";
if (counts[i + 1]) {
ss << " " << Dependency{1u << i} << ": " << counts[i + 1] << "\n";
}
}
Log::Record(severity, event, ss.str());
}

View File

@@ -17,6 +17,7 @@ template <typename T>
class CrossFadedPropertyEvaluator {
public:
using ResultType = Faded<T>;
static constexpr bool useIntegerZoom = false;
CrossFadedPropertyEvaluator(const PropertyEvaluationParameters& parameters_, T defaultValue_)
: parameters(parameters_),

View File

@@ -9,10 +9,11 @@
namespace mbgl {
template <typename T, bool useIntegerZoom = false>
template <typename T, bool useIntegerZoom_ = false>
class DataDrivenPropertyEvaluator {
public:
using ResultType = PossiblyEvaluatedPropertyValue<T>;
static constexpr bool useIntegerZoom = useIntegerZoom_;
DataDrivenPropertyEvaluator(const PropertyEvaluationParameters& parameters_, T defaultValue_)
: parameters(parameters_),
@@ -26,7 +27,7 @@ public:
if constexpr (useIntegerZoom) { // Compiler will optimize out the unused branch.
if (!expression.isFeatureConstant() || !expression.isRuntimeConstant()) {
auto returnExpression = expression;
returnExpression.useIntegerZoom = true;
returnExpression.setUseIntegerZoom(true);
return ResultType(returnExpression);
}
return ResultType(expression.evaluate(std::floor(parameters.z)));
@@ -47,6 +48,7 @@ template <typename T>
class DataDrivenPropertyEvaluator<Faded<T>> {
public:
using ResultType = PossiblyEvaluatedPropertyValue<Faded<T>>;
static constexpr bool useIntegerZoom = false;
DataDrivenPropertyEvaluator(const PropertyEvaluationParameters& parameters_, T defaultValue_)
: parameters(parameters_),

View File

@@ -15,6 +15,8 @@ ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& i
stretchY(image.stretchY),
content(image.content) {}
namespace {
const mapbox::Bin& _packImage(mapbox::ShelfPack& pack,
const style::Image::Impl& image,
ImageAtlas& resultImage,
@@ -26,12 +28,13 @@ const mapbox::Bin& _packImage(mapbox::ShelfPack& pack,
PremultipliedImage::copy(
image.image, resultImage.image, {0, 0}, {bin.x + padding, bin.y + padding}, image.image.size);
uint32_t x = bin.x + padding;
uint32_t y = bin.y + padding;
uint32_t w = image.image.size.width;
uint32_t h = image.image.size.height;
if (imageType == ImageType::Pattern) {
const uint32_t x = bin.x + padding;
const uint32_t y = bin.y + padding;
const uint32_t w = image.image.size.width;
const uint32_t h = image.image.size.height;
// Add 1 pixel wrapped padding on each side of the image.
PremultipliedImage::copy(image.image, resultImage.image, {0, h - 1}, {x, y - 1}, {w, 1}); // T
PremultipliedImage::copy(image.image, resultImage.image, {0, 0}, {x, y + h}, {w, 1}); // B
@@ -41,8 +44,6 @@ const mapbox::Bin& _packImage(mapbox::ShelfPack& pack,
return bin;
}
namespace {
void populateImagePatches(ImagePositions& imagePositions,
const ImageManager& imageManager,
std::vector<ImagePatch>& /*out*/ patches) {

View File

@@ -10,7 +10,9 @@
namespace mbgl {
static ImageManagerObserver nullObserver;
namespace {
ImageManagerObserver nullObserver;
} // namespace
ImageManager::ImageManager() = default;

View File

@@ -23,30 +23,135 @@ namespace mbgl {
using namespace style;
using namespace shaders;
#if MLN_RENDER_BACKEND_METAL && !defined(NDEBUG)
constexpr bool diff(float actual, float expected, float e = 1.0e-6) {
return actual != expected && (expected == 0 || std::fabs((actual - expected) / expected) > e);
}
constexpr bool diff(Color actual, Color expected, float e = 1.0e-6) {
return diff(actual.r, expected.r, e) || diff(actual.g, expected.g, e) || diff(actual.b, expected.b, e) ||
diff(actual.a, expected.a, e);
}
#endif // MLN_RENDER_BACKEND_METAL
#if MLN_RENDER_BACKEND_METAL && !defined(NDEBUG)
template <typename Result>
std::optional<Result> LineLayerTweaker::gpuEvaluate(const LinePaintProperties::PossiblyEvaluated& evaluated,
const PaintParameters& parameters,
const std::size_t index) const {
if (const auto& gpu = gpuExpressions[index]) {
const float effectiveZoom = (gpu->options & gfx::GPUOptions::IntegerZoom)
? parameters.state.getIntegerZoom()
: static_cast<float>(parameters.state.getZoom());
return gpu->template evaluate<Result>(effectiveZoom);
}
return {};
}
#endif // MLN_RENDER_BACKEND_METAL
template <typename Property>
auto LineLayerTweaker::evaluate([[maybe_unused]] const PaintParameters& parameters) const {
const auto& evaluated = static_cast<const LineLayerProperties&>(*evaluatedProperties).evaluated;
#if MLN_RENDER_BACKEND_METAL && !defined(NDEBUG)
constexpr auto index = propertyIndex<Property>();
if (auto gpuValue = gpuEvaluate<typename Property::Type>(evaluated, parameters, index)) {
assert(!diff(*gpuValue, evaluated.get<Property>().constantOr(Property::defaultValue())));
return *gpuValue;
}
#endif // MLN_RENDER_BACKEND_METAL
return evaluated.get<Property>().constantOr(Property::defaultValue());
}
void LineLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParameters& parameters) {
auto& context = parameters.context;
const auto zoom = parameters.state.getZoom();
const auto& evaluated = static_cast<const LineLayerProperties&>(*evaluatedProperties).evaluated;
const auto& crossfade = static_cast<const LineLayerProperties&>(*evaluatedProperties).crossfade;
// Each property UBO is updated at most once if new evaluated properties were set
const auto zoom = static_cast<float>(parameters.state.getZoom());
const auto intZoom = parameters.state.getIntegerZoom();
#if MLN_RENDER_BACKEND_METAL
const auto getExpressionBuffer = [&]() {
const bool enableEval = gfx::Backend::getEnableGPUExpressionEval();
if (!expressionUniformBuffer || (gpuExpressionsUpdated && enableEval)) {
LineExpressionUBO exprUBO = {
/* color = */ enableEval ? gpuExpressions[propertyIndex<LineColor>()].get() : nullptr,
/* blur = */ enableEval ? gpuExpressions[propertyIndex<LineBlur>()].get() : nullptr,
/* opacity = */ enableEval ? gpuExpressions[propertyIndex<LineOpacity>()].get() : nullptr,
/* gapwidth = */ enableEval ? gpuExpressions[propertyIndex<LineGapWidth>()].get() : nullptr,
/* offset = */ enableEval ? gpuExpressions[propertyIndex<LineOffset>()].get() : nullptr,
/* width = */ enableEval ? gpuExpressions[propertyIndex<LineWidth>()].get() : nullptr,
/* floorWidth = */ enableEval ? gpuExpressions[propertyIndex<LineFloorWidth>()].get() : nullptr,
};
context.emplaceOrUpdateUniformBuffer(expressionUniformBuffer, &exprUBO);
gpuExpressionsUpdated = false;
}
return expressionUniformBuffer;
};
#endif // MLN_RENDER_BACKEND_METAL
if (!evaluatedPropsUniformBuffer || propertiesUpdated) {
const LineEvaluatedPropsUBO propsUBO = {
/*color =*/evaluated.get<LineColor>().constantOr(LineColor::defaultValue()),
/*blur =*/evaluated.get<LineBlur>().constantOr(LineBlur::defaultValue()),
/*opacity =*/evaluated.get<LineOpacity>().constantOr(LineOpacity::defaultValue()),
/*gapwidth =*/evaluated.get<LineGapWidth>().constantOr(LineGapWidth::defaultValue()),
/*offset =*/evaluated.get<LineOffset>().constantOr(LineOffset::defaultValue()),
/*width =*/evaluated.get<LineWidth>().constantOr(LineWidth::defaultValue()),
/*floorwidth =*/evaluated.get<LineFloorWidth>().constantOr(LineFloorWidth::defaultValue()),
0,
#if MLN_RENDER_BACKEND_METAL
expressionMask =
!gfx::Backend::getEnableGPUExpressionEval()
? LineExpressionMask::None
: ((gpuExpressions[propertyIndex<LineColor>()] ? LineExpressionMask::Color : LineExpressionMask::None) |
(gpuExpressions[propertyIndex<LineBlur>()] ? LineExpressionMask::Blur : LineExpressionMask::None) |
(gpuExpressions[propertyIndex<LineOpacity>()] ? LineExpressionMask::Opacity
: LineExpressionMask::None) |
(gpuExpressions[propertyIndex<LineGapWidth>()] ? LineExpressionMask::GapWidth
: LineExpressionMask::None) |
(gpuExpressions[propertyIndex<LineOffset>()] ? LineExpressionMask::Offset
: LineExpressionMask::None) |
(gpuExpressions[propertyIndex<LineWidth>()] ? LineExpressionMask::Width : LineExpressionMask::None) |
(gpuExpressions[propertyIndex<LineFloorWidth>()] ? LineExpressionMask::FloorWidth
: LineExpressionMask::None));
const LineEvaluatedPropsUBO propsUBO{
/*color =*/(expressionMask & LineExpressionMask::Color) ? LineColor::defaultValue()
: evaluate<LineColor>(parameters),
/*blur =*/
(expressionMask & LineExpressionMask::Blur) ? LineBlur::defaultValue() : evaluate<LineBlur>(parameters),
/*opacity =*/
(expressionMask & LineExpressionMask::Opacity) ? LineOpacity::defaultValue()
: evaluate<LineOpacity>(parameters),
/*gapwidth =*/
(expressionMask & LineExpressionMask::GapWidth) ? LineGapWidth::defaultValue()
: evaluate<LineGapWidth>(parameters),
/*offset =*/
(expressionMask & LineExpressionMask::Offset) ? LineOffset::defaultValue()
: evaluate<LineOffset>(parameters),
/*width =*/
(expressionMask & LineExpressionMask::Width) ? LineWidth::defaultValue() : evaluate<LineWidth>(parameters),
/*floorwidth =*/
(expressionMask & LineExpressionMask::FloorWidth) ? LineFloorWidth::defaultValue()
: evaluate<LineFloorWidth>(parameters),
expressionMask,
0};
#else
const LineEvaluatedPropsUBO propsUBO{/*color =*/evaluate<LineColor>(parameters),
/*blur =*/evaluate<LineBlur>(parameters),
/*opacity =*/evaluate<LineOpacity>(parameters),
/*gapwidth =*/evaluate<LineGapWidth>(parameters),
/*offset =*/evaluate<LineOffset>(parameters),
/*width =*/evaluate<LineWidth>(parameters),
/*floorwidth =*/evaluate<LineFloorWidth>(parameters),
LineExpressionMask::None,
0};
#endif // MLN_RENDER_BACKEND_METAL
context.emplaceOrUpdateUniformBuffer(evaluatedPropsUniformBuffer, &propsUBO);
propertiesUpdated = false;
}
auto& layerUniforms = layerGroup.mutableUniformBuffers();
layerUniforms.set(idLineEvaluatedPropsUBO, evaluatedPropsUniformBuffer);
#if MLN_RENDER_BACKEND_METAL
// GPU Expressions
layerUniforms.set(idLineExpressionUBO, getExpressionBuffer());
#endif // MLN_RENDER_BACKEND_METAL
visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) {
const auto shader = drawable.getShader();
if (!drawable.getTileID() || !shader || !checkTweakDrawable(drawable)) {
@@ -83,7 +188,6 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParameters
0,
0};
drawableUniforms.createOrUpdate(idLineDrawableUBO, &drawableUBO, context);
;
} break;
case LineType::Pattern: {
@@ -95,7 +199,7 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParameters
/*matrix =*/util::cast<float>(matrix),
/*scale =*/
{parameters.pixelRatio,
1 / tileID.pixelsToTileUnits(1, parameters.state.getIntegerZoom()),
1 / tileID.pixelsToTileUnits(1, intZoom),
crossfade.fromScale,
crossfade.toScale},
/*texsize =*/{static_cast<float>(textureSize.width), static_cast<float>(textureSize.height)},
@@ -128,12 +232,10 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParameters
const LineSDFDrawableUBO drawableUBO{
/* matrix = */ util::cast<float>(matrix),
/* patternscale_a = */
{1.0f / tileID.pixelsToTileUnits(widthA, parameters.state.getIntegerZoom()),
-posA.height / 2.0f},
{1.0f / tileID.pixelsToTileUnits(widthA, intZoom), -posA.height / 2.0f},
/* patternscale_b = */
{1.0f / tileID.pixelsToTileUnits(widthB, parameters.state.getIntegerZoom()),
-posB.height / 2.0f},
/* ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, static_cast<float>(zoom)),
{1.0f / tileID.pixelsToTileUnits(widthB, intZoom), -posB.height / 2.0f},
/* ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, zoom),
/* tex_y_a = */ posA.y,
/* tex_y_b = */ posB.y,
/* sdfgamma = */ static_cast<float>(dashPatternTexture.getSize().width) /
@@ -155,4 +257,18 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParameters
});
}
#if MLN_RENDER_BACKEND_METAL
void LineLayerTweaker::updateGPUExpressions(const Unevaluated& unevaluated, TimePoint now) {
if (gfx::Backend::getEnableGPUExpressionEval()) {
if (unevaluated.updateGPUExpressions(gpuExpressions, now)) {
gpuExpressionsUpdated = true;
// Masks also need to be updated
propertiesUpdated = true;
}
}
}
#endif // MLN_RENDER_BACKEND_METAL
} // namespace mbgl

View File

@@ -1,8 +1,13 @@
#pragma once
#include <mbgl/renderer/layer_tweaker.hpp>
#include <mbgl/style/layers/line_layer_properties.hpp>
#include <string_view>
#if MLN_RENDER_BACKEND_METAL
#include <mbgl/shaders/line_layer_ubo.hpp>
#endif // MLN_RENDER_BACKEND_METAL
#include <string>
namespace mbgl {
@@ -30,8 +35,37 @@ public:
void execute(LayerGroupBase&, const PaintParameters&) override;
#if MLN_RENDER_BACKEND_METAL
using LinePaintProperties = style::LinePaintProperties;
using Unevaluated = LinePaintProperties::Unevaluated;
void updateGPUExpressions(const Unevaluated&, TimePoint now);
template <typename T>
static constexpr std::size_t propertyIndex() {
return LinePaintProperties::Tuple<LinePaintProperties::PropertyTypes>::getIndex<T>();
}
#endif // MLN_RENDER_BACKEND_METAL
private:
template <typename Property>
auto evaluate(const PaintParameters& parameters) const;
#if MLN_RENDER_BACKEND_METAL
template <typename Result>
std::optional<Result> gpuEvaluate(const LinePaintProperties::PossiblyEvaluated&,
const PaintParameters&,
const std::size_t index) const;
#endif // MLN_RENDER_BACKEND_METAL
protected:
gfx::UniformBufferPtr evaluatedPropsUniformBuffer;
#if MLN_RENDER_BACKEND_METAL
gfx::UniformBufferPtr expressionUniformBuffer;
Unevaluated::GPUExpressions gpuExpressions;
shaders::LineExpressionMask expressionMask = shaders::LineExpressionMask::None;
bool gpuExpressionsUpdated = true;
#endif // MLN_RENDER_BACKEND_METAL
};
} // namespace mbgl

View File

@@ -53,7 +53,8 @@ void RenderBackgroundLayer::transition(const TransitionParameters& parameters) {
}
void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters& parameters) {
auto evaluated = unevaluated.evaluate(parameters);
const auto previousProperties = staticImmutableCast<BackgroundLayerProperties>(evaluatedProperties);
auto evaluated = unevaluated.evaluate(parameters, previousProperties->evaluated);
auto properties = makeMutable<BackgroundLayerProperties>(
staticImmutableCast<BackgroundLayer::Impl>(baseImpl), parameters.getCrossfadeParameters(), evaluated);

View File

@@ -71,8 +71,10 @@ void RenderCircleLayer::transition(const TransitionParameters& parameters) {
}
void RenderCircleLayer::evaluate(const PropertyEvaluationParameters& parameters) {
auto properties = makeMutable<CircleLayerProperties>(staticImmutableCast<CircleLayer::Impl>(baseImpl),
unevaluated.evaluate(parameters));
const auto previousProperties = staticImmutableCast<CircleLayerProperties>(evaluatedProperties);
auto properties = makeMutable<CircleLayerProperties>(
staticImmutableCast<CircleLayer::Impl>(baseImpl),
unevaluated.evaluate(parameters, previousProperties->evaluated));
const auto& evaluated = properties->evaluated;
passes = ((evaluated.get<style::CircleRadius>().constantOr(1) > 0 ||

View File

@@ -58,9 +58,11 @@ void RenderFillExtrusionLayer::transition(const TransitionParameters& parameters
}
void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& parameters) {
auto properties = makeMutable<FillExtrusionLayerProperties>(staticImmutableCast<FillExtrusionLayer::Impl>(baseImpl),
parameters.getCrossfadeParameters(),
unevaluated.evaluate(parameters));
const auto previousProperties = staticImmutableCast<FillExtrusionLayerProperties>(evaluatedProperties);
auto properties = makeMutable<FillExtrusionLayerProperties>(
staticImmutableCast<FillExtrusionLayer::Impl>(baseImpl),
parameters.getCrossfadeParameters(),
unevaluated.evaluate(parameters, previousProperties->evaluated));
passes = (properties->evaluated.get<style::FillExtrusionOpacity>() > 0)
? (RenderPass::Translucent | RenderPass::Pass3D)

View File

@@ -69,9 +69,10 @@ void RenderFillLayer::transition(const TransitionParameters& parameters) {
}
void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) {
const auto previousProperties = staticImmutableCast<FillLayerProperties>(evaluatedProperties);
auto properties = makeMutable<FillLayerProperties>(staticImmutableCast<FillLayer::Impl>(baseImpl),
parameters.getCrossfadeParameters(),
unevaluated.evaluate(parameters));
unevaluated.evaluate(parameters, previousProperties->evaluated));
auto& evaluated = properties->evaluated;
if (unevaluated.get<style::FillOutlineColor>().isUndefined()) {

View File

@@ -63,8 +63,10 @@ void RenderHeatmapLayer::layerChanged(const TransitionParameters& parameters,
#endif
void RenderHeatmapLayer::evaluate(const PropertyEvaluationParameters& parameters) {
auto properties = makeMutable<HeatmapLayerProperties>(staticImmutableCast<HeatmapLayer::Impl>(baseImpl),
unevaluated.evaluate(parameters));
const auto previousProperties = staticImmutableCast<HeatmapLayerProperties>(evaluatedProperties);
auto properties = makeMutable<HeatmapLayerProperties>(
staticImmutableCast<HeatmapLayer::Impl>(baseImpl),
unevaluated.evaluate(parameters, previousProperties->evaluated));
passes = (properties->evaluated.get<style::HeatmapOpacity>() > 0) ? (RenderPass::Translucent | RenderPass::Pass3D)
: RenderPass::None;

View File

@@ -77,8 +77,11 @@ void RenderHillshadeLayer::layerChanged(const TransitionParameters& parameters,
#endif
void RenderHillshadeLayer::evaluate(const PropertyEvaluationParameters& parameters) {
auto properties = makeMutable<HillshadeLayerProperties>(staticImmutableCast<HillshadeLayer::Impl>(baseImpl),
unevaluated.evaluate(parameters));
const auto previousProperties = staticImmutableCast<HillshadeLayerProperties>(evaluatedProperties);
auto properties = makeMutable<HillshadeLayerProperties>(
staticImmutableCast<HillshadeLayer::Impl>(baseImpl),
unevaluated.evaluate(parameters, previousProperties->evaluated));
passes = (properties->evaluated.get<style::HillshadeExaggeration>() > 0)
? (RenderPass::Translucent | RenderPass::Pass3D)
: RenderPass::None;

View File

@@ -64,12 +64,19 @@ RenderLineLayer::~RenderLineLayer() = default;
void RenderLineLayer::transition(const TransitionParameters& parameters) {
unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated));
updateColorRamp();
#if MLN_RENDER_BACKEND_METAL
if (auto* tweaker = static_cast<LineLayerTweaker*>(layerTweaker.get())) {
tweaker->updateGPUExpressions(unevaluated, parameters.now);
}
#endif // MLN_RENDER_BACKEND_METAL
}
void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) {
const auto previousProperties = staticImmutableCast<LineLayerProperties>(evaluatedProperties);
auto properties = makeMutable<LineLayerProperties>(staticImmutableCast<LineLayer::Impl>(baseImpl),
parameters.getCrossfadeParameters(),
unevaluated.evaluate(parameters));
unevaluated.evaluate(parameters, previousProperties->evaluated));
auto& evaluated = properties->evaluated;
passes = (evaluated.get<style::LineOpacity>().constantOr(1.0) > 0 &&
@@ -81,8 +88,11 @@ void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) {
evaluatedProperties = std::move(properties);
#if MLN_DRAWABLE_RENDERER
if (layerTweaker) {
layerTweaker->updateProperties(evaluatedProperties);
if (auto* tweaker = static_cast<LineLayerTweaker*>(layerTweaker.get())) {
tweaker->updateProperties(evaluatedProperties);
#if MLN_RENDER_BACKEND_METAL
tweaker->updateGPUExpressions(unevaluated, parameters.now);
#endif // MLN_RENDER_BACKEND_METAL
}
#endif
}
@@ -348,7 +358,7 @@ float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature,
void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
gfx::Context& context,
const TransformState& state,
const std::shared_ptr<UpdateParameters>&,
[[maybe_unused]] const std::shared_ptr<UpdateParameters>& parameters,
[[maybe_unused]] const RenderTree& renderTree,
[[maybe_unused]] UniqueChangeRequestVec& changes) {
if (!renderTiles || renderTiles->empty()) {
@@ -367,7 +377,12 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
auto* tileLayerGroup = static_cast<TileLayerGroup*>(layerGroup.get());
if (!layerTweaker) {
layerTweaker = std::make_shared<LineLayerTweaker>(getID(), evaluatedProperties);
auto tweaker = std::make_shared<LineLayerTweaker>(getID(), evaluatedProperties);
#if MLN_RENDER_BACKEND_METAL
tweaker->updateGPUExpressions(unevaluated, parameters->timePoint);
#endif // MLN_RENDER_BACKEND_METAL
layerTweaker = std::move(tweaker);
layerGroup->addLayerTweaker(layerTweaker);
}

View File

@@ -50,8 +50,11 @@ void RenderRasterLayer::transition(const TransitionParameters& parameters) {
}
void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters) {
auto properties = makeMutable<RasterLayerProperties>(staticImmutableCast<RasterLayer::Impl>(baseImpl),
unevaluated.evaluate(parameters));
const auto previousProperties = staticImmutableCast<RasterLayerProperties>(evaluatedProperties);
auto properties = makeMutable<RasterLayerProperties>(
staticImmutableCast<RasterLayer::Impl>(baseImpl),
unevaluated.evaluate(parameters, previousProperties->evaluated));
passes = properties->evaluated.get<style::RasterOpacity>() > 0 ? RenderPass::Translucent : RenderPass::None;
properties->renderPasses = mbgl::underlying_type(passes);
evaluatedProperties = std::move(properties);

View File

@@ -371,8 +371,11 @@ void RenderSymbolLayer::transition(const TransitionParameters& parameters) {
}
void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) {
auto properties = makeMutable<SymbolLayerProperties>(staticImmutableCast<SymbolLayer::Impl>(baseImpl),
unevaluated.evaluate(parameters));
const auto previousProperties = staticImmutableCast<SymbolLayerProperties>(evaluatedProperties);
auto properties = makeMutable<SymbolLayerProperties>(
staticImmutableCast<SymbolLayer::Impl>(baseImpl),
unevaluated.evaluate(parameters, previousProperties->evaluated));
auto& evaluated = properties->evaluated;
const auto& layout = impl_cast(baseImpl).layout;

View File

@@ -476,7 +476,7 @@ public:
#endif // MLN_LEGACY_RENDERER
std::tuple<float> interpolationFactor(float currentZoom) const override {
const float possiblyRoundedZoom = expression.useIntegerZoom ? std::floor(currentZoom) : currentZoom;
const float possiblyRoundedZoom = expression.getUseIntegerZoom() ? std::floor(currentZoom) : currentZoom;
return std::tuple<float>{
std::fmax(0.0f, std::fmin(1.0f, expression.interpolationFactor(zoomRange, possiblyRoundedZoom)))};

View File

@@ -34,6 +34,11 @@ public:
return value.match(std::forward<Ts>(ts)...);
}
T evaluate(float zoom) const {
return this->match([&](const T& constant_) { return constant_; },
[&](const style::PropertyExpression<T>& expression) { return expression.evaluate(zoom); });
}
template <class Feature>
T evaluate(const Feature& feature, float zoom, T defaultValue) const {
return this->match([&](const T& constant_) { return constant_; },

View File

@@ -41,6 +41,10 @@ public:
TimePoint now;
ZoomHistory zoomHistory;
Duration defaultFadeDuration;
bool zoomChanged = true;
bool layerChanged = false;
bool hasCrossfade = true;
};
} // namespace mbgl

View File

@@ -9,6 +9,7 @@ template <typename T>
class PropertyEvaluator {
public:
using ResultType = T;
static constexpr bool useIntegerZoom = false;
PropertyEvaluator(const PropertyEvaluationParameters& parameters_, T defaultValue_)
: parameters(parameters_),

View File

@@ -175,12 +175,11 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(
: TransitionOptions();
const TransitionParameters transitionParameters{updateParameters->timePoint, transitionOptions};
const auto transitionDuration = transitionOptions.duration.value_or(
isMapModeContinuous ? util::DEFAULT_TRANSITION_DURATION : Duration::zero());
const PropertyEvaluationParameters evaluationParameters{
zoomHistory,
updateParameters->timePoint,
transitionOptions.duration.value_or(isMapModeContinuous ? util::DEFAULT_TRANSITION_DURATION
: Duration::zero())};
PropertyEvaluationParameters evaluationParameters{zoomHistory, updateParameters->timePoint, transitionDuration};
evaluationParameters.zoomChanged = zoomChanged;
const TileParameters tileParameters{updateParameters->pixelRatio,
updateParameters->debugOptions,
@@ -300,13 +299,9 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(
for (RenderLayer& layer : orderedLayers) {
const std::string& id = layer.getID();
const bool layerAddedOrChanged = layerDiff.added.count(id) || layerDiff.changed.count(id);
// Only re-evaluate on change of zoom if the style has some reference to it
using Dependency = expression::Dependency;
const bool zoomChangedAndMatters = zoomChanged && !layerAddedOrChanged &&
(layer.getStyleDependencies() & Dependency::Zoom) != Dependency::None;
if (layerAddedOrChanged || zoomChangedAndMatters || layer.hasTransition() || layer.hasCrossfade()) {
evaluationParameters.layerChanged = layerAddedOrChanged;
evaluationParameters.hasCrossfade = layer.hasCrossfade();
if (layerAddedOrChanged || zoomChanged || evaluationParameters.hasCrossfade || layer.hasTransition()) {
const auto previousMask = layer.evaluatedProperties->constantsMask();
layer.evaluate(evaluationParameters);
if (previousMask != layer.evaluatedProperties->constantsMask()) {
@@ -907,8 +902,12 @@ void RenderOrchestrator::updateLayers(gfx::ShaderRegistry& shaders,
transitionOptions.duration.value_or(defDuration),
};
const auto& items = renderTree.getLayerRenderItemMap();
std::vector<std::unique_ptr<ChangeRequest>> changes;
for (const auto& item : renderTree.getLayerRenderItemMap()) {
changes.reserve(items.size() * 3);
for (const auto& item : items) {
auto& renderLayer = item.layer.get();
renderLayer.update(shaders, context, state, updateParameters, renderTree, changes);
}

View File

@@ -258,8 +258,9 @@ void Renderer::Impl::render(const RenderTree& renderTree,
/* .symbol_fade_change = */ parameters.symbolFadeChange,
/* .aspect_ratio = */ parameters.state.getSize().aspectRatio(),
/* .pixel_ratio = */ parameters.pixelRatio,
/* .pad1/2 = */ 0,
0};
/* .zoom = */ static_cast<float>(parameters.state.getZoom()),
/* .pad1 = */ 0,
};
auto& globalUniforms = context.mutableGlobalUniformBuffers();
globalUniforms.createOrUpdate(shaders::idGlobalPaintParamsUBO, &globalPaintParamsUBO, context);
#endif

View File

@@ -188,7 +188,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr
: linePropertiesUBO(properties) {}
~PolylineDrawableTweaker() override = default;
void init(gfx::Drawable&) override {};
void init(gfx::Drawable&) override {}
void execute(gfx::Drawable& drawable, const PaintParameters& parameters) override {
if (!drawable.getTileID().has_value()) {
@@ -220,6 +220,9 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr
drawableUniforms.createOrUpdate(idLineDrawableUBO, &drawableUBO, parameters.context);
drawableUniforms.createOrUpdate(idLineInterpolationUBO, &lineInterpolationUBO, parameters.context);
drawableUniforms.createOrUpdate(idLineEvaluatedPropsUBO, &linePropertiesUBO, parameters.context);
// We would need to set up `idLineExpressionUBO` if the expression mask isn't empty
assert(linePropertiesUBO.expressionMask == LineExpressionMask::None);
};
private:
@@ -244,7 +247,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr
/*offset*/ 0.f,
/*width*/ 4.f,
/*floorwidth*/ 0,
0,
LineExpressionMask::None,
0};
auto tweaker = std::make_shared<PolylineDrawableTweaker>(linePropertiesUBO);

View File

@@ -3,11 +3,12 @@
namespace mbgl {
namespace shaders {
const std::array<UniformBlockInfo, 4> ShaderSource<BuiltIn::LineShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{true, false, sizeof(GlobalPaintParamsUBO), idGlobalPaintParamsUBO},
const std::array<UniformBlockInfo, 5> ShaderSource<BuiltIn::LineShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{true, true, sizeof(GlobalPaintParamsUBO), idGlobalPaintParamsUBO},
UniformBlockInfo{true, false, sizeof(idLineDrawableUBO), idLineDrawableUBO},
UniformBlockInfo{true, false, sizeof(LineInterpolationUBO), idLineInterpolationUBO},
UniformBlockInfo{true, true, sizeof(LineEvaluatedPropsUBO), idLineEvaluatedPropsUBO},
UniformBlockInfo{true, true, sizeof(LineExpressionUBO), idLineExpressionUBO},
};
const std::array<AttributeInfo, 8> ShaderSource<BuiltIn::LineShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{lineUBOCount + 0, gfx::AttributeDataType::Short2, idLinePosNormalVertexAttribute},
@@ -22,7 +23,7 @@ const std::array<AttributeInfo, 8> ShaderSource<BuiltIn::LineShader, gfx::Backen
const std::array<TextureInfo, 0> ShaderSource<BuiltIn::LineShader, gfx::Backend::Type::Metal>::textures = {};
const std::array<UniformBlockInfo, 4> ShaderSource<BuiltIn::LineGradientShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{true, false, sizeof(GlobalPaintParamsUBO), idGlobalPaintParamsUBO},
UniformBlockInfo{true, true, sizeof(GlobalPaintParamsUBO), idGlobalPaintParamsUBO},
UniformBlockInfo{true, false, sizeof(LineGradientDrawableUBO), idLineDrawableUBO},
UniformBlockInfo{true, false, sizeof(LineGradientInterpolationUBO), idLineInterpolationUBO},
UniformBlockInfo{true, true, sizeof(LineEvaluatedPropsUBO), idLineEvaluatedPropsUBO},
@@ -40,12 +41,13 @@ const std::array<TextureInfo, 1> ShaderSource<BuiltIn::LineGradientShader, gfx::
TextureInfo{0, idLineImageTexture},
};
const std::array<UniformBlockInfo, 5> ShaderSource<BuiltIn::LinePatternShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{true, false, sizeof(GlobalPaintParamsUBO), idGlobalPaintParamsUBO},
const std::array<UniformBlockInfo, 6> ShaderSource<BuiltIn::LinePatternShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{true, true, sizeof(GlobalPaintParamsUBO), idGlobalPaintParamsUBO},
UniformBlockInfo{true, true, sizeof(LinePatternDrawableUBO), idLineDrawableUBO},
UniformBlockInfo{true, false, sizeof(LinePatternInterpolationUBO), idLineInterpolationUBO},
UniformBlockInfo{true, true, sizeof(LinePatternTilePropertiesUBO), idLineTilePropertiesUBO},
UniformBlockInfo{true, true, sizeof(LineEvaluatedPropsUBO), idLineEvaluatedPropsUBO},
UniformBlockInfo{true, true, sizeof(LineExpressionUBO), idLineExpressionUBO},
};
const std::array<AttributeInfo, 9> ShaderSource<BuiltIn::LinePatternShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{lineUBOCount + 0, gfx::AttributeDataType::Short2, idLinePosNormalVertexAttribute},
@@ -62,11 +64,12 @@ const std::array<TextureInfo, 1> ShaderSource<BuiltIn::LinePatternShader, gfx::B
TextureInfo{0, idLineImageTexture},
};
const std::array<UniformBlockInfo, 4> ShaderSource<BuiltIn::LineSDFShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{true, false, sizeof(GlobalPaintParamsUBO), idGlobalPaintParamsUBO},
const std::array<UniformBlockInfo, 5> ShaderSource<BuiltIn::LineSDFShader, gfx::Backend::Type::Metal>::uniforms = {
UniformBlockInfo{true, true, sizeof(GlobalPaintParamsUBO), idGlobalPaintParamsUBO},
UniformBlockInfo{true, true, sizeof(LineSDFDrawableUBO), idLineDrawableUBO},
UniformBlockInfo{true, false, sizeof(LineSDFInterpolationUBO), idLineInterpolationUBO},
UniformBlockInfo{true, true, sizeof(LineEvaluatedPropsUBO), idLineEvaluatedPropsUBO},
UniformBlockInfo{true, true, sizeof(LineExpressionUBO), idLineExpressionUBO},
};
const std::array<AttributeInfo, 9> ShaderSource<BuiltIn::LineSDFShader, gfx::Backend::Type::Metal>::attributes = {
AttributeInfo{lineUBOCount + 0, gfx::AttributeDataType::Short2, idLinePosNormalVertexAttribute},

View File

@@ -102,8 +102,9 @@ CoerceFunction getCoerceFunction(const type::Type& t) {
return toStringValue;
}
Dependency extraDependency(const type::Type& t) {
return t.is<type::ImageType>() ? Dependency::Image : Dependency::None;
/// `isRuntimeConstant` does not consider values coerced to `Type` image to be of `Kind` image, so we don't either.
constexpr Dependency extraDependency(const type::Type& /*t*/) {
return /*t.is<type::ImageType>() ? Dependency::Image :*/ Dependency::None;
}
} // namespace

View File

@@ -8,14 +8,17 @@ namespace mbgl {
namespace style {
namespace expression {
namespace {
/// Collators are considered feature-dependent, see `isFeatureConstant`
constexpr auto extraDependency = Dependency::Feature;
} // namespace
CollatorExpression::CollatorExpression(std::unique_ptr<Expression> caseSensitive_,
std::unique_ptr<Expression> diacriticSensitive_,
std::optional<std::unique_ptr<Expression>> locale_)
: Expression(Kind::CollatorExpression,
type::Collator,
depsOf(caseSensitive_) | depsOf(diacriticSensitive_) | depsOf(locale_) |
// Collations are treated as feature-dependent. See `style::expression::isFeatureConstant`
Dependency::Feature),
depsOf(caseSensitive_) | depsOf(diacriticSensitive_) | depsOf(locale_) | extraDependency),
caseSensitive(std::move(caseSensitive_)),
diacriticSensitive(std::move(diacriticSensitive_)),
locale(std::move(locale_)) {}

View File

@@ -17,7 +17,7 @@ std::ostream& operator<<(std::ostream& os, const Dependency deps) {
bool any = false;
const auto add = [&](Dependency dep, std::string_view name) {
if ((deps & dep) != Dependency::None) {
if (deps & dep) {
os << (any ? "|" : std::string_view{}) << name;
any = true;
}

View File

@@ -12,42 +12,46 @@ namespace mbgl {
namespace style {
namespace expression {
std::optional<variant<const Interpolate*, const Step*, ParsingError>> findZoomCurve(const expression::Expression* e) {
std::optional<variant<const Interpolate*, const Step*, ParsingError>> result;
ZoomCurveOrError findZoomCurve(const expression::Expression& e) {
ZoomCurveOrError result;
switch (e->getKind()) {
switch (e.getKind()) {
case Kind::Let: {
auto let = static_cast<const Let*>(e);
result = findZoomCurve(let->getResult());
const auto& let = static_cast<const Let&>(e);
if (const auto& child = let.getResult()) {
result = findZoomCurve(*child);
}
break;
}
case Kind::Coalesce: {
auto coalesce = static_cast<const Coalesce*>(e);
std::size_t length = coalesce->getLength();
const auto& coalesce = static_cast<const Coalesce&>(e);
const std::size_t length = coalesce.getLength();
for (std::size_t i = 0; i < length; i++) {
result = findZoomCurve(coalesce->getChild(i));
if (result) {
break;
if (const auto* child = coalesce.getChild(i)) {
result = findZoomCurve(*child);
if (result) {
break;
}
}
}
break;
}
case Kind::Interpolate: {
auto curve = static_cast<const Interpolate*>(e);
if (curve->getInput()->getKind() == Kind::CompoundExpression) {
auto z = static_cast<CompoundExpression*>(curve->getInput().get());
const auto& curve = static_cast<const Interpolate&>(e);
if (curve.getInput()->getKind() == Kind::CompoundExpression) {
const auto* z = static_cast<CompoundExpression*>(curve.getInput().get());
if (z && z->getOperator() == "zoom") {
result = {curve};
result = {&curve};
}
}
break;
}
case Kind::Step: {
auto step = static_cast<const Step*>(e);
if (step->getInput()->getKind() == Kind::CompoundExpression) {
auto z = static_cast<CompoundExpression*>(step->getInput().get());
const auto& step = static_cast<const Step&>(e);
if (step.getInput()->getKind() == Kind::CompoundExpression) {
const auto* z = static_cast<CompoundExpression*>(step.getInput().get());
if (z && z->getOperator() == "zoom") {
result = {step};
result = {&step};
}
}
break;
@@ -60,9 +64,8 @@ std::optional<variant<const Interpolate*, const Step*, ParsingError>> findZoomCu
return result;
}
e->eachChild([&](const Expression& child) {
std::optional<variant<const Interpolate*, const Step*, ParsingError>> childResult(findZoomCurve(&child));
if (childResult) {
e.eachChild([&](const Expression& child) {
if (const ZoomCurveOrError childResult = findZoomCurve(child)) {
if (childResult->is<ParsingError>()) {
result = childResult;
} else if (!result && childResult) {
@@ -79,16 +82,16 @@ std::optional<variant<const Interpolate*, const Step*, ParsingError>> findZoomCu
return result;
}
using ZoomCurveOrNull = variant<std::nullptr_t, const Interpolate*, const Step*>;
ZoomCurveOrNull findZoomCurveChecked(const expression::Expression& e) {
assert(!expression::isZoomConstant(e));
return findZoomCurve(&e)->match(
[](const ParsingError& err) -> ZoomCurveOrNull {
ZoomCurvePtr findZoomCurveChecked(const expression::Expression& e) {
if (!e.has(Dependency::Zoom)) {
return nullptr;
}
return findZoomCurve(e)->match(
[](const ParsingError& err) -> ZoomCurvePtr {
Log::Error(Event::Style, "Invalid Expression: " + err.message);
return nullptr;
},
[](auto zoomCurve) -> ZoomCurveOrNull { return zoomCurve; });
[](auto zoomCurve) -> ZoomCurvePtr { return zoomCurve; });
}
} // namespace expression

View File

@@ -248,19 +248,22 @@ ParseResult ParsingContext::parseExpression(const Convertible& value,
}
ParseResult ParsingContext::parseLayerPropertyExpression(const Convertible& value) {
std::optional<TypeAnnotationOption> typeAnnotationOption;
if (expected && *expected == type::String) {
typeAnnotationOption = TypeAnnotationOption::coerce;
}
const auto typeAnnotationOption = (expected && *expected == type::String)
? std::make_optional(TypeAnnotationOption::coerce)
: std::nullopt;
ParseResult parsed = parse(value, typeAnnotationOption);
if (parsed && !isZoomConstant(**parsed)) {
std::optional<variant<const Interpolate*, const Step*, ParsingError>> zoomCurve = findZoomCurve(parsed->get());
if (!zoomCurve) {
// If the expression is zoom-dependent, validate that we can resolve a zoom curve or treat it as an error
assert(!parsed || !*parsed || !((*parsed)->dependencies & Dependency::Zoom) == isZoomConstant(**parsed));
if (parsed && (*parsed)->has(Dependency::Zoom)) {
if (const auto zoomCurve = findZoomCurve(**parsed)) {
if (zoomCurve->is<ParsingError>()) {
error(zoomCurve->get<ParsingError>().message);
return ParseResult();
}
} else {
error(R"("zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.)");
return ParseResult();
} else if (zoomCurve->is<ParsingError>()) {
error(zoomCurve->get<ParsingError>().message);
return ParseResult();
}
}
return parsed;

View File

@@ -91,8 +91,9 @@ class LineDrawableTweaker : public gfx::DrawableTweaker {
public:
LineDrawableTweaker(const shaders::LineEvaluatedPropsUBO& properties)
: linePropertiesUBO(properties) {}
~LineDrawableTweaker() override = default;
void init(gfx::Drawable&) override {};
void init(gfx::Drawable&) override {}
void execute(gfx::Drawable& drawable, const PaintParameters& parameters) override {
if (!drawable.getTileID().has_value()) {
@@ -124,6 +125,9 @@ public:
drawableUniforms.createOrUpdate(idLineDrawableUBO, &drawableUBO, parameters.context);
drawableUniforms.createOrUpdate(idLineInterpolationUBO, &lineInterpolationUBO, parameters.context);
drawableUniforms.createOrUpdate(idLineEvaluatedPropsUBO, &linePropertiesUBO, parameters.context);
// We would need to set up `idLineExpressionUBO` if the expression mask isn't empty
assert(linePropertiesUBO.expressionMask == LineExpressionMask::None);
};
private:
@@ -135,7 +139,7 @@ public:
WideVectorDrawableTweaker(const CustomDrawableLayerHost::Interface::LineOptions& options_)
: options(options_) {}
void init(gfx::Drawable&) override {};
void init(gfx::Drawable&) override {}
void execute(gfx::Drawable& drawable, const PaintParameters& parameters) override {
if (!drawable.getTileID().has_value()) {
@@ -198,8 +202,9 @@ public:
FillDrawableTweaker(const Color& color_, float opacity_)
: color(color_),
opacity(opacity_) {}
~FillDrawableTweaker() override = default;
void init(gfx::Drawable&) override {};
void init(gfx::Drawable&) override {}
void execute(gfx::Drawable& drawable, const PaintParameters& parameters) override {
if (!drawable.getTileID().has_value()) {
@@ -244,8 +249,9 @@ class SymbolDrawableTweaker : public gfx::DrawableTweaker {
public:
SymbolDrawableTweaker(const CustomDrawableLayerHost::Interface::SymbolOptions& options_)
: options(options_) {}
~SymbolDrawableTweaker() override = default;
void init(gfx::Drawable&) override {};
void init(gfx::Drawable&) override {}
void execute(gfx::Drawable& drawable, const PaintParameters& parameters) override {
if (!drawable.getTileID().has_value()) {
@@ -536,8 +542,8 @@ void CustomDrawableLayerHost::Interface::finish() {
lineOptions.gapWidth,
lineOptions.offset,
lineOptions.width,
0,
0,
/*floorwidth=*/0,
LineExpressionMask::None,
0};
auto tweaker = std::make_shared<LineDrawableTweaker>(linePropertiesUBO);

View File

@@ -6,10 +6,13 @@
#include <mbgl/style/color_ramp_property_value.hpp>
#include <mbgl/style/conversion/stringify.hpp>
#include <mbgl/style/transition_options.hpp>
#include <mbgl/util/convert.hpp>
#include <mbgl/util/indexed_tuple.hpp>
#include <mbgl/util/ignore.hpp>
#include <mbgl/util/logging.hpp>
#include <bitset>
#include <tuple>
namespace mbgl {
@@ -65,8 +68,13 @@ public:
bool hasTransition() const noexcept { return bool(prior); }
bool isTransitioning(TimePoint now) const {
return hasTransition() && (begin <= now) && (now < end) && !value.isDataDriven();
}
bool isUndefined() const noexcept { return value.isUndefined(); }
Value& getValue() noexcept { return value; }
const Value& getValue() const noexcept { return value; }
private:
@@ -296,6 +304,24 @@ public:
return PossiblyEvaluated{evaluate<Ps>(parameters)...};
}
/// Evaluate the property if necessary, or produce a copy of the previous value if appropriate
template <class P>
auto maybeEvaluate(const PropertyEvaluationParameters& parameters,
const typename P::EvaluatorType::ResultType& oldResult) const {
using Evaluator = typename P::EvaluatorType;
const auto& property = this->template get<P>();
const bool needEvaluate = parameters.layerChanged || parameters.hasCrossfade || property.hasTransition() ||
(parameters.zoomChanged && (getDependencies(property) & Dependency::Zoom));
return needEvaluate ? property.evaluate(Evaluator(parameters, P::defaultValue()), parameters.now)
: oldResult;
}
/// Optionally evaluate each property or produce a copy of the previous value, if appropriate.
PossiblyEvaluated evaluate(const PropertyEvaluationParameters& parameters,
const PossiblyEvaluated& previous) const {
return PossiblyEvaluated{maybeEvaluate<Ps>(parameters, previous.template get<Ps>())...};
}
template <class Writer>
void stringify(Writer& writer) const {
writer.StartObject();
@@ -303,6 +329,8 @@ public:
writer.EndObject();
}
unsigned long constantsMask() const { return ConstantsMask<DataDrivenProperties>::getMask(*this); }
/// Get the combined dependencies of any contained expressions
constexpr Dependency getDependencies() const noexcept {
Dependency result = Dependency::None;
@@ -310,9 +338,20 @@ public:
return result;
}
unsigned long constantsMask() const { return ConstantsMask<DataDrivenProperties>::getMask(*this); }
#if MLN_DRAWABLE_RENDERER
using GPUExpressions = std::array<gfx::UniqueGPUExpression, UnevaluatedTypes::TypeCount>;
/// Update the GPU expressions, if applicable, for each item in the tuple.
/// @return true if any are updated (including being cleared)
bool updateGPUExpressions(Unevaluated::GPUExpressions& exprs, TimePoint now) const {
const auto results = util::to_array(std::make_tuple(updateGPUExpression<Ps>(exprs, now)...));
return std::any_of(results.begin(), results.end(), [](bool x) { return x; });
}
#endif // MLN_DRAWABLE_RENDERER
protected:
// gather dependencies for each type that can appear in this tuple
template <class P>
Dependency getDependencies(const PropertyValue<P>& v) const noexcept {
return v.getDependencies();
@@ -322,6 +361,53 @@ public:
Dependency getDependencies(const Transitioning<P>& v) const noexcept {
return v.getValue().getDependencies();
}
#if MLN_DRAWABLE_RENDERER
template <typename P>
bool updateGPUExpression(Unevaluated::GPUExpressions& exprs, TimePoint now) const {
constexpr auto index = TypeIndex<P, Ps...>::value;
constexpr bool forceIntZoom = P::EvaluatorType::useIntegerZoom;
return updateGPUExpression(exprs[index], this->template get<P>(), now, forceIntZoom);
}
template <class P>
static bool updateGPUExpression(gfx::UniqueGPUExpression& expr,
const PropertyValue<P>& val,
TimePoint /*now*/,
bool intZoom) {
if (val.isExpression() && val.asExpression().isGPUCapable()) {
if (!expr) {
expr = val.asExpression().getGPUExpression(intZoom);
return true;
}
} else if (expr) {
// Previously set and shouldn't be
expr.reset();
return true;
}
return false;
}
template <class P>
static bool updateGPUExpression(gfx::UniqueGPUExpression& expr,
const Transitioning<P>& val,
TimePoint now,
bool intZoom) {
if (val.isTransitioning(now)) {
if (expr) {
expr.reset();
return true;
}
return false;
}
return updateGPUExpression(expr, val.getValue(), now, intZoom);
}
static bool updateGPUExpression(gfx::UniqueGPUExpression&,
const style::ColorRampPropertyValue&,
TimePoint,
bool) {
return false;
}
#endif // MLN_DRAWABLE_RENDERER
};
class Transitionable : public Tuple<TransitionableTypes> {

View File

@@ -1,14 +1,84 @@
#include <mbgl/style/property_expression.hpp>
#include <mbgl/renderer/paint_property_binder.hpp>
#include <mbgl/util/convert.hpp>
#if MLN_DRAWABLE_RENDERER
#include <mbgl/gfx/gpu_expression.hpp>
#endif // MLN_DRAWABLE_RENDERER
namespace mbgl {
namespace style {
PropertyExpressionBase::PropertyExpressionBase(std::unique_ptr<expression::Expression> expression_) noexcept
namespace {
using namespace expression;
bool checkGPUCapable(const Expression& expression, const ZoomCurvePtr& zoomCurve) {
return (expression.dependencies == Dependency::Zoom) && !zoomCurve.is<std::nullptr_t>() &&
(expression.getType().is<type::NumberType>() || expression.getType().is<type::ColorType>());
}
} // namespace
PropertyExpressionBase::PropertyExpressionBase(std::unique_ptr<expression::Expression> expression_)
: expression(std::move(expression_)),
isZoomConstant_(expression::isZoomConstant(*expression)),
isFeatureConstant_(expression::isFeatureConstant(*expression)),
isRuntimeConstant_(expression::isRuntimeConstant(*expression)),
zoomCurve(isZoomConstant_ ? nullptr : expression::findZoomCurveChecked(*expression)) {}
zoomCurve(expression->has(Dependency::Zoom) ? expression::findZoomCurveChecked(*expression) : nullptr),
useIntegerZoom_(false),
isZoomConstant_(!expression->has(Dependency::Zoom)),
isFeatureConstant_(!expression->has(Dependency::Feature)),
isRuntimeConstant_(!expression->has(Dependency::Image)),
isGPUCapable_(checkGPUCapable(*expression, zoomCurve)) {
assert(isZoomConstant_ == expression::isZoomConstant(*expression));
assert(isFeatureConstant_ == expression::isFeatureConstant(*expression));
assert(isRuntimeConstant_ == expression::isRuntimeConstant(*expression));
}
PropertyExpressionBase::PropertyExpressionBase(PropertyExpressionBase&& other)
: expression(std::move(other.expression)),
zoomCurve(std::move(other.zoomCurve)),
useIntegerZoom_(other.useIntegerZoom_),
isZoomConstant_(other.isZoomConstant_),
isFeatureConstant_(other.isFeatureConstant_),
isRuntimeConstant_(other.isRuntimeConstant_),
isGPUCapable_(other.isGPUCapable_) {}
PropertyExpressionBase::PropertyExpressionBase(const PropertyExpressionBase& other)
: expression(other.expression),
zoomCurve(other.zoomCurve),
useIntegerZoom_(other.useIntegerZoom_),
isZoomConstant_(other.isZoomConstant_),
isFeatureConstant_(other.isFeatureConstant_),
isRuntimeConstant_(other.isRuntimeConstant_),
isGPUCapable_(other.isGPUCapable_) {}
PropertyExpressionBase& PropertyExpressionBase::operator=(PropertyExpressionBase&& other) {
expression = std::move(other.expression);
zoomCurve = other.zoomCurve;
useIntegerZoom_ = other.useIntegerZoom_;
isZoomConstant_ = other.isZoomConstant_;
isFeatureConstant_ = other.isFeatureConstant_;
isRuntimeConstant_ = other.isRuntimeConstant_;
isGPUCapable_ = other.isGPUCapable_;
return *this;
}
PropertyExpressionBase& PropertyExpressionBase::operator=(const PropertyExpressionBase& other) {
expression = other.expression;
zoomCurve = other.zoomCurve;
useIntegerZoom_ = other.useIntegerZoom_;
isZoomConstant_ = other.isZoomConstant_;
isFeatureConstant_ = other.isFeatureConstant_;
isRuntimeConstant_ = other.isRuntimeConstant_;
isGPUCapable_ = other.isGPUCapable_;
return *this;
}
#if MLN_DRAWABLE_RENDERER
gfx::UniqueGPUExpression PropertyExpressionBase::getGPUExpression(bool intZoom) const {
return isGPUCapable_ ? gfx::GPUExpression::create(*expression, zoomCurve, useIntegerZoom_ || intZoom)
: gfx::UniqueGPUExpression{};
}
#endif // MLN_DRAWABLE_RENDERER
float PropertyExpressionBase::interpolationFactor(const Range<float>& inputLevels,
const float inputValue) const noexcept {
return zoomCurve.match(

View File

@@ -39,7 +39,15 @@ TEST(ExpressionDependencies, Convert) {
EXPECT_EQ(Dependency::Feature, toString(number(string(get("color"))))->dependencies);
EXPECT_EQ(Dependency::Feature, boolean(string(get("color")))->dependencies);
EXPECT_EQ(Dependency::Feature, toFormatted(toColor(string(get("color"))))->dependencies);
EXPECT_EQ(Dependency::Feature | Dependency::Image, toImage(string(get("color")))->dependencies);
/// See `coercion.cpp`, `extraDependency`
EXPECT_EQ(Dependency::Feature, toImage(string(get("color")))->dependencies);
/// See `collator_expression.cpp`, `extraDependency`
EXPECT_EQ(Dependency::Feature,
createExpression(R"(["resolved-locale",["collator",{"locale": "de"}]])")->dependencies);
EXPECT_EQ(Dependency::Feature | Dependency::Zoom,
CollatorExpression(gt(literal(1.), zoom()), literal(true), literal("en-us")).dependencies);
}
TEST(ExpressionDependencies, Compare) {
@@ -78,8 +86,3 @@ TEST(ExpressionDependencies, CustomLayer) {
auto impl = makeMutable<CustomLayer::Impl>("", nullptr);
EXPECT_EQ(Dependency::None, CustomLayerProperties{std::move(impl)}.getDependencies());
}
TEST(ExpressionDependencies, Collation) {
auto collator = CollatorExpression(gt(literal(1.), zoom()), literal(true), literal("en-us"));
EXPECT_EQ(Dependency::Feature | Dependency::Zoom, collator.dependencies);
}