GPU Expressions (#2202)
This commit is contained in:
@@ -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
|
||||
|
||||
108
include/mbgl/gfx/gpu_expression.hpp
Normal file
108
include/mbgl/gfx/gpu_expression.hpp
Normal 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
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_)) {}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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_)) {}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/traits.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user