Reduce symbol buffers memory by using instancing (Core optimization) (#4383)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -289,7 +289,7 @@ protected:
|
||||
/// Stores a collection of vertex attributes by name
|
||||
class VertexAttributeArray {
|
||||
public:
|
||||
using AttributeVector = std::array<std::unique_ptr<VertexAttribute>, shaders::maxVertexAttributeCountPerShader>;
|
||||
using AttributeVector = std::array<std::unique_ptr<VertexAttribute>, shaders::maxAttributeCountPerShader>;
|
||||
VertexAttributeArray() = default;
|
||||
VertexAttributeArray(VertexAttributeArray&&);
|
||||
VertexAttributeArray(const VertexAttributeArray&) = delete; // Would need to use the virtual assignment operator
|
||||
|
||||
@@ -72,6 +72,7 @@ enum {
|
||||
|
||||
#define MLN_UBO_CONSOLIDATION (MLN_RENDER_BACKEND_METAL || MLN_RENDER_BACKEND_VULKAN || MLN_RENDER_BACKEND_WEBGPU)
|
||||
#define MLN_USE_FILL_EXTRUSION_INSTANCING (MLN_RENDER_BACKEND_METAL || MLN_RENDER_BACKEND_VULKAN)
|
||||
#define MLN_USE_SYMBOL_INSTANCING (MLN_RENDER_BACKEND_METAL || MLN_RENDER_BACKEND_VULKAN)
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mln
|
||||
|
||||
@@ -45,10 +45,17 @@ float4 decode_color(const float2 encoded) {
|
||||
return float4(unpack_float(encoded[0]) / 255, unpack_float(encoded[1]) / 255);
|
||||
}
|
||||
// Unpack a pair of paint values and interpolate between them.
|
||||
float unpack_mix_float(device const float packedValue[2], const float t) {
|
||||
return mix(packedValue[0], packedValue[1], t);
|
||||
}
|
||||
float unpack_mix_float(const float2 packedValue, const float t) {
|
||||
return mix(packedValue[0], packedValue[1], t);
|
||||
}
|
||||
// Unpack a pair of paint values and interpolate between them.
|
||||
float4 unpack_mix_color(device const float packedColors[4], const float t) {
|
||||
return mix(decode_color(float2(packedColors[0], packedColors[1])),
|
||||
decode_color(float2(packedColors[2], packedColors[3])), t);
|
||||
}
|
||||
float4 unpack_mix_color(const float4 packedColors, const float t) {
|
||||
return mix(decode_color(float2(packedColors[0], packedColors[1])),
|
||||
decode_color(float2(packedColors[2], packedColors[3])), t);
|
||||
|
||||
@@ -84,10 +84,10 @@ struct VertexStage {
|
||||
float4 color [[attribute(2)]];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_base)
|
||||
float base [[attribute(3)]];
|
||||
float2 base [[attribute(3)]];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_height)
|
||||
float height [[attribute(4)]];
|
||||
float2 height [[attribute(4)]];
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -206,10 +206,10 @@ struct VertexStage {
|
||||
float4 color [[attribute(3)]];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_base)
|
||||
float base [[attribute(4)]];
|
||||
float2 base [[attribute(4)]];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_height)
|
||||
float height [[attribute(5)]];
|
||||
float2 height [[attribute(5)]];
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -344,10 +344,10 @@ struct VertexStage {
|
||||
ushort2 decimals_ed [[attribute(1)]];
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_base)
|
||||
float base [[attribute(2)]];
|
||||
float2 base [[attribute(2)]];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_height)
|
||||
float height [[attribute(3)]];
|
||||
float2 height [[attribute(3)]];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_pattern_from)
|
||||
ushort4 pattern_from [[attribute(4)]];
|
||||
@@ -530,10 +530,10 @@ struct VertexStage {
|
||||
short2 pos [[attribute(0)]];
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_base)
|
||||
float base [[attribute(3)]];
|
||||
float2 base [[attribute(3)]];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_height)
|
||||
float height [[attribute(4)]];
|
||||
float2 height [[attribute(4)]];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_pattern_from)
|
||||
ushort4 pattern_from [[attribute(5)]];
|
||||
|
||||
@@ -81,22 +81,41 @@ struct ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::Metal> {
|
||||
static constexpr auto vertexMainFunction = "vertexMain";
|
||||
static constexpr auto fragmentMainFunction = "fragmentMain";
|
||||
|
||||
static const std::array<AttributeInfo, 6> attributes;
|
||||
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
|
||||
static const std::array<AttributeInfo, 1> attributes;
|
||||
static const std::array<AttributeInfo, 10> instanceAttributes;
|
||||
static const std::array<TextureInfo, 1> textures;
|
||||
|
||||
static constexpr auto prelude = symbolShaderPrelude;
|
||||
static constexpr auto source = R"(
|
||||
|
||||
struct VertexStage {
|
||||
float4 pos_offset [[attribute(0)]];
|
||||
float4 data [[attribute(1)]];
|
||||
float4 pixeloffset [[attribute(2)]];
|
||||
float3 projected_pos [[attribute(3)]];
|
||||
float fade_opacity [[attribute(4)]];
|
||||
float2 pos [[attribute(0)]];
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_sorted_instance)
|
||||
ushort sorted_instance [[attribute(1)]];
|
||||
#endif
|
||||
};
|
||||
|
||||
struct SymbolInstance {
|
||||
short2 pos_scale[2];
|
||||
short2 offset_tltr[2];
|
||||
short2 offset_blbr[2];
|
||||
ushort2 texture_rect[2];
|
||||
short2 pixeloffset[2];
|
||||
ushort2 size_sdf;
|
||||
};
|
||||
|
||||
struct DynamicInstance {
|
||||
float projected_pos[3];
|
||||
};
|
||||
|
||||
struct OpacityInstance {
|
||||
float fade_opacity;
|
||||
};
|
||||
|
||||
struct DataInstance {
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
float opacity [[attribute(5)]];
|
||||
float opacity[2];
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -116,18 +135,33 @@ struct FragmentStage {
|
||||
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
device const GlobalPaintParamsUBO& paintParams [[buffer(idGlobalPaintParamsUBO)]],
|
||||
device const uint32_t& uboIndex [[buffer(idGlobalUBOIndex)]],
|
||||
device const SymbolDrawableUBO* drawableVector [[buffer(idSymbolDrawableUBO)]]) {
|
||||
device const SymbolDrawableUBO* drawableVector [[buffer(idSymbolDrawableUBO)]],
|
||||
uint instanceID [[ instance_id ]],
|
||||
device const SymbolInstance* symbolInstances [[buffer(symbolUBOCount + 2)]],
|
||||
device const DynamicInstance* dynamicInstances [[buffer(symbolUBOCount + 3)]],
|
||||
device const OpacityInstance* opacityInstances [[buffer(symbolUBOCount + 4)]],
|
||||
device const DataInstance* dataInstances [[buffer(symbolUBOCount + 5)]]) {
|
||||
|
||||
#if defined(HAS_UNIFORM_u_sorted_instance)
|
||||
const uint instance = instanceID;
|
||||
#else
|
||||
const uint instance = vertx.sorted_instance;
|
||||
#endif
|
||||
|
||||
device const SymbolDrawableUBO& drawable = drawableVector[uboIndex];
|
||||
device const SymbolInstance& symbol = symbolInstances[instance];
|
||||
device const DynamicInstance& dynamic = dynamicInstances[instance];
|
||||
device const OpacityInstance& opacity = opacityInstances[instance];
|
||||
device const DataInstance& data = dataInstances[instance];
|
||||
|
||||
const float2 raw_fade_opacity = unpack_opacity(vertx.fade_opacity);
|
||||
const float2 raw_fade_opacity = unpack_opacity(opacity.fade_opacity);
|
||||
const float fade_change = raw_fade_opacity[1] > 0.5 ? paintParams.symbol_fade_change : -paintParams.symbol_fade_change;
|
||||
const float fade_opacity = max(0.0, min(1.0, raw_fade_opacity[0] + fade_change));
|
||||
|
||||
#if defined(HAS_UNIFORM_u_opacity)
|
||||
const half fo = half(fade_opacity);
|
||||
#else
|
||||
const half fo = half(unpack_mix_float(vertx.opacity, drawable.opacity_t) * fade_opacity);
|
||||
const half fo = half(unpack_mix_float(data.opacity, drawable.opacity_t) * fade_opacity);
|
||||
#endif
|
||||
|
||||
// This will check to see if the opacity is zero and push the triangle offscreen if it is
|
||||
@@ -140,17 +174,17 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
};
|
||||
}
|
||||
|
||||
const float2 a_pos = vertx.pos_offset.xy;
|
||||
const float2 a_offset = vertx.pos_offset.zw;
|
||||
const float2 a_pos = float2(symbol.pos_scale[0]);
|
||||
const float2 a_offset = float2(select(symbol.offset_tltr[uint(vertx.pos.x)], symbol.offset_blbr[uint(vertx.pos.x)], uint(vertx.pos.y)));
|
||||
|
||||
const float2 a_tex = vertx.data.xy;
|
||||
const float2 a_size = vertx.data.zw;
|
||||
const float2 a_tex = float2(symbol.texture_rect[0]) + vertx.pos * float2(symbol.texture_rect[1]);
|
||||
const float2 a_size = float2(symbol.size_sdf);
|
||||
|
||||
const float a_size_min = floor(a_size[0] * 0.5);
|
||||
const float2 a_pxoffset = vertx.pixeloffset.xy;
|
||||
const float2 a_minFontScale = vertx.pixeloffset.zw / 256.0;
|
||||
const float2 a_pxoffset = float2(symbol.pixeloffset[0]) + vertx.pos * float2(symbol.pixeloffset[1] - symbol.pixeloffset[0]);
|
||||
const float2 a_minFontScale = float2(symbol.pos_scale[1]) / 256.0;
|
||||
|
||||
const float segment_angle = -vertx.projected_pos[2];
|
||||
const float segment_angle = -dynamic.projected_pos[2];
|
||||
|
||||
float size;
|
||||
if (!drawable.is_size_zoom_constant && !drawable.is_size_feature_constant) {
|
||||
@@ -192,7 +226,7 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
const float angle_cos = cos(segment_angle + symbol_rotation);
|
||||
const float2x2 rotation_matrix = float2x2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);
|
||||
|
||||
const float4 projected_pos = drawable.label_plane_matrix * float4(vertx.projected_pos.xy, 0.0, 1.0);
|
||||
const float4 projected_pos = drawable.label_plane_matrix * float4(dynamic.projected_pos[0], dynamic.projected_pos[1], 0.0, 1.0);
|
||||
const float2 pos0 = projected_pos.xy / projected_pos.w;
|
||||
const float2 posOffset = a_offset * max(a_minFontScale, fontScale) / 32.0 + a_pxoffset / 16.0;
|
||||
const float4 position = drawable.coord_matrix * float4(pos0 + rotation_matrix * posOffset, 0.0, 1.0);
|
||||
@@ -237,34 +271,53 @@ struct ShaderSource<BuiltIn::SymbolSDFShader, gfx::Backend::Type::Metal> {
|
||||
static constexpr auto vertexMainFunction = "vertexMain";
|
||||
static constexpr auto fragmentMainFunction = "fragmentMain";
|
||||
|
||||
static const std::array<AttributeInfo, 10> attributes;
|
||||
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
|
||||
static const std::array<AttributeInfo, 1> attributes;
|
||||
static const std::array<AttributeInfo, 14> instanceAttributes;
|
||||
static const std::array<TextureInfo, 1> textures;
|
||||
|
||||
static constexpr auto prelude = symbolShaderPrelude;
|
||||
static constexpr auto source = R"(
|
||||
|
||||
struct VertexStage {
|
||||
float4 pos_offset [[attribute(0)]];
|
||||
float4 data [[attribute(1)]];
|
||||
float4 pixeloffset [[attribute(2)]];
|
||||
float3 projected_pos [[attribute(3)]];
|
||||
float fade_opacity [[attribute(4)]];
|
||||
float2 pos [[attribute(0)]];
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_sorted_instance)
|
||||
ushort sorted_instance [[attribute(1)]];
|
||||
#endif
|
||||
};
|
||||
|
||||
struct SymbolInstance {
|
||||
short2 pos_scale[2];
|
||||
short2 offset_tltr[2];
|
||||
short2 offset_blbr[2];
|
||||
ushort2 texture_rect[2];
|
||||
short2 pixeloffset[2];
|
||||
ushort2 size_sdf;
|
||||
};
|
||||
|
||||
struct DynamicInstance {
|
||||
float projected_pos[3];
|
||||
};
|
||||
|
||||
struct OpacityInstance {
|
||||
float fade_opacity;
|
||||
};
|
||||
|
||||
struct DataInstance {
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
float opacity[2];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_fill_color)
|
||||
float4 fill_color [[attribute(5)]];
|
||||
float fill_color[4];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_color)
|
||||
float4 halo_color [[attribute(6)]];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
float opacity [[attribute(7)]];
|
||||
float halo_color[4];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_width)
|
||||
float halo_width [[attribute(8)]];
|
||||
float halo_width[2];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_blur)
|
||||
float halo_blur [[attribute(9)]];
|
||||
float halo_blur[2];
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -297,11 +350,26 @@ struct FragmentStage {
|
||||
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
device const GlobalPaintParamsUBO& paintParams [[buffer(idGlobalPaintParamsUBO)]],
|
||||
device const uint32_t& uboIndex [[buffer(idGlobalUBOIndex)]],
|
||||
device const SymbolDrawableUBO* drawableVector [[buffer(idSymbolDrawableUBO)]]) {
|
||||
device const SymbolDrawableUBO* drawableVector [[buffer(idSymbolDrawableUBO)]],
|
||||
uint instanceID [[ instance_id ]],
|
||||
device const SymbolInstance* symbolInstances [[buffer(symbolUBOCount + 2)]],
|
||||
device const DynamicInstance* dynamicInstances [[buffer(symbolUBOCount + 3)]],
|
||||
device const OpacityInstance* opacityInstances [[buffer(symbolUBOCount + 4)]],
|
||||
device const DataInstance* dataInstances [[buffer(symbolUBOCount + 5)]]) {
|
||||
|
||||
#if defined(HAS_UNIFORM_u_sorted_instance)
|
||||
const uint instance = instanceID;
|
||||
#else
|
||||
const uint instance = vertx.sorted_instance;
|
||||
#endif
|
||||
|
||||
device const SymbolDrawableUBO& drawable = drawableVector[uboIndex];
|
||||
device const SymbolInstance& symbol = symbolInstances[instance];
|
||||
device const DynamicInstance& dynamic = dynamicInstances[instance];
|
||||
device const OpacityInstance& opacity = opacityInstances[instance];
|
||||
device const DataInstance& data = dataInstances[instance];
|
||||
|
||||
const float2 fade_opacity = unpack_opacity(vertx.fade_opacity);
|
||||
const float2 fade_opacity = unpack_opacity(opacity.fade_opacity);
|
||||
const float fade_change = (fade_opacity[1] > 0.5) ? paintParams.symbol_fade_change : -paintParams.symbol_fade_change;
|
||||
const half fo = half(max(0.0, min(1.0, fade_opacity[0] + fade_change)));
|
||||
|
||||
@@ -315,16 +383,16 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
};
|
||||
}
|
||||
|
||||
const float2 a_pos = vertx.pos_offset.xy;
|
||||
const float2 a_offset = vertx.pos_offset.zw;
|
||||
const float2 a_pos = float2(symbol.pos_scale[0]);
|
||||
const float2 a_offset = float2(select(symbol.offset_tltr[uint(vertx.pos.x)], symbol.offset_blbr[uint(vertx.pos.x)], uint(vertx.pos.y)));
|
||||
|
||||
const float2 a_tex = vertx.data.xy;
|
||||
const float2 a_size = vertx.data.zw;
|
||||
const float2 a_tex = float2(symbol.texture_rect[0]) + vertx.pos * float2(symbol.texture_rect[1]);
|
||||
const float2 a_size = float2(symbol.size_sdf);
|
||||
|
||||
const float a_size_min = floor(a_size[0] * 0.5);
|
||||
const float2 a_pxoffset = vertx.pixeloffset.xy;
|
||||
const float2 a_pxoffset = float2(symbol.pixeloffset[0]) + vertx.pos * float2(symbol.pixeloffset[1] - symbol.pixeloffset[0]);
|
||||
|
||||
const float segment_angle = -vertx.projected_pos[2];
|
||||
const float segment_angle = -dynamic.projected_pos[2];
|
||||
|
||||
float size;
|
||||
if (!drawable.is_size_zoom_constant && !drawable.is_size_feature_constant) {
|
||||
@@ -373,7 +441,7 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
const float angle_sin = sin(segment_angle + symbol_rotation);
|
||||
const float angle_cos = cos(segment_angle + symbol_rotation);
|
||||
const auto rotation_matrix = float2x2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);
|
||||
const float4 projected_pos = drawable.label_plane_matrix * float4(vertx.projected_pos.xy, 0.0, 1.0);
|
||||
const float4 projected_pos = drawable.label_plane_matrix * float4(dynamic.projected_pos[0], dynamic.projected_pos[1], 0.0, 1.0);
|
||||
const float2 pos_rot = a_offset / 32.0 * fontScale + a_pxoffset;
|
||||
const float2 pos0 = projected_pos.xy / projected_pos.w + rotation_matrix * pos_rot;
|
||||
const float4 position = drawable.coord_matrix * float4(pos0, 0.0, 1.0);
|
||||
@@ -381,19 +449,19 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
return {
|
||||
.position = position,
|
||||
#if !defined(HAS_UNIFORM_u_fill_color)
|
||||
.fill_color = half4(unpack_mix_color(vertx.fill_color, drawable.fill_color_t)),
|
||||
.fill_color = half4(unpack_mix_color(data.fill_color, drawable.fill_color_t)),
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_color)
|
||||
.halo_color = half4(unpack_mix_color(vertx.halo_color, drawable.halo_color_t)),
|
||||
.halo_color = half4(unpack_mix_color(data.halo_color, drawable.halo_color_t)),
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_width)
|
||||
.halo_width = half(unpack_mix_float(vertx.halo_width, drawable.halo_width_t)),
|
||||
.halo_width = half(unpack_mix_float(data.halo_width, drawable.halo_width_t)),
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_blur)
|
||||
.halo_blur = half(unpack_mix_float(vertx.halo_blur, drawable.halo_blur_t)),
|
||||
.halo_blur = half(unpack_mix_float(data.halo_blur, drawable.halo_blur_t)),
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
.opacity = half(unpack_mix_float(vertx.opacity, drawable.opacity_t)),
|
||||
.opacity = half(unpack_mix_float(data.opacity, drawable.opacity_t)),
|
||||
#endif
|
||||
.tex = half2(a_tex / drawable.texsize),
|
||||
.gamma_scale = half(position.w),
|
||||
@@ -470,8 +538,8 @@ struct ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Metal>
|
||||
static constexpr auto vertexMainFunction = "vertexMain";
|
||||
static constexpr auto fragmentMainFunction = "fragmentMain";
|
||||
|
||||
static const std::array<AttributeInfo, 9> attributes;
|
||||
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
|
||||
static const std::array<AttributeInfo, 1> attributes;
|
||||
static const std::array<AttributeInfo, 14> instanceAttributes;
|
||||
static const std::array<TextureInfo, 2> textures;
|
||||
|
||||
static constexpr auto prelude = symbolShaderPrelude;
|
||||
@@ -481,25 +549,45 @@ struct ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Metal>
|
||||
#define ICON 0.0
|
||||
|
||||
struct VertexStage {
|
||||
float4 pos_offset [[attribute(0)]];
|
||||
float4 data [[attribute(1)]];
|
||||
float3 projected_pos [[attribute(2)]];
|
||||
float fade_opacity [[attribute(3)]];
|
||||
float2 pos [[attribute(0)]];
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_sorted_instance)
|
||||
ushort sorted_instance [[attribute(1)]];
|
||||
#endif
|
||||
};
|
||||
|
||||
struct SymbolInstance {
|
||||
short2 pos_scale[2];
|
||||
short2 offset_tltr[2];
|
||||
short2 offset_blbr[2];
|
||||
ushort2 texture_rect[2];
|
||||
short2 pixeloffset[2];
|
||||
ushort2 size_sdf;
|
||||
};
|
||||
|
||||
struct DynamicInstance {
|
||||
float projected_pos[3];
|
||||
};
|
||||
|
||||
struct OpacityInstance {
|
||||
float fade_opacity;
|
||||
};
|
||||
|
||||
struct DataInstance {
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
float opacity[2];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_fill_color)
|
||||
float4 fill_color [[attribute(4)]];
|
||||
float fill_color[4];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_color)
|
||||
float4 halo_color [[attribute(5)]];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
float opacity [[attribute(6)]];
|
||||
float halo_color[4];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_width)
|
||||
float halo_width [[attribute(7)]];
|
||||
float halo_width[2];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_blur)
|
||||
float halo_blur [[attribute(8)]];
|
||||
float halo_blur[2];
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -534,11 +622,26 @@ struct FragmentStage {
|
||||
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
device const GlobalPaintParamsUBO& paintParams [[buffer(idGlobalPaintParamsUBO)]],
|
||||
device const uint32_t& uboIndex [[buffer(idGlobalUBOIndex)]],
|
||||
device const SymbolDrawableUBO* drawableVector [[buffer(idSymbolDrawableUBO)]]) {
|
||||
device const SymbolDrawableUBO* drawableVector [[buffer(idSymbolDrawableUBO)]],
|
||||
uint instanceID [[ instance_id ]],
|
||||
device const SymbolInstance* symbolInstances [[buffer(symbolUBOCount + 2)]],
|
||||
device const DynamicInstance* dynamicInstances [[buffer(symbolUBOCount + 3)]],
|
||||
device const OpacityInstance* opacityInstances [[buffer(symbolUBOCount + 4)]],
|
||||
device const DataInstance* dataInstances [[buffer(symbolUBOCount + 5)]]) {
|
||||
|
||||
#if defined(HAS_UNIFORM_u_sorted_instance)
|
||||
const uint instance = instanceID;
|
||||
#else
|
||||
const uint instance = vertx.sorted_instance;
|
||||
#endif
|
||||
|
||||
device const SymbolDrawableUBO& drawable = drawableVector[uboIndex];
|
||||
device const SymbolInstance& symbol = symbolInstances[instance];
|
||||
device const DynamicInstance& dynamic = dynamicInstances[instance];
|
||||
device const OpacityInstance& opacity = opacityInstances[instance];
|
||||
device const DataInstance& data = dataInstances[instance];
|
||||
|
||||
const float2 fade_opacity = unpack_opacity(vertx.fade_opacity);
|
||||
const float2 fade_opacity = unpack_opacity(opacity.fade_opacity);
|
||||
const float fade_change = (fade_opacity[1] > 0.5) ? paintParams.symbol_fade_change : -paintParams.symbol_fade_change;
|
||||
const half fo = half(max(0.0, min(1.0, fade_opacity[0] + fade_change)));
|
||||
|
||||
@@ -552,16 +655,16 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
};
|
||||
}
|
||||
|
||||
const float2 a_pos = vertx.pos_offset.xy;
|
||||
const float2 a_offset = vertx.pos_offset.zw;
|
||||
const float2 a_pos = float2(symbol.pos_scale[0]);
|
||||
const float2 a_offset = float2(select(symbol.offset_tltr[uint(vertx.pos.x)], symbol.offset_blbr[uint(vertx.pos.x)], uint(vertx.pos.y)));
|
||||
|
||||
const float2 a_tex = vertx.data.xy;
|
||||
const float2 a_size = vertx.data.zw;
|
||||
const float2 a_tex = float2(symbol.texture_rect[0]) + vertx.pos * float2(symbol.texture_rect[1]);
|
||||
const float2 a_size = float2(symbol.size_sdf);
|
||||
|
||||
const float a_size_min = floor(a_size[0] * 0.5);
|
||||
const float is_sdf = a_size[0] - 2.0 * a_size_min;
|
||||
|
||||
const float segment_angle = -vertx.projected_pos[2];
|
||||
const float segment_angle = -dynamic.projected_pos[2];
|
||||
|
||||
float size;
|
||||
if (!drawable.is_size_zoom_constant && !drawable.is_size_feature_constant) {
|
||||
@@ -611,7 +714,7 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
const float angle_cos = cos(segment_angle + symbol_rotation);
|
||||
const float2x2 rotation_matrix = float2x2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);
|
||||
|
||||
const float4 projected_pos = drawable.label_plane_matrix * float4(vertx.projected_pos.xy, 0.0, 1.0);
|
||||
const float4 projected_pos = drawable.label_plane_matrix * float4(dynamic.projected_pos[0], dynamic.projected_pos[1], 0.0, 1.0);
|
||||
const float2 pos_rot = a_offset / 32.0 * fontScale;
|
||||
const float2 pos0 = projected_pos.xy / projected_pos.w + rotation_matrix * pos_rot;
|
||||
const float4 position = drawable.coord_matrix * float4(pos0, 0.0, 1.0);
|
||||
@@ -627,19 +730,19 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||
.is_icon = is_icon,
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_fill_color)
|
||||
.fill_color = half(unpack_mix_color(vertx.fill_color, drawable.fill_color_t));
|
||||
.fill_color = half(unpack_mix_color(data.fill_color, drawable.fill_color_t));
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_color)
|
||||
.halo_color = half(unpack_mix_color(vertx.halo_color, drawable.halo_color_t));
|
||||
.halo_color = half(unpack_mix_color(data.halo_color, drawable.halo_color_t));
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
.opacity = half(unpack_mix_float(vertx.opacity, drawable.opacity_t));
|
||||
.opacity = half(unpack_mix_float(data.opacity, drawable.opacity_t));
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_width)
|
||||
.halo_width = half(unpack_mix_float(vertx.halo_width, drawable.halo_width_t));
|
||||
.halo_width = half(unpack_mix_float(data.halo_width, drawable.halo_width_t));
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_blur)
|
||||
.halo_blur = half(unpack_mix_float(vertx.halo_blur, drawable.halo_blur_t));
|
||||
.halo_blur = half(unpack_mix_float(data.halo_blur, drawable.halo_blur_t));
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
@@ -163,15 +163,26 @@ static constexpr uint32_t drawableSSBOStartId = std::max({static_cast<uint32_t>(
|
||||
|
||||
enum {
|
||||
#if MLN_USE_FILL_EXTRUSION_INSTANCING
|
||||
idFillExtrusionInstanced = getEnumValue(fillExtrusionLayerUBOCount, drawableSSBOStartId),
|
||||
idFillExtrusionInstancedDrawableUBO = getEnumValue(fillExtrusionLayerUBOCount, drawableSSBOStartId),
|
||||
#endif
|
||||
fillExtrusionDrawableSSBOCount
|
||||
};
|
||||
|
||||
enum {
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
idSymbolInstancedDrawableUBO = getEnumValue(symbolLayerUBOCount, drawableSSBOStartId),
|
||||
idSymbolDynamicInstancedDrawableUBO,
|
||||
idSymbolOpacityInstancedDrawableUBO,
|
||||
idSymbolDataInstancedDrawableUBO,
|
||||
#endif
|
||||
symbolDrawableSSBOCount
|
||||
};
|
||||
|
||||
// drawable UBOs
|
||||
|
||||
static constexpr uint32_t drawableUBOStartId = std::max(
|
||||
{static_cast<uint32_t>(drawableSSBOStartId), static_cast<uint32_t>(fillExtrusionDrawableSSBOCount)});
|
||||
static constexpr uint32_t drawableUBOStartId = std::max({static_cast<uint32_t>(drawableSSBOStartId),
|
||||
static_cast<uint32_t>(fillExtrusionDrawableSSBOCount),
|
||||
static_cast<uint32_t>(symbolDrawableSSBOCount)});
|
||||
|
||||
enum {
|
||||
backgroundUBOCount = getEnumValue(backgroundLayerUBOCount, drawableUBOStartId)
|
||||
@@ -521,20 +532,34 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
idSymbolPosOffsetVertexAttribute,
|
||||
idSymbolDataVertexAttribute,
|
||||
idSymbolPixelOffsetVertexAttribute,
|
||||
idSymbolProjectedPosVertexAttribute,
|
||||
idSymbolFadeOpacityVertexAttribute,
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
idSymbolPosAttribute,
|
||||
|
||||
idSymbolSortedInstanceAttribute,
|
||||
|
||||
idSymbolPosScaleAttribute,
|
||||
idSymbolOffsetTlTrAttribute,
|
||||
idSymbolOffsetBlBrAttribute,
|
||||
idSymbolTextureRectAttribute,
|
||||
idSymbolPixelOffsetAttribute,
|
||||
idSymbolSizeSdfAttribute,
|
||||
#else
|
||||
idSymbolPosOffsetAttribute,
|
||||
idSymbolDataAttribute,
|
||||
idSymbolPixelOffsetAttribute,
|
||||
#endif
|
||||
|
||||
idSymbolProjectedPosAttribute,
|
||||
idSymbolFadeOpacityAttribute,
|
||||
|
||||
// Data driven
|
||||
idSymbolOpacityVertexAttribute,
|
||||
idSymbolColorVertexAttribute,
|
||||
idSymbolHaloColorVertexAttribute,
|
||||
idSymbolHaloWidthVertexAttribute,
|
||||
idSymbolHaloBlurVertexAttribute,
|
||||
idSymbolOpacityAttribute,
|
||||
idSymbolColorAttribute,
|
||||
idSymbolHaloColorAttribute,
|
||||
idSymbolHaloWidthAttribute,
|
||||
idSymbolHaloBlurAttribute,
|
||||
|
||||
symbolVertexAttributeCount
|
||||
symbolAttributeCount
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -554,7 +579,7 @@ enum {
|
||||
wideVectorInstanceAttributeCount
|
||||
};
|
||||
|
||||
static constexpr uint32_t maxVertexAttributeCountPerShader = std::max({
|
||||
static constexpr uint32_t maxAttributeCountPerShader = std::max({
|
||||
static_cast<uint32_t>(backgroundVertexAttributeCount),
|
||||
static_cast<uint32_t>(circleVertexAttributeCount),
|
||||
static_cast<uint32_t>(clippingMaskVertexAttributeCount),
|
||||
@@ -570,7 +595,7 @@ static constexpr uint32_t maxVertexAttributeCountPerShader = std::max({
|
||||
static_cast<uint32_t>(lineVertexAttributeCount),
|
||||
static_cast<uint32_t>(locationIndicatorVertexAttributeCount),
|
||||
static_cast<uint32_t>(rasterVertexAttributeCount),
|
||||
static_cast<uint32_t>(symbolVertexAttributeCount),
|
||||
static_cast<uint32_t>(symbolAttributeCount),
|
||||
static_cast<uint32_t>(wideVectorAttributeCount),
|
||||
static_cast<uint32_t>(wideVectorInstanceAttributeCount),
|
||||
});
|
||||
|
||||
@@ -49,11 +49,19 @@ vec4 decode_color(const vec2 encodedColor) {
|
||||
}
|
||||
|
||||
// Unpack a pair of paint values and interpolate between them.
|
||||
float unpack_mix_float(const float packedValue[2], const float t) {
|
||||
return mix(packedValue[0], packedValue[1], t);
|
||||
}
|
||||
float unpack_mix_float(const vec2 packedValue, const float t) {
|
||||
return mix(packedValue[0], packedValue[1], t);
|
||||
}
|
||||
|
||||
// Unpack a pair of paint values and interpolate between them.
|
||||
vec4 unpack_mix_color(const float packedColors[4], const float t) {
|
||||
vec4 minColor = decode_color(vec2(packedColors[0], packedColors[1]));
|
||||
vec4 maxColor = decode_color(vec2(packedColors[2], packedColors[3]));
|
||||
return mix(minColor, maxColor, t);
|
||||
}
|
||||
vec4 unpack_mix_color(const vec4 packedColors, const float t) {
|
||||
vec4 minColor = decode_color(vec2(packedColors[0], packedColors[1]));
|
||||
vec4 maxColor = decode_color(vec2(packedColors[2], packedColors[3]));
|
||||
@@ -89,7 +97,7 @@ vec2 unpack_uint(uint value) {
|
||||
#define layerSSBOStartId 0
|
||||
#define layerUBOStartId 3
|
||||
#define drawableSSBOStartId 0
|
||||
#define drawableUBOStartId 1
|
||||
#define drawableUBOStartId 4
|
||||
|
||||
#define idDrawableReservedVertexOnlyUBO layerSSBOStartId
|
||||
#define idDrawableReservedFragmentOnlyUBO idDrawableReservedVertexOnlyUBO + 1
|
||||
@@ -140,7 +148,7 @@ void applySurfaceTransform() {
|
||||
#define layerSSBOStartId 0
|
||||
#define layerUBOStartId 3
|
||||
#define drawableSSBOStartId 0
|
||||
#define drawableUBOStartId 1
|
||||
#define drawableUBOStartId 4
|
||||
|
||||
#define idDrawableReservedVertexOnlyUBO layerSSBOStartId
|
||||
#define idDrawableReservedFragmentOnlyUBO idDrawableReservedVertexOnlyUBO + 1
|
||||
|
||||
@@ -8,9 +8,13 @@ namespace shaders {
|
||||
|
||||
constexpr auto symbolShaderPrelude = R"(
|
||||
|
||||
#define idSymbolDrawableUBO idDrawableReservedVertexOnlyUBO
|
||||
#define idSymbolTilePropsUBO idDrawableReservedFragmentOnlyUBO
|
||||
#define idSymbolEvaluatedPropsUBO layerUBOStartId
|
||||
#define idSymbolDrawableUBO idDrawableReservedVertexOnlyUBO
|
||||
#define idSymbolTilePropsUBO idDrawableReservedFragmentOnlyUBO
|
||||
#define idSymbolEvaluatedPropsUBO layerUBOStartId
|
||||
#define idSymbolInstancedDrawableUBO drawableSSBOStartId
|
||||
#define idSymbolDynamicInstancedDrawableUBO drawableSSBOStartId + 1
|
||||
#define idSymbolOpacityInstancedDrawableUBO drawableSSBOStartId + 2
|
||||
#define idSymbolDataInstancedDrawableUBO drawableSSBOStartId + 3
|
||||
|
||||
)";
|
||||
|
||||
@@ -18,21 +22,17 @@ template <>
|
||||
struct ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::Vulkan> {
|
||||
static constexpr const char* name = "SymbolIconShader";
|
||||
|
||||
static const std::array<AttributeInfo, 6> attributes;
|
||||
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
|
||||
static const std::array<AttributeInfo, 1> attributes;
|
||||
static const std::array<AttributeInfo, 10> instanceAttributes;
|
||||
static const std::array<TextureInfo, 1> textures;
|
||||
|
||||
static constexpr auto prelude = symbolShaderPrelude;
|
||||
static constexpr auto vertex = R"(
|
||||
|
||||
layout(location = 0) in ivec4 in_pos_offset;
|
||||
layout(location = 1) in uvec4 in_data;
|
||||
layout(location = 2) in ivec4 in_pixeloffset;
|
||||
layout(location = 3) in vec3 in_projected_pos;
|
||||
layout(location = 4) in float in_fade_opacity;
|
||||
layout(location = 0) in ivec2 in_pos;
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
layout(location = 5) in vec2 in_opacity;
|
||||
#if !defined(HAS_UNIFORM_u_sorted_instance)
|
||||
layout(location = 1) in uint in_sorted_instance;
|
||||
#endif
|
||||
|
||||
layout(push_constant) uniform Constants {
|
||||
@@ -69,23 +69,72 @@ layout(std140, set = LAYER_SET_INDEX, binding = idSymbolDrawableUBO) readonly bu
|
||||
SymbolDrawableUBO drawable_ubo[];
|
||||
} drawableVector;
|
||||
|
||||
struct SymbolInstance {
|
||||
int pos_scale[2];
|
||||
int offset_tltr[2];
|
||||
int offset_blbr[2];
|
||||
uint texture_rect[2];
|
||||
int pixeloffset[2];
|
||||
uint size_sdf;
|
||||
};
|
||||
|
||||
layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idSymbolInstancedDrawableUBO) readonly buffer SymbolInstanceDrawableUBOVector {
|
||||
SymbolInstance instance[];
|
||||
} symbolInstanceVector;
|
||||
|
||||
struct DynamicInstance {
|
||||
float projected_pos[3];
|
||||
};
|
||||
|
||||
layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idSymbolDynamicInstancedDrawableUBO) readonly buffer DynamicInstanceDrawableUBOVector {
|
||||
DynamicInstance instance[];
|
||||
} dynamicInstanceVector;
|
||||
|
||||
struct OpacityInstance {
|
||||
float fade_opacity;
|
||||
};
|
||||
|
||||
layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idSymbolOpacityInstancedDrawableUBO) readonly buffer OpacityInstanceDrawableUBOVector {
|
||||
OpacityInstance instance[];
|
||||
} opacityInstanceVector;
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
struct DataInstance {
|
||||
float opacity[2];
|
||||
};
|
||||
|
||||
layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idSymbolDataInstancedDrawableUBO) readonly buffer DataInstanceDrawableUBOVector {
|
||||
DataInstance instance[];
|
||||
} dataInstanceVector;
|
||||
#endif
|
||||
|
||||
layout(location = 0) out mediump vec2 frag_tex;
|
||||
layout(location = 1) out mediump float frag_opacity;
|
||||
|
||||
void main() {
|
||||
#if defined(HAS_UNIFORM_u_sorted_instance)
|
||||
const uint instance = gl_InstanceIndex;
|
||||
#else
|
||||
const uint instance = in_sorted_instance;
|
||||
#endif
|
||||
|
||||
const SymbolDrawableUBO drawable = drawableVector.drawable_ubo[constant.ubo_index];
|
||||
const SymbolInstance symbol = symbolInstanceVector.instance[instance];
|
||||
const DynamicInstance dynamic = dynamicInstanceVector.instance[instance];
|
||||
const OpacityInstance opacity = opacityInstanceVector.instance[instance];
|
||||
|
||||
const vec2 a_pos = in_pos_offset.xy;
|
||||
const vec2 a_offset = in_pos_offset.zw;
|
||||
const vec2 a_pos = unpack_int(symbol.pos_scale[0]);
|
||||
const vec2 offset_tb[2] = {unpack_int(symbol.offset_tltr[in_pos.x]), unpack_int(symbol.offset_blbr[in_pos.x])};
|
||||
const vec2 a_offset = offset_tb[in_pos.y];
|
||||
|
||||
const vec2 a_tex = in_data.xy;
|
||||
const vec2 a_size = in_data.zw;
|
||||
const vec2 a_tex = unpack_uint(symbol.texture_rect[0]) + in_pos * unpack_uint(symbol.texture_rect[1]);
|
||||
const vec2 a_size = unpack_uint(symbol.size_sdf);
|
||||
|
||||
const float a_size_min = floor(a_size[0] * 0.5);
|
||||
const vec2 a_pxoffset = in_pixeloffset.xy;
|
||||
const vec2 a_minFontScale = in_pixeloffset.zw / 256.0;
|
||||
const vec2 a_pxoffset = unpack_int(symbol.pixeloffset[0]) + in_pos * (unpack_int(symbol.pixeloffset[1]) - unpack_int(symbol.pixeloffset[0]));
|
||||
const vec2 a_minFontScale = unpack_int(symbol.pos_scale[1]) / 256.0;
|
||||
|
||||
const float segment_angle = -in_projected_pos[2];
|
||||
const float segment_angle = -dynamic.projected_pos[2];
|
||||
|
||||
float size;
|
||||
if (!drawable.is_size_zoom_constant && !drawable.is_size_feature_constant) {
|
||||
@@ -127,13 +176,13 @@ void main() {
|
||||
const float angle_cos = cos(segment_angle + symbol_rotation);
|
||||
const mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);
|
||||
|
||||
const vec4 projected_pos = drawable.label_plane_matrix * vec4(in_projected_pos.xy, 0.0, 1.0);
|
||||
const vec4 projected_pos = drawable.label_plane_matrix * vec4(dynamic.projected_pos[0], dynamic.projected_pos[1], 0.0, 1.0);
|
||||
const vec2 pos0 = projected_pos.xy / projected_pos.w;
|
||||
const vec2 posOffset = a_offset * max(a_minFontScale, fontScale) / 32.0 + a_pxoffset / 16.0;
|
||||
gl_Position = drawable.coord_matrix * vec4(pos0 + rotation_matrix * posOffset, 0.0, 1.0);
|
||||
applySurfaceTransform();
|
||||
|
||||
const vec2 raw_fade_opacity = unpack_opacity(in_fade_opacity);
|
||||
const vec2 raw_fade_opacity = unpack_opacity(opacity.fade_opacity);
|
||||
const float fade_change = raw_fade_opacity[1] > 0.5 ? paintParams.symbol_fade_change : -paintParams.symbol_fade_change;
|
||||
const float fade_opacity = max(0.0, min(1.0, raw_fade_opacity[0] + fade_change));
|
||||
|
||||
@@ -142,7 +191,7 @@ void main() {
|
||||
#if defined(HAS_UNIFORM_u_opacity)
|
||||
frag_opacity = fade_opacity;
|
||||
#else
|
||||
frag_opacity = unpack_mix_float(in_opacity, drawable.opacity_t) * fade_opacity;
|
||||
frag_opacity = unpack_mix_float(dataInstanceVector.instance[instance].opacity, drawable.opacity_t) * fade_opacity;
|
||||
#endif
|
||||
}
|
||||
)";
|
||||
@@ -209,37 +258,17 @@ template <>
|
||||
struct ShaderSource<BuiltIn::SymbolSDFShader, gfx::Backend::Type::Vulkan> {
|
||||
static constexpr const char* name = "SymbolSDFShader";
|
||||
|
||||
static const std::array<AttributeInfo, 10> attributes;
|
||||
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
|
||||
static const std::array<AttributeInfo, 1> attributes;
|
||||
static const std::array<AttributeInfo, 14> instanceAttributes;
|
||||
static const std::array<TextureInfo, 1> textures;
|
||||
|
||||
static constexpr auto prelude = symbolShaderPrelude;
|
||||
static constexpr auto vertex = R"(
|
||||
|
||||
layout(location = 0) in ivec4 in_pos_offset;
|
||||
layout(location = 1) in uvec4 in_data;
|
||||
layout(location = 2) in ivec4 in_pixeloffset;
|
||||
layout(location = 3) in vec3 in_projected_pos;
|
||||
layout(location = 4) in float in_fade_opacity;
|
||||
layout(location = 0) in ivec2 in_pos;
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_fill_color)
|
||||
layout(location = 5) in vec4 in_fill_color;
|
||||
#endif
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_halo_color)
|
||||
layout(location = 6) in vec4 in_halo_color;
|
||||
#endif
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
layout(location = 7) in vec2 in_opacity;
|
||||
#endif
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_halo_width)
|
||||
layout(location = 8) in vec2 in_halo_width;
|
||||
#endif
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_halo_blur)
|
||||
layout(location = 9) in vec2 in_halo_blur;
|
||||
#if !defined(HAS_UNIFORM_u_sorted_instance)
|
||||
layout(location = 1) in uint in_sorted_instance;
|
||||
#endif
|
||||
|
||||
layout(push_constant) uniform Constants {
|
||||
@@ -276,6 +305,59 @@ layout(std140, set = LAYER_SET_INDEX, binding = idSymbolDrawableUBO) readonly bu
|
||||
SymbolDrawableUBO drawable_ubo[];
|
||||
} drawableVector;
|
||||
|
||||
struct SymbolInstance {
|
||||
int pos_scale[2];
|
||||
int offset_tltr[2];
|
||||
int offset_blbr[2];
|
||||
uint texture_rect[2];
|
||||
int pixeloffset[2];
|
||||
uint size_sdf;
|
||||
};
|
||||
|
||||
layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idSymbolInstancedDrawableUBO) readonly buffer SymbolInstanceDrawableUBOVector {
|
||||
SymbolInstance instance[];
|
||||
} symbolInstanceVector;
|
||||
|
||||
struct DynamicInstance {
|
||||
float projected_pos[3];
|
||||
};
|
||||
|
||||
layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idSymbolDynamicInstancedDrawableUBO) readonly buffer DynamicInstanceDrawableUBOVector {
|
||||
DynamicInstance instance[];
|
||||
} dynamicInstanceVector;
|
||||
|
||||
struct OpacityInstance {
|
||||
float fade_opacity;
|
||||
};
|
||||
|
||||
layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idSymbolOpacityInstancedDrawableUBO) readonly buffer OpacityInstanceDrawableUBOVector {
|
||||
OpacityInstance instance[];
|
||||
} opacityInstanceVector;
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_opacity) || !defined(HAS_UNIFORM_u_fill_color) || !defined(HAS_UNIFORM_u_halo_color) || !defined(HAS_UNIFORM_u_halo_width) || !defined(HAS_UNIFORM_u_halo_blur)
|
||||
struct DataInstance {
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
float opacity[2];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_fill_color)
|
||||
float fill_color[4];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_color)
|
||||
float halo_color[4];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_width)
|
||||
float halo_width[2];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_blur)
|
||||
float halo_blur[2];
|
||||
#endif
|
||||
};
|
||||
|
||||
layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idSymbolDataInstancedDrawableUBO) readonly buffer DataInstanceDrawableUBOVector {
|
||||
DataInstance instance[];
|
||||
} dataInstanceVector;
|
||||
#endif
|
||||
|
||||
layout(location = 0) out mediump vec2 frag_tex;
|
||||
layout(location = 1) out mediump float frag_fade_opacity;
|
||||
layout(location = 2) out mediump float frag_font_scale;
|
||||
@@ -302,17 +384,27 @@ layout(location = 8) out mediump float frag_halo_blur;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
#if defined(HAS_UNIFORM_u_sorted_instance)
|
||||
const uint instance = gl_InstanceIndex;
|
||||
#else
|
||||
const uint instance = in_sorted_instance;
|
||||
#endif
|
||||
|
||||
const SymbolDrawableUBO drawable = drawableVector.drawable_ubo[constant.ubo_index];
|
||||
const SymbolInstance symbol = symbolInstanceVector.instance[instance];
|
||||
const DynamicInstance dynamic = dynamicInstanceVector.instance[instance];
|
||||
const OpacityInstance opacity = opacityInstanceVector.instance[instance];
|
||||
|
||||
const vec2 a_pos = in_pos_offset.xy;
|
||||
const vec2 a_offset = in_pos_offset.zw;
|
||||
const vec2 a_pos = unpack_int(symbol.pos_scale[0]);
|
||||
const vec2 offset_tb[2] = {unpack_int(symbol.offset_tltr[in_pos.x]), unpack_int(symbol.offset_blbr[in_pos.x])};
|
||||
const vec2 a_offset = offset_tb[in_pos.y];
|
||||
|
||||
const vec2 a_tex = in_data.xy;
|
||||
const vec2 a_size = in_data.zw;
|
||||
const vec2 a_tex = unpack_uint(symbol.texture_rect[0]) + in_pos * unpack_uint(symbol.texture_rect[1]);
|
||||
const vec2 a_size = unpack_uint(symbol.size_sdf);
|
||||
|
||||
const float a_size_min = floor(a_size[0] * 0.5);
|
||||
const vec2 a_pxoffset = in_pixeloffset.xy;
|
||||
const float segment_angle = -in_projected_pos[2];
|
||||
const vec2 a_pxoffset = unpack_int(symbol.pixeloffset[0]) + in_pos * (unpack_int(symbol.pixeloffset[1]) - unpack_int(symbol.pixeloffset[0]));
|
||||
const float segment_angle = -dynamic.projected_pos[2];
|
||||
|
||||
float size;
|
||||
if (!drawable.is_size_zoom_constant && !drawable.is_size_feature_constant) {
|
||||
@@ -361,13 +453,13 @@ void main() {
|
||||
const float angle_cos = cos(segment_angle + symbol_rotation);
|
||||
const mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);
|
||||
|
||||
const vec4 projected_pos = drawable.label_plane_matrix * vec4(in_projected_pos.xy, 0.0, 1.0);
|
||||
const vec4 projected_pos = drawable.label_plane_matrix * vec4(dynamic.projected_pos[0], dynamic.projected_pos[1], 0.0, 1.0);
|
||||
const vec2 pos_rot = a_offset / 32.0 * fontScale + a_pxoffset;
|
||||
const vec2 pos0 = projected_pos.xy / projected_pos.w + rotation_matrix * pos_rot;
|
||||
gl_Position = drawable.coord_matrix * vec4(pos0, 0.0, 1.0);
|
||||
applySurfaceTransform();
|
||||
|
||||
const vec2 raw_fade_opacity = unpack_opacity(in_fade_opacity);
|
||||
const vec2 raw_fade_opacity = unpack_opacity(opacity.fade_opacity);
|
||||
const float fade_change = raw_fade_opacity[1] > 0.5 ? paintParams.symbol_fade_change : -paintParams.symbol_fade_change;
|
||||
|
||||
frag_tex = a_tex / drawable.texsize;
|
||||
@@ -376,19 +468,19 @@ void main() {
|
||||
frag_gamma_scale = gl_Position.w;
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_fill_color)
|
||||
frag_fill_color = unpack_mix_color(in_fill_color, drawable.fill_color_t);
|
||||
frag_fill_color = unpack_mix_color(dataInstanceVector.instance[instance].fill_color, drawable.fill_color_t);
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_color)
|
||||
frag_halo_color = unpack_mix_color(in_halo_color, drawable.halo_color_t);
|
||||
frag_halo_color = unpack_mix_color(dataInstanceVector.instance[instance].halo_color, drawable.halo_color_t);
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_width)
|
||||
frag_halo_width = unpack_mix_float(in_halo_width, drawable.halo_width_t);
|
||||
frag_halo_width = unpack_mix_float(dataInstanceVector.instance[instance].halo_width, drawable.halo_width_t);
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_blur)
|
||||
frag_halo_blur = unpack_mix_float(in_halo_blur, drawable.halo_blur_t);
|
||||
frag_halo_blur = unpack_mix_float(dataInstanceVector.instance[instance].halo_blur, drawable.halo_blur_t);
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
frag_opacity = unpack_mix_float(in_opacity, drawable.opacity_t);
|
||||
frag_opacity = unpack_mix_float(dataInstanceVector.instance[instance].opacity, drawable.opacity_t);
|
||||
#endif
|
||||
}
|
||||
)";
|
||||
@@ -517,8 +609,8 @@ template <>
|
||||
struct ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Vulkan> {
|
||||
static constexpr const char* name = "SymbolTextAndIconShader";
|
||||
|
||||
static const std::array<AttributeInfo, 9> attributes;
|
||||
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
|
||||
static const std::array<AttributeInfo, 1> attributes;
|
||||
static const std::array<AttributeInfo, 14> instanceAttributes;
|
||||
static const std::array<TextureInfo, 2> textures;
|
||||
|
||||
static constexpr auto prelude = symbolShaderPrelude;
|
||||
@@ -527,29 +619,10 @@ struct ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Vulkan
|
||||
#define SDF 1.0
|
||||
#define ICON 0.0
|
||||
|
||||
layout(location = 0) in ivec4 in_pos_offset;
|
||||
layout(location = 1) in uvec4 in_data;
|
||||
layout(location = 2) in vec3 in_projected_pos;
|
||||
layout(location = 3) in float in_fade_opacity;
|
||||
layout(location = 0) in ivec2 in_pos;
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_fill_color)
|
||||
layout(location = 4) in vec4 in_fill_color;
|
||||
#endif
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_halo_color)
|
||||
layout(location = 5) in vec4 in_halo_color;
|
||||
#endif
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
layout(location = 6) in vec2 in_opacity;
|
||||
#endif
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_halo_width)
|
||||
layout(location = 7) in vec2 in_halo_width;
|
||||
#endif
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_halo_blur)
|
||||
layout(location = 8) in vec2 in_halo_blur;
|
||||
#if !defined(HAS_UNIFORM_u_sorted_instance)
|
||||
layout(location = 1) in uint in_sorted_instance;
|
||||
#endif
|
||||
|
||||
layout(push_constant) uniform Constants {
|
||||
@@ -586,6 +659,59 @@ layout(std140, set = LAYER_SET_INDEX, binding = idSymbolDrawableUBO) readonly bu
|
||||
SymbolDrawableUBO drawable_ubo[];
|
||||
} drawableVector;
|
||||
|
||||
struct SymbolInstance {
|
||||
int pos_scale[2];
|
||||
int offset_tltr[2];
|
||||
int offset_blbr[2];
|
||||
uint texture_rect[2];
|
||||
int pixeloffset[2];
|
||||
uint size_sdf;
|
||||
};
|
||||
|
||||
layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idSymbolInstancedDrawableUBO) readonly buffer SymbolInstanceDrawableUBOVector {
|
||||
SymbolInstance instance[];
|
||||
} symbolInstanceVector;
|
||||
|
||||
struct DynamicInstance {
|
||||
float projected_pos[3];
|
||||
};
|
||||
|
||||
layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idSymbolDynamicInstancedDrawableUBO) readonly buffer DynamicInstanceDrawableUBOVector {
|
||||
DynamicInstance instance[];
|
||||
} dynamicInstanceVector;
|
||||
|
||||
struct OpacityInstance {
|
||||
float fade_opacity;
|
||||
};
|
||||
|
||||
layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idSymbolOpacityInstancedDrawableUBO) readonly buffer OpacityInstanceDrawableUBOVector {
|
||||
OpacityInstance instance[];
|
||||
} opacityInstanceVector;
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_opacity) || !defined(HAS_UNIFORM_u_fill_color) || !defined(HAS_UNIFORM_u_halo_color) || !defined(HAS_UNIFORM_u_halo_width) || !defined(HAS_UNIFORM_u_halo_blur)
|
||||
struct DataInstance {
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
float opacity[2];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_fill_color)
|
||||
float fill_color[4];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_color)
|
||||
float halo_color[4];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_width)
|
||||
float halo_width[2];
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_blur)
|
||||
float halo_blur[2];
|
||||
#endif
|
||||
};
|
||||
|
||||
layout(std430, set = DRAWABLE_UBO_SET_INDEX, binding = idSymbolDataInstancedDrawableUBO) readonly buffer DataInstanceDrawableUBOVector {
|
||||
DataInstance instance[];
|
||||
} dataInstanceVector;
|
||||
#endif
|
||||
|
||||
layout(location = 0) out mediump vec2 frag_tex;
|
||||
layout(location = 1) out mediump float frag_fade_opacity;
|
||||
layout(location = 2) out mediump float frag_font_scale;
|
||||
@@ -614,17 +740,27 @@ layout(location = 8) out mediump float frag_halo_blur;
|
||||
layout(location = 9) out int frag_is_icon;
|
||||
|
||||
void main() {
|
||||
#if defined(HAS_UNIFORM_u_sorted_instance)
|
||||
const uint instance = gl_InstanceIndex;
|
||||
#else
|
||||
const uint instance = in_sorted_instance;
|
||||
#endif
|
||||
|
||||
const SymbolDrawableUBO drawable = drawableVector.drawable_ubo[constant.ubo_index];
|
||||
const SymbolInstance symbol = symbolInstanceVector.instance[instance];
|
||||
const DynamicInstance dynamic = dynamicInstanceVector.instance[instance];
|
||||
const OpacityInstance opacity = opacityInstanceVector.instance[instance];
|
||||
|
||||
const vec2 a_pos = in_pos_offset.xy;
|
||||
const vec2 a_offset = in_pos_offset.zw;
|
||||
const vec2 a_pos = unpack_int(symbol.pos_scale[0]);
|
||||
const vec2 offset_tb[2] = {unpack_int(symbol.offset_tltr[in_pos.x]), unpack_int(symbol.offset_blbr[in_pos.x])};
|
||||
const vec2 a_offset = offset_tb[in_pos.y];
|
||||
|
||||
const vec2 a_tex = in_data.xy;
|
||||
const vec2 a_size = in_data.zw;
|
||||
const vec2 a_tex = unpack_uint(symbol.texture_rect[0]) + in_pos * unpack_uint(symbol.texture_rect[1]);
|
||||
const vec2 a_size = unpack_uint(symbol.size_sdf);
|
||||
|
||||
const float a_size_min = floor(a_size[0] * 0.5);
|
||||
const float is_sdf = a_size[0] - 2.0 * a_size_min;
|
||||
const float segment_angle = -in_projected_pos[2];
|
||||
const float segment_angle = -dynamic.projected_pos[2];
|
||||
|
||||
float size;
|
||||
if (!drawable.is_size_zoom_constant && !drawable.is_size_feature_constant) {
|
||||
@@ -673,13 +809,13 @@ void main() {
|
||||
const float angle_cos = cos(segment_angle + symbol_rotation);
|
||||
const mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);
|
||||
|
||||
const vec4 projected_pos = drawable.label_plane_matrix * vec4(in_projected_pos.xy, 0.0, 1.0);
|
||||
const vec4 projected_pos = drawable.label_plane_matrix * vec4(dynamic.projected_pos[0], dynamic.projected_pos[1], 0.0, 1.0);
|
||||
const vec2 pos_rot = a_offset / 32.0 * fontScale;
|
||||
const vec2 pos0 = projected_pos.xy / projected_pos.w + rotation_matrix * pos_rot;
|
||||
gl_Position = drawable.coord_matrix * vec4(pos0, 0.0, 1.0);
|
||||
applySurfaceTransform();
|
||||
|
||||
const vec2 raw_fade_opacity = unpack_opacity(in_fade_opacity);
|
||||
const vec2 raw_fade_opacity = unpack_opacity(opacity.fade_opacity);
|
||||
const float fade_change = raw_fade_opacity[1] > 0.5 ? paintParams.symbol_fade_change : -paintParams.symbol_fade_change;
|
||||
|
||||
const bool is_icon = (is_sdf == ICON);
|
||||
@@ -691,19 +827,19 @@ void main() {
|
||||
frag_gamma_scale = gl_Position.w;
|
||||
|
||||
#if !defined(HAS_UNIFORM_u_fill_color)
|
||||
frag_fill_color = unpack_mix_color(in_fill_color, drawable.fill_color_t);
|
||||
frag_fill_color = unpack_mix_color(dataInstanceVector.instance[instance].fill_color, drawable.fill_color_t);
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_color)
|
||||
frag_halo_color = unpack_mix_color(in_halo_color, drawable.halo_color_t);
|
||||
frag_halo_color = unpack_mix_color(dataInstanceVector.instance[instance].halo_color, drawable.halo_color_t);
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_width)
|
||||
frag_halo_width = unpack_mix_float(in_halo_width, drawable.halo_width_t);
|
||||
frag_halo_width = unpack_mix_float(dataInstanceVector.instance[instance].halo_width, drawable.halo_width_t);
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_halo_blur)
|
||||
frag_halo_blur = unpack_mix_float(in_halo_blur, drawable.halo_blur_t);
|
||||
frag_halo_blur = unpack_mix_float(dataInstanceVector.instance[instance].halo_blur, drawable.halo_blur_t);
|
||||
#endif
|
||||
#if !defined(HAS_UNIFORM_u_opacity)
|
||||
frag_opacity = unpack_mix_float(in_opacity, drawable.opacity_t);
|
||||
frag_opacity = unpack_mix_float(dataInstanceVector.instance[instance].opacity, drawable.opacity_t);
|
||||
#endif
|
||||
}
|
||||
)";
|
||||
|
||||
@@ -182,6 +182,17 @@ struct MBGL_VERTEX_ALIGN VertexType<A1, A2, A3, A4, A5> {
|
||||
typename A5::Value a5;
|
||||
};
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
struct MBGL_VERTEX_ALIGN VertexType<A1, A2, A3, A4, A5, A6> {
|
||||
using Type = VertexType<A1, A2, A3, A4, A5, A6>;
|
||||
typename A1::Value a1;
|
||||
typename A2::Value a2;
|
||||
typename A3::Value a3;
|
||||
typename A4::Value a4;
|
||||
typename A5::Value a5;
|
||||
typename A6::Value a6;
|
||||
};
|
||||
|
||||
template <class>
|
||||
struct Descriptor;
|
||||
|
||||
|
||||
@@ -224,6 +224,8 @@ void DrawableBuilder::setSegments(const gfx::DrawMode mode,
|
||||
seg.indexOffset,
|
||||
seg.vertexLength,
|
||||
seg.indexLength,
|
||||
seg.baseInstance,
|
||||
seg.instanceCount,
|
||||
seg.sortKey,
|
||||
};
|
||||
impl->segments.emplace_back(createSegment(mode, std::move(segCopy)));
|
||||
|
||||
@@ -204,7 +204,7 @@ void DrawableBuilder::Impl::setupForWideVectors(gfx::Context& context, gfx::Draw
|
||||
|
||||
// segments
|
||||
SegmentVector triangleSegments;
|
||||
triangleSegments.emplace_back(0, 0, 12, 18);
|
||||
triangleSegments.emplace_back(0, 0, 12, 18, 0, sharedInstanceData->elements());
|
||||
|
||||
// add to builder
|
||||
{
|
||||
|
||||
@@ -104,6 +104,8 @@ void DrawableGL::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices,
|
||||
seg.indexOffset,
|
||||
seg.vertexLength,
|
||||
seg.indexLength,
|
||||
seg.baseInstance,
|
||||
seg.instanceCount,
|
||||
seg.sortKey,
|
||||
};
|
||||
auto drawSeg = std::make_unique<DrawableGL::DrawSegmentGL>(
|
||||
|
||||
@@ -115,7 +115,7 @@ private:
|
||||
if (segments.empty() ||
|
||||
segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
|
||||
// Move to a new segments because the old one can't hold the geometry.
|
||||
segments.emplace_back(vertices.elements(), triangles.elements(), 0ul, 0ul, sortKey);
|
||||
segments.emplace_back(vertices.elements(), triangles.elements(), 0ul, 0ul, 0ul, 1ul, sortKey);
|
||||
}
|
||||
|
||||
// this geometry will be of the Point type, and we'll derive
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <mln/math/angles.hpp>
|
||||
#include <mln/renderer/bucket_parameters.hpp>
|
||||
#include <mln/renderer/layers/render_symbol_layer.hpp>
|
||||
#include <mln/renderer/render_static_data.hpp>
|
||||
#include <mln/text/get_anchors.hpp>
|
||||
#include <mln/text/shaping.hpp>
|
||||
#include <mln/text/glyph_manager.hpp>
|
||||
@@ -1064,7 +1065,7 @@ void SymbolLayout::createBucket(const ImagePositions&,
|
||||
iconSymbol.angle = (allowVerticalPlacement && writingMode == WritingModeType::Vertical)
|
||||
? pi_v<float> / 2
|
||||
: 0.0f;
|
||||
iconSymbol.vertexStartIndex = addSymbols(
|
||||
iconSymbol.startIndex = addSymbols(
|
||||
iconBuffer, sizeData, iconQuads, symbolInstance.getAnchor(), iconSymbol, feature.sortKey);
|
||||
};
|
||||
|
||||
@@ -1078,8 +1079,12 @@ void SymbolLayout::createBucket(const ImagePositions&,
|
||||
}
|
||||
|
||||
for (auto& pair : bucket->paintProperties) {
|
||||
pair.second.iconBinders.populateVertexVectors(
|
||||
feature, iconBuffer.vertices().elements(), symbolInstance.getDataFeatureIndex(), {}, {}, canonical);
|
||||
pair.second.iconBinders.populateVertexVectors(feature,
|
||||
iconBuffer.attributeData().elements(),
|
||||
symbolInstance.getDataFeatureIndex(),
|
||||
{},
|
||||
{},
|
||||
canonical);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1169,7 +1174,7 @@ void SymbolLayout::updatePaintPropertiesForSection(SymbolBucket& bucket,
|
||||
const auto& formattedSection = sectionOptionsToValue((*feature.formattedText).sectionAt(sectionIndex));
|
||||
for (auto& pair : bucket.paintProperties) {
|
||||
pair.second.textBinders.populateVertexVectors(
|
||||
feature, bucket.text.vertices().elements(), feature.index, {}, {}, canonical, formattedSection);
|
||||
feature, bucket.text.attributeData().elements(), feature.index, {}, {}, canonical, formattedSection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1209,7 +1214,7 @@ std::size_t SymbolLayout::addSymbolGlyphQuads(SymbolBucket& bucket,
|
||||
const std::size_t index = addSymbol(
|
||||
bucket.text, sizeData, symbolQuad, symbolInstance.getAnchor(), placedSymbol, feature.sortKey);
|
||||
if (firstSymbol) {
|
||||
placedSymbol.vertexStartIndex = index;
|
||||
placedSymbol.startIndex = index;
|
||||
firstSymbol = false;
|
||||
}
|
||||
}
|
||||
@@ -1217,6 +1222,40 @@ std::size_t SymbolLayout::addSymbolGlyphQuads(SymbolBucket& bucket,
|
||||
return lastAddedSection ? *lastAddedSection : 0u;
|
||||
}
|
||||
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
|
||||
const Range<float> sizeData,
|
||||
const SymbolQuad& symbol,
|
||||
const Anchor& labelAnchor,
|
||||
PlacedSymbol& placedSymbol,
|
||||
float sortKey) {
|
||||
constexpr const uint16_t instanceCount = 1;
|
||||
|
||||
const uint16_t baseInstance = buffer.segments.empty() ? 0 : buffer.segments.back().instanceCount;
|
||||
if (buffer.segments.empty() || baseInstance + instanceCount > std::numeric_limits<uint16_t>::max() ||
|
||||
std::fabs(buffer.segments.back().sortKey - sortKey) > std::numeric_limits<float>::epsilon()) {
|
||||
buffer.segments.emplace_back(RenderStaticData::symbolSegment(baseInstance, sortKey));
|
||||
}
|
||||
|
||||
auto& segment = buffer.segments.back();
|
||||
auto index = static_cast<uint16_t>(segment.baseInstance + segment.instanceCount);
|
||||
|
||||
auto attributes = SymbolBucket::layoutAttributes(symbol, labelAnchor, sizeData);
|
||||
buffer.attributeData().emplace_back(attributes);
|
||||
|
||||
auto dynamicAttributes = SymbolBucket::dynamicLayoutAttributes(labelAnchor.point, 0);
|
||||
buffer.dynamicAttributeData().emplace_back(dynamicAttributes);
|
||||
|
||||
auto opacityAttributes = SymbolBucket::opacityAttributes(true, 1.0);
|
||||
buffer.opacityAttributeData().emplace_back(opacityAttributes);
|
||||
|
||||
segment.instanceCount += instanceCount;
|
||||
|
||||
placedSymbol.glyphOffsets.push_back(symbol.glyphOffset.x);
|
||||
|
||||
return index;
|
||||
}
|
||||
#else
|
||||
size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
|
||||
const Range<float> sizeData,
|
||||
const SymbolQuad& symbol,
|
||||
@@ -1237,7 +1276,8 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
|
||||
if (buffer.segments.empty() ||
|
||||
buffer.segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max() ||
|
||||
std::fabs(buffer.segments.back().sortKey - sortKey) > std::numeric_limits<float>::epsilon()) {
|
||||
buffer.segments.emplace_back(buffer.vertices().elements(), buffer.triangles.elements(), 0ul, 0ul, sortKey);
|
||||
buffer.segments.emplace_back(
|
||||
buffer.attributeData().elements(), buffer.triangles.elements(), 0ul, 0ul, 0ul, 1ul, sortKey);
|
||||
}
|
||||
|
||||
// We're generating triangle fans, so we always start with the first
|
||||
@@ -1247,58 +1287,58 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
|
||||
auto index = static_cast<uint16_t>(segment.vertexLength);
|
||||
|
||||
// coordinates (2 triangles)
|
||||
auto& vertices = buffer.vertices();
|
||||
vertices.emplace_back(SymbolBucket::layoutVertex(labelAnchor.point,
|
||||
tl,
|
||||
symbol.glyphOffset.y,
|
||||
tex.x,
|
||||
tex.y,
|
||||
sizeData,
|
||||
symbol.isSDF,
|
||||
pixelOffsetTL,
|
||||
minFontScale));
|
||||
vertices.emplace_back(SymbolBucket::layoutVertex(labelAnchor.point,
|
||||
tr,
|
||||
symbol.glyphOffset.y,
|
||||
tex.x + tex.w,
|
||||
tex.y,
|
||||
sizeData,
|
||||
symbol.isSDF,
|
||||
{pixelOffsetBR.x, pixelOffsetTL.y},
|
||||
minFontScale));
|
||||
vertices.emplace_back(SymbolBucket::layoutVertex(labelAnchor.point,
|
||||
bl,
|
||||
symbol.glyphOffset.y,
|
||||
tex.x,
|
||||
tex.y + tex.h,
|
||||
sizeData,
|
||||
symbol.isSDF,
|
||||
{pixelOffsetTL.x, pixelOffsetBR.y},
|
||||
minFontScale));
|
||||
vertices.emplace_back(SymbolBucket::layoutVertex(labelAnchor.point,
|
||||
br,
|
||||
symbol.glyphOffset.y,
|
||||
tex.x + tex.w,
|
||||
tex.y + tex.h,
|
||||
sizeData,
|
||||
symbol.isSDF,
|
||||
pixelOffsetBR,
|
||||
minFontScale));
|
||||
auto& attributeData = buffer.attributeData();
|
||||
attributeData.emplace_back(SymbolBucket::layoutAttributes(labelAnchor.point,
|
||||
tl,
|
||||
symbol.glyphOffset.y,
|
||||
tex.x,
|
||||
tex.y,
|
||||
sizeData,
|
||||
symbol.isSDF,
|
||||
pixelOffsetTL,
|
||||
minFontScale));
|
||||
attributeData.emplace_back(SymbolBucket::layoutAttributes(labelAnchor.point,
|
||||
tr,
|
||||
symbol.glyphOffset.y,
|
||||
tex.x + tex.w,
|
||||
tex.y,
|
||||
sizeData,
|
||||
symbol.isSDF,
|
||||
{pixelOffsetBR.x, pixelOffsetTL.y},
|
||||
minFontScale));
|
||||
attributeData.emplace_back(SymbolBucket::layoutAttributes(labelAnchor.point,
|
||||
bl,
|
||||
symbol.glyphOffset.y,
|
||||
tex.x,
|
||||
tex.y + tex.h,
|
||||
sizeData,
|
||||
symbol.isSDF,
|
||||
{pixelOffsetTL.x, pixelOffsetBR.y},
|
||||
minFontScale));
|
||||
attributeData.emplace_back(SymbolBucket::layoutAttributes(labelAnchor.point,
|
||||
br,
|
||||
symbol.glyphOffset.y,
|
||||
tex.x + tex.w,
|
||||
tex.y + tex.h,
|
||||
sizeData,
|
||||
symbol.isSDF,
|
||||
pixelOffsetBR,
|
||||
minFontScale));
|
||||
|
||||
// Dynamic/Opacity vertices are initialized so that the vertex count always
|
||||
// agrees with the layout vertex buffer, but they will always be updated
|
||||
// before rendering happens
|
||||
auto dynamicVertex = SymbolBucket::dynamicLayoutVertex(labelAnchor.point, 0);
|
||||
buffer.dynamicVertices().emplace_back(dynamicVertex);
|
||||
buffer.dynamicVertices().emplace_back(dynamicVertex);
|
||||
buffer.dynamicVertices().emplace_back(dynamicVertex);
|
||||
buffer.dynamicVertices().emplace_back(dynamicVertex);
|
||||
auto dynamicAttributes = SymbolBucket::dynamicLayoutAttributes(labelAnchor.point, 0);
|
||||
buffer.dynamicAttributeData().emplace_back(dynamicAttributes);
|
||||
buffer.dynamicAttributeData().emplace_back(dynamicAttributes);
|
||||
buffer.dynamicAttributeData().emplace_back(dynamicAttributes);
|
||||
buffer.dynamicAttributeData().emplace_back(dynamicAttributes);
|
||||
|
||||
auto opacityVertex = SymbolBucket::opacityVertex(true, 1.0);
|
||||
buffer.opacityVertices().emplace_back(opacityVertex);
|
||||
buffer.opacityVertices().emplace_back(opacityVertex);
|
||||
buffer.opacityVertices().emplace_back(opacityVertex);
|
||||
buffer.opacityVertices().emplace_back(opacityVertex);
|
||||
auto opacityAttributes = SymbolBucket::opacityAttributes(true, 1.0);
|
||||
buffer.opacityAttributeData().emplace_back(opacityAttributes);
|
||||
buffer.opacityAttributeData().emplace_back(opacityAttributes);
|
||||
buffer.opacityAttributeData().emplace_back(opacityAttributes);
|
||||
buffer.opacityAttributeData().emplace_back(opacityAttributes);
|
||||
|
||||
// add the two triangles, referencing the four coordinates we just inserted.
|
||||
buffer.triangles.emplace_back(index + 0, index + 1, index + 2);
|
||||
@@ -1311,6 +1351,7 @@ size_t SymbolLayout::addSymbol(SymbolBucket::Buffer& buffer,
|
||||
|
||||
return index;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t SymbolLayout::addSymbols(SymbolBucket::Buffer& buffer,
|
||||
const Range<float> sizeData,
|
||||
|
||||
@@ -180,18 +180,25 @@ bool isVisible(const vec4& anchorPos, const std::array<double, 2>& clippingBuffe
|
||||
|
||||
void addDynamicAttributes(const Point<float>& anchorPoint,
|
||||
const float angle,
|
||||
gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray) {
|
||||
auto dynamicVertex = SymbolBucket::dynamicLayoutVertex(anchorPoint, angle);
|
||||
dynamicVertexArray.emplace_back(dynamicVertex);
|
||||
dynamicVertexArray.emplace_back(dynamicVertex);
|
||||
dynamicVertexArray.emplace_back(dynamicVertex);
|
||||
dynamicVertexArray.emplace_back(dynamicVertex);
|
||||
SymbolBucket::DynamicAttributeVector& dynamicAttributeData) {
|
||||
auto dynamicAttributes = SymbolBucket::dynamicLayoutAttributes(anchorPoint, angle);
|
||||
dynamicAttributeData.emplace_back(dynamicAttributes);
|
||||
#if !MLN_USE_SYMBOL_INSTANCING
|
||||
dynamicAttributeData.emplace_back(dynamicAttributes);
|
||||
dynamicAttributeData.emplace_back(dynamicAttributes);
|
||||
dynamicAttributeData.emplace_back(dynamicAttributes);
|
||||
#endif
|
||||
}
|
||||
|
||||
void hideGlyphs(size_t numGlyphs, gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray) {
|
||||
void hideGlyphs(size_t numGlyphs, SymbolBucket::DynamicAttributeVector& dynamicVertexArray) {
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
const size_t count = 1;
|
||||
#else
|
||||
const size_t count = 4;
|
||||
#endif
|
||||
const Point<float> offscreenPoint = {-INFINITY, -INFINITY};
|
||||
if (dynamicVertexArray.empty()) {
|
||||
dynamicVertexArray.reserve(4 * numGlyphs);
|
||||
dynamicVertexArray.reserve(count * numGlyphs);
|
||||
}
|
||||
for (size_t i = 0; i < numGlyphs; i++) {
|
||||
addDynamicAttributes(offscreenPoint, 0, dynamicVertexArray);
|
||||
@@ -378,7 +385,7 @@ PlacementResult placeGlyphsAlongLine(const PlacedSymbol& symbol,
|
||||
const mat4& posMatrix,
|
||||
const mat4& labelPlaneMatrix,
|
||||
const mat4& glCoordMatrix,
|
||||
gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray,
|
||||
SymbolBucket::DynamicAttributeVector& dynamicVertexArray,
|
||||
const Point<float>& projectedAnchorPoint,
|
||||
const float aspectRatio) {
|
||||
const float fontScale = fontSize / util::ONE_EM;
|
||||
@@ -486,7 +493,7 @@ PlacementResult placeGlyphsAlongLine(const PlacedSymbol& symbol,
|
||||
return PlacementResult::OK;
|
||||
}
|
||||
|
||||
void reprojectLineLabels(gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray,
|
||||
void reprojectLineLabels(SymbolBucket::DynamicAttributeVector& dynamicVertexArray,
|
||||
const std::vector<PlacedSymbol>& placedSymbols,
|
||||
const mat4& posMatrix,
|
||||
bool pitchWithMap,
|
||||
|
||||
@@ -48,7 +48,7 @@ mat4 getGlCoordMatrix(
|
||||
using PointAndCameraDistance = std::pair<Point<float>, float>;
|
||||
PointAndCameraDistance project(const Point<float>& point, const mat4& matrix);
|
||||
|
||||
void reprojectLineLabels(gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>&,
|
||||
void reprojectLineLabels(SymbolBucket::DynamicAttributeVector&,
|
||||
const std::vector<PlacedSymbol>&,
|
||||
const mat4& posMatrix,
|
||||
bool pitchWithMap,
|
||||
@@ -68,10 +68,9 @@ std::optional<std::pair<PlacedGlyph, PlacedGlyph>> placeFirstAndLastGlyph(float
|
||||
const mat4& labelPlaneMatrix,
|
||||
bool returnTileDistance);
|
||||
|
||||
void hideGlyphs(std::size_t numGlyphs,
|
||||
gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray);
|
||||
void hideGlyphs(std::size_t numGlyphs, SymbolBucket::DynamicAttributeVector& dynamicVertexArray);
|
||||
void addDynamicAttributes(const Point<float>& anchorPoint,
|
||||
float angle,
|
||||
gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>& dynamicVertexArray);
|
||||
SymbolBucket::DynamicAttributeVector& dynamicAttributeData);
|
||||
|
||||
} // end namespace mln
|
||||
|
||||
@@ -276,8 +276,8 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
const auto primitiveType = getPrimitiveType(mode.type);
|
||||
constexpr auto indexType = MTL::IndexType::IndexTypeUInt16;
|
||||
constexpr auto indexSize = sizeof(std::uint16_t);
|
||||
const NS::UInteger instanceCount = instanceAttributes ? instanceAttributes->getMinCount() : 1;
|
||||
constexpr NS::UInteger baseInstance = 0;
|
||||
const NS::UInteger instanceCount = mlSegment.instanceCount;
|
||||
const NS::UInteger baseInstance = mlSegment.baseInstance;
|
||||
const NS::UInteger indexOffset = static_cast<NS::UInteger>(indexSize *
|
||||
mlSegment.indexOffset); // in bytes, not indexes
|
||||
const NS::Integer baseVertex = static_cast<NS::Integer>(mlSegment.vertexOffset);
|
||||
@@ -373,6 +373,8 @@ void Drawable::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices,
|
||||
seg.indexOffset,
|
||||
seg.vertexLength,
|
||||
seg.indexLength,
|
||||
seg.baseInstance,
|
||||
seg.instanceCount,
|
||||
seg.sortKey,
|
||||
};
|
||||
drawSegs.push_back(std::make_unique<Drawable::DrawSegment>(mode, std::move(segCopy)));
|
||||
@@ -548,10 +550,8 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
|
||||
|
||||
const bool buildVertexAttribs = !impl->vertexDesc || !vertexAttributes || !attributeUpdateTime ||
|
||||
vertexAttributes->isModifiedAfter(*attributeUpdateTime);
|
||||
const bool buildInstanceAttribs = instanceAttributes && (!attributeUpdateTime ||
|
||||
instanceAttributes->isModifiedAfter(*attributeUpdateTime));
|
||||
|
||||
if (buildVertexAttribs || buildInstanceAttribs) {
|
||||
if (buildVertexAttribs) {
|
||||
#if !defined(NDEBUG)
|
||||
const auto debugGroup = uploadPass.createDebugGroup(debugLabel(*this));
|
||||
#endif
|
||||
@@ -574,87 +574,94 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
|
||||
|
||||
vertexAttributes->visitAttributes([](gfx::VertexAttribute& attrib) { attrib.setDirty(false); });
|
||||
|
||||
// Build instance attribute buffers
|
||||
gfx::AttributeBindingArray instanceBindings_;
|
||||
if (instanceAttributes) {
|
||||
std::vector<std::unique_ptr<gfx::VertexBufferResource>> instanceBuffers;
|
||||
instanceBindings_ = uploadPass.buildAttributeBindings(instanceAttributes->getMinCount(),
|
||||
/*vertexType*/ gfx::AttributeDataType::Byte,
|
||||
/*vertexAttributeIndex=*/-1,
|
||||
/*vertexData=*/{},
|
||||
shader->getInstanceAttributes(),
|
||||
*instanceAttributes,
|
||||
usage,
|
||||
attributeUpdateTime,
|
||||
instanceBuffers);
|
||||
|
||||
// clear dirty flag
|
||||
instanceAttributes->visitAttributes([](gfx::VertexAttribute& attrib) { attrib.setDirty(false); });
|
||||
}
|
||||
|
||||
if (impl->attributeBindings != attributeBindings_ || impl->instanceBindings != instanceBindings_) {
|
||||
if (impl->attributeBindings != attributeBindings_) {
|
||||
impl->attributeBindings = std::move(attributeBindings_);
|
||||
impl->instanceBindings = std::move(instanceBindings_);
|
||||
|
||||
// hash
|
||||
std::size_t hash{0};
|
||||
|
||||
// Create a layout descriptor for each attribute
|
||||
auto vertDesc = NS::RetainPtr(MTL::VertexDescriptor::vertexDescriptor());
|
||||
|
||||
const auto applyBindings = [&](const gfx::AttributeBindingArray& attributeBindings,
|
||||
MTL::VertexStepFunction stepFunction) {
|
||||
NS::UInteger index = 0;
|
||||
for (auto& binding : attributeBindings) {
|
||||
if (!binding) {
|
||||
assert("Missing attribute binding");
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!binding->vertexBufferResource && !impl->noBindingBuffer) {
|
||||
if (const auto& buf = context.getEmptyVertexBuffer()) {
|
||||
impl->noBindingBuffer = buf.get();
|
||||
}
|
||||
}
|
||||
|
||||
const auto& attribDesc = vertDesc->attributes()->object(index);
|
||||
attribDesc->setBufferIndex(binding->bufferIndex);
|
||||
attribDesc->setOffset(static_cast<NS::UInteger>(binding->attribute.offset));
|
||||
attribDesc->setFormat(mtlVertexTypeOf(binding->attribute.dataType));
|
||||
|
||||
const auto& layoutDesc = vertDesc->layouts()->object(binding->bufferIndex);
|
||||
if (!layoutDesc->stride()) {
|
||||
assert(binding->vertexStride > 0);
|
||||
layoutDesc->setStride(static_cast<NS::UInteger>(binding->vertexStride));
|
||||
layoutDesc->setStepFunction(binding->vertexBufferResource ? stepFunction
|
||||
: MTL::VertexStepFunctionConstant);
|
||||
layoutDesc->setStepRate(binding->vertexBufferResource ? 1 : 0);
|
||||
} else {
|
||||
assert(layoutDesc->stride() == static_cast<NS::UInteger>(binding->vertexStride));
|
||||
assert(layoutDesc->stepRate() == (binding->vertexBufferResource ? 1 : 0));
|
||||
}
|
||||
|
||||
mln::util::hash_combine(hash,
|
||||
mln::util::hash(index,
|
||||
binding->attribute.offset,
|
||||
binding->attribute.dataType,
|
||||
binding->vertexStride,
|
||||
static_cast<bool>(binding->vertexBufferResource)));
|
||||
|
||||
index += 1;
|
||||
}
|
||||
};
|
||||
|
||||
applyBindings(impl->attributeBindings, MTL::VertexStepFunctionPerVertex);
|
||||
applyBindings(impl->instanceBindings, MTL::VertexStepFunctionPerInstance);
|
||||
|
||||
impl->vertexDesc = std::move(vertDesc);
|
||||
impl->vertexDescHash = hash;
|
||||
impl->pipelineState.reset();
|
||||
}
|
||||
}
|
||||
|
||||
const bool buildInstanceAttribs = instanceAttributes && (!attributeUpdateTime ||
|
||||
instanceAttributes->isModifiedAfter(*attributeUpdateTime));
|
||||
|
||||
if (buildInstanceAttribs) {
|
||||
// Build instance attribute buffers
|
||||
std::vector<std::unique_ptr<gfx::VertexBufferResource>> instanceBuffers;
|
||||
auto instanceBindings_ = uploadPass.buildAttributeBindings(instanceAttributes->getMinCount(),
|
||||
/*vertexType*/ gfx::AttributeDataType::Byte,
|
||||
/*vertexAttributeIndex=*/-1,
|
||||
/*vertexData=*/{},
|
||||
shader->getInstanceAttributes(),
|
||||
*instanceAttributes,
|
||||
usage,
|
||||
attributeUpdateTime,
|
||||
instanceBuffers);
|
||||
|
||||
// clear dirty flag
|
||||
instanceAttributes->visitAttributes([](gfx::VertexAttribute& attrib) { attrib.setDirty(false); });
|
||||
|
||||
if (impl->instanceBindings != instanceBindings_) {
|
||||
impl->instanceBindings = std::move(instanceBindings_);
|
||||
}
|
||||
}
|
||||
|
||||
if (buildVertexAttribs || buildInstanceAttribs) {
|
||||
// hash
|
||||
std::size_t hash{0};
|
||||
|
||||
// Create a layout descriptor for each attribute
|
||||
auto vertDesc = NS::RetainPtr(MTL::VertexDescriptor::vertexDescriptor());
|
||||
|
||||
const auto applyBindings = [&](const gfx::AttributeBindingArray& attributeBindings,
|
||||
MTL::VertexStepFunction stepFunction) {
|
||||
NS::UInteger index = 0;
|
||||
for (auto& binding : attributeBindings) {
|
||||
if (!binding) {
|
||||
assert("Missing attribute binding");
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!binding->vertexBufferResource && !impl->noBindingBuffer) {
|
||||
if (const auto& buf = context.getEmptyVertexBuffer()) {
|
||||
impl->noBindingBuffer = buf.get();
|
||||
}
|
||||
}
|
||||
|
||||
const auto& attribDesc = vertDesc->attributes()->object(index);
|
||||
attribDesc->setBufferIndex(binding->bufferIndex);
|
||||
attribDesc->setOffset(static_cast<NS::UInteger>(binding->attribute.offset));
|
||||
attribDesc->setFormat(mtlVertexTypeOf(binding->attribute.dataType));
|
||||
|
||||
const auto& layoutDesc = vertDesc->layouts()->object(binding->bufferIndex);
|
||||
if (!layoutDesc->stride()) {
|
||||
assert(binding->vertexStride > 0);
|
||||
layoutDesc->setStride(static_cast<NS::UInteger>(binding->vertexStride));
|
||||
layoutDesc->setStepFunction(binding->vertexBufferResource ? stepFunction
|
||||
: MTL::VertexStepFunctionConstant);
|
||||
layoutDesc->setStepRate(binding->vertexBufferResource ? 1 : 0);
|
||||
} else {
|
||||
assert(layoutDesc->stride() == static_cast<NS::UInteger>(binding->vertexStride));
|
||||
assert(layoutDesc->stepRate() == (binding->vertexBufferResource ? 1 : 0));
|
||||
}
|
||||
|
||||
mln::util::hash_combine(hash,
|
||||
mln::util::hash(index,
|
||||
binding->attribute.offset,
|
||||
binding->attribute.dataType,
|
||||
binding->vertexStride,
|
||||
static_cast<bool>(binding->vertexBufferResource)));
|
||||
|
||||
index += 1;
|
||||
}
|
||||
};
|
||||
|
||||
applyBindings(impl->attributeBindings, MTL::VertexStepFunctionPerVertex);
|
||||
applyBindings(impl->instanceBindings, MTL::VertexStepFunctionPerInstance);
|
||||
|
||||
impl->vertexDesc = std::move(vertDesc);
|
||||
impl->vertexDescHash = hash;
|
||||
impl->pipelineState.reset();
|
||||
}
|
||||
|
||||
const bool texturesNeedUpload = std::any_of(
|
||||
textures.begin(), textures.end(), [](const auto& texture) { return texture && texture->needsUpload(); });
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <mln/renderer/bucket_parameters.hpp>
|
||||
#include <mln/style/layers/fill_extrusion_layer_impl.hpp>
|
||||
#include <mln/renderer/layers/render_fill_extrusion_layer.hpp>
|
||||
#include <mln/renderer/render_static_data.hpp>
|
||||
#include <mln/map/transform_state.hpp>
|
||||
#include <mln/util/math.hpp>
|
||||
#include <mln/util/constants.hpp>
|
||||
@@ -201,6 +202,11 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
|
||||
|
||||
triangleSegment.vertexLength += totalVertices;
|
||||
triangleSegment.indexLength += nIndices;
|
||||
|
||||
if (instanceSegments.empty()) {
|
||||
instanceSegments.emplace_back(RenderStaticData::fillExtrusionSegment());
|
||||
}
|
||||
instanceSegments.back().instanceCount += totalVertices;
|
||||
}
|
||||
|
||||
for (auto& pair : paintPropertyBinders) {
|
||||
|
||||
@@ -97,6 +97,7 @@ public:
|
||||
TriangleIndexVector& triangles = *sharedTriangles;
|
||||
|
||||
SegmentVector triangleSegments;
|
||||
SegmentVector instanceSegments;
|
||||
|
||||
std::unordered_map<std::string, FillExtrusionBinders> paintPropertyBinders;
|
||||
};
|
||||
|
||||
@@ -73,16 +73,40 @@ SymbolBucket::SymbolBucket(Immutable<style::SymbolLayoutProperties::PossiblyEval
|
||||
placementModes(std::move(placementModes_)) {
|
||||
for (const auto& pair : paintProperties_) {
|
||||
const auto& evaluated = getEvaluated<SymbolLayerProperties>(pair.second);
|
||||
paintProperties.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(pair.first),
|
||||
std::forward_as_tuple(PaintProperties{
|
||||
.iconBinders = {RenderSymbolLayer::iconPaintProperties(evaluated), zoom},
|
||||
.textBinders = {RenderSymbolLayer::textPaintProperties(evaluated), zoom}}));
|
||||
paintProperties.emplace(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(pair.first),
|
||||
std::forward_as_tuple(PaintProperties{.iconBinders = {iconPaintProperties(evaluated), zoom},
|
||||
.textBinders = {textPaintProperties(evaluated), zoom}}));
|
||||
}
|
||||
}
|
||||
|
||||
SymbolBucket::~SymbolBucket() = default;
|
||||
|
||||
// static
|
||||
style::IconPaintProperties::PossiblyEvaluated SymbolBucket::iconPaintProperties(
|
||||
const style::SymbolPaintProperties::PossiblyEvaluated& evaluated_) {
|
||||
return style::IconPaintProperties::PossiblyEvaluated{evaluated_.get<style::IconOpacity>(),
|
||||
evaluated_.get<style::IconColor>(),
|
||||
evaluated_.get<style::IconHaloColor>(),
|
||||
evaluated_.get<style::IconHaloWidth>(),
|
||||
evaluated_.get<style::IconHaloBlur>(),
|
||||
evaluated_.get<style::IconTranslate>(),
|
||||
evaluated_.get<style::IconTranslateAnchor>()};
|
||||
}
|
||||
|
||||
// static
|
||||
style::TextPaintProperties::PossiblyEvaluated SymbolBucket::textPaintProperties(
|
||||
const style::SymbolPaintProperties::PossiblyEvaluated& evaluated_) {
|
||||
return style::TextPaintProperties::PossiblyEvaluated{evaluated_.get<style::TextOpacity>(),
|
||||
evaluated_.get<style::TextColor>(),
|
||||
evaluated_.get<style::TextHaloColor>(),
|
||||
evaluated_.get<style::TextHaloWidth>(),
|
||||
evaluated_.get<style::TextHaloBlur>(),
|
||||
evaluated_.get<style::TextTranslate>(),
|
||||
evaluated_.get<style::TextTranslateAnchor>()};
|
||||
}
|
||||
|
||||
void SymbolBucket::upload([[maybe_unused]] gfx::UploadPass& uploadPass) {
|
||||
uploaded = true;
|
||||
staticUploaded = true;
|
||||
@@ -136,9 +160,17 @@ bool SymbolBucket::hasTextCollisionCircleData() const {
|
||||
return textCollisionCircle && !textCollisionCircle->segments.empty();
|
||||
}
|
||||
|
||||
void addPlacedSymbol(gfx::IndexVector<gfx::Triangles>& triangles, const PlacedSymbol& placedSymbol) {
|
||||
auto endIndex = placedSymbol.vertexStartIndex + placedSymbol.glyphOffsets.size() * 4;
|
||||
for (auto vertexIndex = placedSymbol.vertexStartIndex; vertexIndex < endIndex; vertexIndex += 4) {
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
void addPlacedSymbol(SymbolBucket::SortedInstanceVector& sortedInstances, const PlacedSymbol& placedSymbol) {
|
||||
auto endIndex = placedSymbol.startIndex + placedSymbol.glyphOffsets.size() * 1;
|
||||
for (auto instanceIndex = placedSymbol.startIndex; instanceIndex < endIndex; instanceIndex += 1) {
|
||||
sortedInstances.emplace_back(SymbolSortedInstance{static_cast<uint16_t>(instanceIndex)});
|
||||
}
|
||||
}
|
||||
#else
|
||||
void addPlacedSymbol(SymbolBucket::TriangleIndexVector& triangles, const PlacedSymbol& placedSymbol) {
|
||||
auto endIndex = placedSymbol.startIndex + placedSymbol.glyphOffsets.size() * 4;
|
||||
for (auto vertexIndex = placedSymbol.startIndex; vertexIndex < endIndex; vertexIndex += 4) {
|
||||
triangles.emplace_back(static_cast<uint16_t>(vertexIndex + 0),
|
||||
static_cast<uint16_t>(vertexIndex + 1),
|
||||
static_cast<uint16_t>(vertexIndex + 2));
|
||||
@@ -147,6 +179,7 @@ void addPlacedSymbol(gfx::IndexVector<gfx::Triangles>& triangles, const PlacedSy
|
||||
static_cast<uint16_t>(vertexIndex + 3));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void SymbolBucket::sortFeatures(const float angle) {
|
||||
if (!sortFeaturesByY) {
|
||||
@@ -170,9 +203,19 @@ void SymbolBucket::sortFeatures(const float angle) {
|
||||
sortUploaded = false;
|
||||
uploaded = false;
|
||||
|
||||
text.triangles.clear();
|
||||
icon.triangles.clear();
|
||||
sdfIcon.triangles.clear();
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
auto& textVector = text.sortedInstances();
|
||||
auto& iconVector = icon.sortedInstances();
|
||||
auto& sdfIconVector = sdfIcon.sortedInstances();
|
||||
#else
|
||||
auto& textVector = text.triangles;
|
||||
auto& iconVector = icon.triangles;
|
||||
auto& sdfIconVector = sdfIcon.triangles;
|
||||
#endif
|
||||
|
||||
textVector.clear();
|
||||
iconVector.clear();
|
||||
sdfIconVector.clear();
|
||||
|
||||
auto symbolsSortOrder = std::make_unique<std::vector<size_t>>();
|
||||
symbolsSortOrder->reserve(symbolInstances.size());
|
||||
@@ -189,29 +232,29 @@ void SymbolBucket::sortFeatures(const float angle) {
|
||||
symbolsSortOrder->push_back(symbolInstance.getDataFeatureIndex());
|
||||
|
||||
if (symbolInstance.getPlacedRightTextIndex()) {
|
||||
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.getPlacedRightTextIndex()]);
|
||||
addPlacedSymbol(textVector, text.placedSymbols[*symbolInstance.getPlacedRightTextIndex()]);
|
||||
}
|
||||
|
||||
if (symbolInstance.getPlacedCenterTextIndex() && !symbolInstance.getSingleLine()) {
|
||||
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.getPlacedCenterTextIndex()]);
|
||||
addPlacedSymbol(textVector, text.placedSymbols[*symbolInstance.getPlacedCenterTextIndex()]);
|
||||
}
|
||||
|
||||
if (symbolInstance.getPlacedLeftTextIndex() && !symbolInstance.getSingleLine()) {
|
||||
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.getPlacedLeftTextIndex()]);
|
||||
addPlacedSymbol(textVector, text.placedSymbols[*symbolInstance.getPlacedLeftTextIndex()]);
|
||||
}
|
||||
|
||||
if (symbolInstance.getPlacedVerticalTextIndex()) {
|
||||
addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.getPlacedVerticalTextIndex()]);
|
||||
addPlacedSymbol(textVector, text.placedSymbols[*symbolInstance.getPlacedVerticalTextIndex()]);
|
||||
}
|
||||
|
||||
auto& iconBuffer = symbolInstance.hasSdfIcon() ? sdfIcon : icon;
|
||||
auto& iconVectorBuffer = symbolInstance.hasSdfIcon() ? sdfIconVector : iconVector;
|
||||
if (symbolInstance.getPlacedIconIndex()) {
|
||||
addPlacedSymbol(iconBuffer.triangles, iconBuffer.placedSymbols[*symbolInstance.getPlacedIconIndex()]);
|
||||
addPlacedSymbol(iconVectorBuffer, iconBuffer.placedSymbols[*symbolInstance.getPlacedIconIndex()]);
|
||||
}
|
||||
|
||||
if (symbolInstance.getPlacedVerticalIconIndex()) {
|
||||
addPlacedSymbol(iconBuffer.triangles,
|
||||
iconBuffer.placedSymbols[*symbolInstance.getPlacedVerticalIconIndex()]);
|
||||
addPlacedSymbol(iconVectorBuffer, iconBuffer.placedSymbols[*symbolInstance.getPlacedVerticalIconIndex()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,12 +291,12 @@ SymbolInstanceReferences SymbolBucket::getSymbols(const std::optional<SortKeyRan
|
||||
|
||||
#if MLN_SYMBOL_GUARDS
|
||||
bool SymbolBucket::check(source_location source) {
|
||||
if (text.vertices().elements() != text.dynamicVertices().elements() ||
|
||||
text.vertices().elements() != text.opacityVertices().elements() ||
|
||||
icon.vertices().elements() != icon.dynamicVertices().elements() ||
|
||||
icon.vertices().elements() != icon.opacityVertices().elements() ||
|
||||
sdfIcon.vertices().elements() != sdfIcon.dynamicVertices().elements() ||
|
||||
sdfIcon.vertices().elements() != sdfIcon.opacityVertices().elements()) {
|
||||
if (text.attributeData().elements() != text.dynamicAttributeData().elements() ||
|
||||
text.attributeData().elements() != text.opacityAttributeData().elements() ||
|
||||
icon.attributeData().elements() != icon.dynamicAttributeData().elements() ||
|
||||
icon.attributeData().elements() != icon.opacityAttributeData().elements() ||
|
||||
sdfIcon.attributeData().elements() != sdfIcon.dynamicAttributeData().elements() ||
|
||||
sdfIcon.attributeData().elements() != sdfIcon.opacityAttributeData().elements()) {
|
||||
// This bucket was left in a partial state and it cannot be used
|
||||
return false;
|
||||
}
|
||||
@@ -311,7 +354,7 @@ void SymbolBucket::updateVertices(const Placement& placement,
|
||||
uploaded = false;
|
||||
}
|
||||
|
||||
if (placement.updateBucketDynamicVertices(*this, state, tile)) {
|
||||
if (placement.updateBucketDynamicAttributeData(*this, state, tile)) {
|
||||
dynamicUploaded = false;
|
||||
uploaded = false;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <mln/shaders/segment.hpp>
|
||||
#include <mln/renderer/bucket.hpp>
|
||||
#include <mln/renderer/paint_property_binder.hpp>
|
||||
#include <mln/renderer/layers/render_symbol_layer.hpp>
|
||||
#include <mln/style/layers/symbol_layer_properties.hpp>
|
||||
#include <mln/text/glyph_range.hpp>
|
||||
|
||||
@@ -17,17 +16,54 @@
|
||||
|
||||
namespace mln {
|
||||
|
||||
namespace style {
|
||||
|
||||
// {icon,text}-specific paint-property packs for use in the symbol Programs.
|
||||
// Since each program deals either with icons or text, using a smaller property set
|
||||
// lets us avoid unnecessarily binding attributes for properties the program wouldn't use.
|
||||
class IconPaintProperties : public Properties<IconOpacity,
|
||||
IconColor,
|
||||
IconHaloColor,
|
||||
IconHaloWidth,
|
||||
IconHaloBlur,
|
||||
IconTranslate,
|
||||
IconTranslateAnchor> {};
|
||||
|
||||
class TextPaintProperties : public Properties<TextOpacity,
|
||||
TextColor,
|
||||
TextHaloColor,
|
||||
TextHaloWidth,
|
||||
TextHaloBlur,
|
||||
TextTranslate,
|
||||
TextTranslateAnchor> {};
|
||||
|
||||
} // namespace style
|
||||
|
||||
class CrossTileSymbolLayerIndex;
|
||||
|
||||
using SymbolIconBinders = PaintPropertyBinders<style::IconPaintProperties::DataDrivenProperties>;
|
||||
using SymbolTextBinders = PaintPropertyBinders<style::TextPaintProperties::DataDrivenProperties>;
|
||||
using SymbolLayoutVertex =
|
||||
gfx::Vertex<TypeList<attributes::pos_offset, attributes::data<uint16_t, 4>, attributes::pixeloffset>>;
|
||||
using SymbolDynamicLayoutAttributes = TypeList<attributes::projected_pos>;
|
||||
using SymbolOpacityAttributes = TypeList<attributes::fade_opacity>;
|
||||
using SymbolStaticVertexAttributes = gfx::Vertex<TypeList<attributes::pos>>;
|
||||
|
||||
using CollisionBoxLayoutAttributes = TypeList<attributes::pos, attributes::anchor_pos, attributes::extrude>;
|
||||
using CollisionBoxDynamicAttributes = TypeList<attributes::placed, attributes::shift>;
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
using SymbolSortedInstance = gfx::Vertex<TypeList<attributes::sorted_instance>>;
|
||||
using SymbolLayoutAttributes = gfx::Vertex<TypeList<attributes::pos_scale,
|
||||
attributes::offset_tltr,
|
||||
attributes::offset_blbr,
|
||||
attributes::texture_rect,
|
||||
attributes::pixeloffset,
|
||||
attributes::size_sdf>>;
|
||||
#else
|
||||
using SymbolLayoutAttributes =
|
||||
gfx::Vertex<TypeList<attributes::pos_offset, attributes::data<uint16_t, 4>, attributes::pixeloffset>>;
|
||||
#endif
|
||||
|
||||
using SymbolDynamicLayoutAttributes = gfx::Vertex<TypeList<attributes::projected_pos>>;
|
||||
using SymbolOpacityAttributes = gfx::Vertex<TypeList<attributes::fade_opacity>>;
|
||||
|
||||
using CollisionBoxLayoutVertexAttributes =
|
||||
gfx::Vertex<TypeList<attributes::pos, attributes::anchor_pos, attributes::extrude>>;
|
||||
using CollisionBoxDynamicVertexAttributes = gfx::Vertex<TypeList<attributes::placed, attributes::shift>>;
|
||||
|
||||
const uint16_t MAX_GLYPH_ICON_SIZE = 255;
|
||||
const uint16_t SIZE_PACK_FACTOR = 128;
|
||||
@@ -184,7 +220,7 @@ public:
|
||||
line(std::move(line_)),
|
||||
tileDistances(std::move(tileDistances_)),
|
||||
hidden(false),
|
||||
vertexStartIndex(0),
|
||||
startIndex(0),
|
||||
placedIconIndex(std::move(placedIconIndex_)) {}
|
||||
Point<float> anchorPoint;
|
||||
std::size_t segment;
|
||||
@@ -196,7 +232,7 @@ public:
|
||||
std::vector<float> tileDistances;
|
||||
std::vector<float> glyphOffsets;
|
||||
bool hidden;
|
||||
size_t vertexStartIndex;
|
||||
size_t startIndex;
|
||||
// The crossTileID is only filled/used on the foreground for variable text anchors
|
||||
uint32_t crossTileID = 0u;
|
||||
// The placedOrientation is only used when symbol layer's property is set to
|
||||
@@ -226,6 +262,11 @@ public:
|
||||
bool iconsInText);
|
||||
~SymbolBucket() override;
|
||||
|
||||
static style::IconPaintProperties::PossiblyEvaluated iconPaintProperties(
|
||||
const style::SymbolPaintProperties::PossiblyEvaluated&);
|
||||
static style::TextPaintProperties::PossiblyEvaluated textPaintProperties(
|
||||
const style::SymbolPaintProperties::PossiblyEvaluated&);
|
||||
|
||||
void upload(gfx::UploadPass&) override;
|
||||
bool hasData() const override;
|
||||
void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override;
|
||||
@@ -255,15 +296,50 @@ public:
|
||||
bool check(source_location) override;
|
||||
#endif
|
||||
|
||||
static SymbolLayoutVertex layoutVertex(Point<float> labelAnchor,
|
||||
Point<float> o,
|
||||
float glyphOffsetY,
|
||||
uint16_t tx,
|
||||
uint16_t ty,
|
||||
const Range<float>& sizeData,
|
||||
bool isSDF,
|
||||
Point<float> pixelOffset,
|
||||
Point<float> minFontScale) {
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
static SymbolLayoutAttributes layoutAttributes(const SymbolQuad& symbol,
|
||||
const Anchor& labelAnchor,
|
||||
const Range<float>& sizeData) {
|
||||
const uint16_t aSizeMin = (std::min(MAX_PACKED_SIZE, static_cast<uint16_t>(sizeData.min * SIZE_PACK_FACTOR))
|
||||
<< 1) +
|
||||
uint16_t(symbol.isSDF);
|
||||
const uint16_t aSizeMax = std::min(MAX_PACKED_SIZE, static_cast<uint16_t>(sizeData.max * SIZE_PACK_FACTOR));
|
||||
|
||||
return {{static_cast<int16_t>(labelAnchor.point.x),
|
||||
static_cast<int16_t>(labelAnchor.point.y),
|
||||
static_cast<int16_t>(symbol.minFontScale.x * 256),
|
||||
static_cast<int16_t>(symbol.minFontScale.y * 256)},
|
||||
|
||||
{static_cast<int16_t>(std::round(symbol.tl.x * 32)),
|
||||
static_cast<int16_t>(std::round((symbol.tl.y + symbol.glyphOffset.y) * 32)),
|
||||
static_cast<int16_t>(std::round(symbol.tr.x * 32)),
|
||||
static_cast<int16_t>(std::round((symbol.tr.y + symbol.glyphOffset.y) * 32))},
|
||||
|
||||
{static_cast<int16_t>(std::round(symbol.bl.x * 32)),
|
||||
static_cast<int16_t>(std::round((symbol.bl.y + symbol.glyphOffset.y) * 32)),
|
||||
static_cast<int16_t>(std::round(symbol.br.x * 32)),
|
||||
static_cast<int16_t>(std::round((symbol.br.y + symbol.glyphOffset.y) * 32))},
|
||||
|
||||
{symbol.tex.x, symbol.tex.y, symbol.tex.w, symbol.tex.h},
|
||||
|
||||
{static_cast<int16_t>(symbol.pixelOffsetTL.x * 16),
|
||||
static_cast<int16_t>(symbol.pixelOffsetTL.y * 16),
|
||||
static_cast<int16_t>(symbol.pixelOffsetBR.x * 16),
|
||||
static_cast<int16_t>(symbol.pixelOffsetBR.y * 16)},
|
||||
|
||||
{ aSizeMin,
|
||||
aSizeMax }};
|
||||
}
|
||||
#else
|
||||
static SymbolLayoutAttributes layoutAttributes(Point<float> labelAnchor,
|
||||
Point<float> o,
|
||||
float glyphOffsetY,
|
||||
uint16_t tx,
|
||||
uint16_t ty,
|
||||
const Range<float>& sizeData,
|
||||
bool isSDF,
|
||||
Point<float> pixelOffset,
|
||||
Point<float> minFontScale) {
|
||||
const uint16_t aSizeMin = (std::min(MAX_PACKED_SIZE, static_cast<uint16_t>(sizeData.min * SIZE_PACK_FACTOR))
|
||||
<< 1) +
|
||||
uint16_t(isSDF);
|
||||
@@ -282,12 +358,13 @@ public:
|
||||
static_cast<int16_t>(minFontScale.y * 256)}},
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
static gfx::Vertex<SymbolDynamicLayoutAttributes> dynamicLayoutVertex(Point<float> anchorPoint, float labelAngle) {
|
||||
static SymbolDynamicLayoutAttributes dynamicLayoutAttributes(Point<float> anchorPoint, float labelAngle) {
|
||||
return {{{anchorPoint.x, anchorPoint.y, labelAngle}}};
|
||||
}
|
||||
|
||||
static gfx::Vertex<SymbolOpacityAttributes> opacityVertex(bool placed, float opacity) {
|
||||
static SymbolOpacityAttributes opacityAttributes(bool placed, float opacity) {
|
||||
return {{{static_cast<float>((static_cast<uint8_t>(opacity * 127) << 1) | static_cast<uint8_t>(placed))}}};
|
||||
}
|
||||
|
||||
@@ -319,47 +396,63 @@ public:
|
||||
|
||||
std::unique_ptr<SymbolSizeBinder> textSizeBinder;
|
||||
|
||||
using VertexVector = gfx::VertexVector<SymbolLayoutVertex>;
|
||||
using VertexBuffer = gfx::VertexBuffer<SymbolLayoutVertex>;
|
||||
using DynamicVertexVector = gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>>;
|
||||
using DynamicVertexBuffer = gfx::VertexBuffer<gfx::Vertex<SymbolDynamicLayoutAttributes>>;
|
||||
using OpacityVertexVector = gfx::VertexVector<gfx::Vertex<SymbolOpacityAttributes>>;
|
||||
using OpacityVertexBuffer = gfx::VertexBuffer<gfx::Vertex<SymbolOpacityAttributes>>;
|
||||
using AttributeVector = gfx::VertexVector<SymbolLayoutAttributes>;
|
||||
using DynamicAttributeVector = gfx::VertexVector<SymbolDynamicLayoutAttributes>;
|
||||
using OpacityAttributeVector = gfx::VertexVector<SymbolOpacityAttributes>;
|
||||
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
using SortedInstanceVector = gfx::VertexVector<SymbolSortedInstance>;
|
||||
#else
|
||||
using TriangleIndexVector = gfx::IndexVector<gfx::Triangles>;
|
||||
#endif
|
||||
|
||||
struct Buffer final {
|
||||
~Buffer() {
|
||||
sharedVertices->release();
|
||||
sharedDynamicVertices->release();
|
||||
sharedOpacityVertices->release();
|
||||
sharedAttributeData->release();
|
||||
sharedDynamicAttributeData->release();
|
||||
sharedOpacityAttributeData->release();
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
sharedSortedInstances->release();
|
||||
#endif
|
||||
}
|
||||
|
||||
void updateModified() {
|
||||
if (sharedVertices) {
|
||||
sharedVertices->updateModified();
|
||||
if (sharedAttributeData) {
|
||||
sharedAttributeData->updateModified();
|
||||
}
|
||||
if (sharedDynamicVertices) {
|
||||
sharedDynamicVertices->updateModified();
|
||||
if (sharedDynamicAttributeData) {
|
||||
sharedDynamicAttributeData->updateModified();
|
||||
}
|
||||
if (sharedOpacityVertices) {
|
||||
sharedOpacityVertices->updateModified();
|
||||
if (sharedOpacityAttributeData) {
|
||||
sharedOpacityAttributeData->updateModified();
|
||||
}
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
if (sharedSortedInstances) {
|
||||
sharedSortedInstances->updateModified();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::shared_ptr<VertexVector> sharedVertices = std::make_shared<VertexVector>();
|
||||
VertexVector& vertices() { return *sharedVertices; }
|
||||
const VertexVector& vertices() const { return *sharedVertices; }
|
||||
std::shared_ptr<AttributeVector> sharedAttributeData = std::make_shared<AttributeVector>();
|
||||
AttributeVector& attributeData() { return *sharedAttributeData; }
|
||||
const AttributeVector& attributeData() const { return *sharedAttributeData; }
|
||||
|
||||
std::shared_ptr<DynamicVertexVector> sharedDynamicVertices = std::make_shared<DynamicVertexVector>();
|
||||
DynamicVertexVector& dynamicVertices() { return *sharedDynamicVertices; }
|
||||
const DynamicVertexVector& dynamicVertices() const { return *sharedDynamicVertices; }
|
||||
std::shared_ptr<DynamicAttributeVector> sharedDynamicAttributeData = std::make_shared<DynamicAttributeVector>();
|
||||
DynamicAttributeVector& dynamicAttributeData() { return *sharedDynamicAttributeData; }
|
||||
const DynamicAttributeVector& dynamicAttributeData() const { return *sharedDynamicAttributeData; }
|
||||
|
||||
std::shared_ptr<OpacityVertexVector> sharedOpacityVertices = std::make_shared<OpacityVertexVector>();
|
||||
OpacityVertexVector& opacityVertices() { return *sharedOpacityVertices; }
|
||||
const OpacityVertexVector& opacityVertices() const { return *sharedOpacityVertices; }
|
||||
std::shared_ptr<OpacityAttributeVector> sharedOpacityAttributeData = std::make_shared<OpacityAttributeVector>();
|
||||
OpacityAttributeVector& opacityAttributeData() { return *sharedOpacityAttributeData; }
|
||||
const OpacityAttributeVector& opacityAttributeData() const { return *sharedOpacityAttributeData; }
|
||||
|
||||
using TriangleIndexVector = gfx::IndexVector<gfx::Triangles>;
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
std::shared_ptr<SortedInstanceVector> sharedSortedInstances = std::make_shared<SortedInstanceVector>();
|
||||
SortedInstanceVector& sortedInstances() { return *sharedSortedInstances; }
|
||||
const SortedInstanceVector& sortedInstances() const { return *sharedSortedInstances; }
|
||||
#else
|
||||
const std::shared_ptr<TriangleIndexVector> sharedTriangles = std::make_shared<TriangleIndexVector>();
|
||||
TriangleIndexVector& triangles = *sharedTriangles;
|
||||
#endif
|
||||
|
||||
SegmentVector segments;
|
||||
std::vector<PlacedSymbol> placedSymbols;
|
||||
@@ -370,8 +463,8 @@ public:
|
||||
Buffer icon;
|
||||
Buffer sdfIcon;
|
||||
|
||||
using CollisionVertexVector = gfx::VertexVector<gfx::Vertex<CollisionBoxLayoutAttributes>>;
|
||||
using CollisionDynamicVertexVector = gfx::VertexVector<gfx::Vertex<CollisionBoxDynamicAttributes>>;
|
||||
using CollisionVertexVector = gfx::VertexVector<CollisionBoxLayoutVertexAttributes>;
|
||||
using CollisionDynamicVertexVector = gfx::VertexVector<CollisionBoxDynamicVertexAttributes>;
|
||||
|
||||
struct CollisionBuffer {
|
||||
std::shared_ptr<CollisionVertexVector> sharedVertices = std::make_shared<CollisionVertexVector>();
|
||||
@@ -422,17 +515,15 @@ public:
|
||||
return *textCollisionCircle;
|
||||
}
|
||||
|
||||
static gfx::Vertex<CollisionBoxLayoutAttributes> collisionLayoutVertex(Point<float> a,
|
||||
Point<float> anchor,
|
||||
Point<float> o) {
|
||||
static CollisionBoxLayoutVertexAttributes collisionLayoutVertex(Point<float> a,
|
||||
Point<float> anchor,
|
||||
Point<float> o) {
|
||||
return {{{static_cast<int16_t>(a.x), static_cast<int16_t>(a.y)}},
|
||||
{{static_cast<int16_t>(anchor.x), static_cast<int16_t>(anchor.y)}},
|
||||
{{static_cast<int16_t>(::round(o.x)), static_cast<int16_t>(::round(o.y))}}};
|
||||
}
|
||||
|
||||
static gfx::Vertex<CollisionBoxDynamicAttributes> collisionDynamicVertex(bool placed,
|
||||
bool notUsed,
|
||||
Point<float> shift) {
|
||||
static CollisionBoxDynamicVertexAttributes collisionDynamicVertex(bool placed, bool notUsed, Point<float> shift) {
|
||||
return {{{static_cast<uint16_t>(placed), static_cast<uint16_t>(notUsed)}}, {{shift.x, shift.y}}};
|
||||
}
|
||||
|
||||
|
||||
@@ -178,9 +178,6 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
|
||||
if (!staticDataIndices) {
|
||||
staticDataIndices = std::make_shared<TriangleIndexVector>(RenderStaticData::fillExtrusionTriangleIndices());
|
||||
}
|
||||
if (!staticDataSegments) {
|
||||
staticDataSegments = std::make_shared<SegmentVector>(RenderStaticData::fillExtrusionSegments());
|
||||
}
|
||||
|
||||
const auto& instancedShaderGroup = hasPattern ? fillExtrusionPatternInstancedGroup : fillExtrusionInstancedGroup;
|
||||
if (!instancedShaderGroup) {
|
||||
@@ -472,7 +469,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
|
||||
return;
|
||||
}
|
||||
instancedBuilder.setSegments(
|
||||
gfx::Triangles(), staticDataIndices, staticDataSegments->data(), staticDataSegments->size());
|
||||
gfx::Triangles(), staticDataIndices, bucket.instanceSegments.data(), bucket.instanceSegments.size());
|
||||
|
||||
instancedBuilder.flush(context);
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ private:
|
||||
|
||||
std::shared_ptr<FillExtrusionVertexVector> staticDataVertices;
|
||||
std::shared_ptr<TriangleIndexVector> staticDataIndices;
|
||||
std::shared_ptr<SegmentVector> staticDataSegments;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <mln/renderer/paint_parameters.hpp>
|
||||
#include <mln/renderer/property_evaluation_parameters.hpp>
|
||||
#include <mln/renderer/render_source.hpp>
|
||||
#include <mln/renderer/render_static_data.hpp>
|
||||
#include <mln/renderer/render_tile.hpp>
|
||||
#include <mln/renderer/tile_render_data.hpp>
|
||||
#include <mln/renderer/upload_parameters.hpp>
|
||||
@@ -192,30 +193,6 @@ bool RenderSymbolLayer::hasCrossfade() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
style::IconPaintProperties::PossiblyEvaluated RenderSymbolLayer::iconPaintProperties(
|
||||
const style::SymbolPaintProperties::PossiblyEvaluated& evaluated_) {
|
||||
return style::IconPaintProperties::PossiblyEvaluated{evaluated_.get<style::IconOpacity>(),
|
||||
evaluated_.get<style::IconColor>(),
|
||||
evaluated_.get<style::IconHaloColor>(),
|
||||
evaluated_.get<style::IconHaloWidth>(),
|
||||
evaluated_.get<style::IconHaloBlur>(),
|
||||
evaluated_.get<style::IconTranslate>(),
|
||||
evaluated_.get<style::IconTranslateAnchor>()};
|
||||
}
|
||||
|
||||
// static
|
||||
style::TextPaintProperties::PossiblyEvaluated RenderSymbolLayer::textPaintProperties(
|
||||
const style::SymbolPaintProperties::PossiblyEvaluated& evaluated_) {
|
||||
return style::TextPaintProperties::PossiblyEvaluated{evaluated_.get<style::TextOpacity>(),
|
||||
evaluated_.get<style::TextColor>(),
|
||||
evaluated_.get<style::TextHaloColor>(),
|
||||
evaluated_.get<style::TextHaloWidth>(),
|
||||
evaluated_.get<style::TextHaloBlur>(),
|
||||
evaluated_.get<style::TextTranslate>(),
|
||||
evaluated_.get<style::TextTranslateAnchor>()};
|
||||
}
|
||||
|
||||
void RenderSymbolLayer::prepare(const LayerPrepareParameters& params) {
|
||||
renderTiles = params.source->getRenderTilesSortedByYPosition();
|
||||
|
||||
@@ -261,6 +238,7 @@ void RenderSymbolLayer::prepare(const LayerPrepareParameters& params) {
|
||||
namespace {
|
||||
const SegmentVector emptySegmentVector;
|
||||
constexpr auto posOffsetAttribName = "a_pos_offset";
|
||||
[[maybe_unused]] constexpr auto sortedInstanceUniformName = "sorted_instance";
|
||||
|
||||
void updateTileAttributes(const SymbolBucket::Buffer& buffer,
|
||||
const bool isText,
|
||||
@@ -268,51 +246,106 @@ void updateTileAttributes(const SymbolBucket::Buffer& buffer,
|
||||
const SymbolPaintProperties::PossiblyEvaluated& evaluated,
|
||||
gfx::VertexAttributeArray& attribs,
|
||||
StringIDSetsPair* propertiesAsUniforms) {
|
||||
if (const auto& attr = attribs.set(idSymbolPosOffsetVertexAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedVertices,
|
||||
offsetof(SymbolLayoutVertex, a1),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolLayoutVertex),
|
||||
gfx::AttributeDataType::Short4);
|
||||
}
|
||||
if (const auto& attr = attribs.set(idSymbolDataVertexAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedVertices,
|
||||
offsetof(SymbolLayoutVertex, a2),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolLayoutVertex),
|
||||
gfx::AttributeDataType::UShort4);
|
||||
}
|
||||
if (const auto& attr = attribs.set(idSymbolPixelOffsetVertexAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedVertices,
|
||||
offsetof(SymbolLayoutVertex, a3),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolLayoutVertex),
|
||||
gfx::AttributeDataType::Short4);
|
||||
}
|
||||
|
||||
if (const auto& attr = attribs.set(idSymbolProjectedPosVertexAttribute)) {
|
||||
using Vertex = gfx::Vertex<SymbolDynamicLayoutAttributes>;
|
||||
attr->setSharedRawData(buffer.sharedDynamicVertices,
|
||||
offsetof(Vertex, a1),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(Vertex),
|
||||
gfx::AttributeDataType::Float3);
|
||||
}
|
||||
if (const auto& attr = attribs.set(idSymbolFadeOpacityVertexAttribute)) {
|
||||
using Vertex = gfx::Vertex<SymbolOpacityAttributes>;
|
||||
attr->setSharedRawData(buffer.sharedOpacityVertices,
|
||||
offsetof(Vertex, a1),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(Vertex),
|
||||
gfx::AttributeDataType::Float);
|
||||
}
|
||||
|
||||
if (isText) {
|
||||
attribs.readDataDrivenPaintProperties<TextOpacity, TextColor, TextHaloColor, TextHaloWidth, TextHaloBlur>(
|
||||
paintProps.textBinders, evaluated, propertiesAsUniforms, idSymbolOpacityVertexAttribute);
|
||||
paintProps.textBinders, evaluated, propertiesAsUniforms, idSymbolOpacityAttribute);
|
||||
} else {
|
||||
attribs.readDataDrivenPaintProperties<IconOpacity, IconColor, IconHaloColor, IconHaloWidth, IconHaloBlur>(
|
||||
paintProps.iconBinders, evaluated, propertiesAsUniforms, idSymbolOpacityVertexAttribute);
|
||||
paintProps.iconBinders, evaluated, propertiesAsUniforms, idSymbolOpacityAttribute);
|
||||
}
|
||||
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
if (!buffer.sortedInstances().empty()) {
|
||||
if (const auto& attr = attribs.set(idSymbolSortedInstanceAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedSortedInstances,
|
||||
offsetof(SymbolSortedInstance, a1),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolSortedInstance),
|
||||
gfx::AttributeDataType::UShort);
|
||||
}
|
||||
} else if (propertiesAsUniforms) {
|
||||
propertiesAsUniforms->first.emplace(sortedInstanceUniformName);
|
||||
propertiesAsUniforms->second.emplace(idSymbolSortedInstanceAttribute);
|
||||
}
|
||||
if (const auto& attr = attribs.set(idSymbolPosScaleAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedAttributeData,
|
||||
offsetof(SymbolLayoutAttributes, a1),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolLayoutAttributes),
|
||||
gfx::AttributeDataType::Short4);
|
||||
}
|
||||
if (const auto& attr = attribs.set(idSymbolOffsetTlTrAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedAttributeData,
|
||||
offsetof(SymbolLayoutAttributes, a2),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolLayoutAttributes),
|
||||
gfx::AttributeDataType::Short4);
|
||||
}
|
||||
if (const auto& attr = attribs.set(idSymbolOffsetBlBrAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedAttributeData,
|
||||
offsetof(SymbolLayoutAttributes, a3),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolLayoutAttributes),
|
||||
gfx::AttributeDataType::Short4);
|
||||
}
|
||||
if (const auto& attr = attribs.set(idSymbolTextureRectAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedAttributeData,
|
||||
offsetof(SymbolLayoutAttributes, a4),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolLayoutAttributes),
|
||||
gfx::AttributeDataType::UShort4);
|
||||
}
|
||||
if (const auto& attr = attribs.set(idSymbolPixelOffsetAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedAttributeData,
|
||||
offsetof(SymbolLayoutAttributes, a5),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolLayoutAttributes),
|
||||
gfx::AttributeDataType::Short4);
|
||||
}
|
||||
if (const auto& attr = attribs.set(idSymbolSizeSdfAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedAttributeData,
|
||||
offsetof(SymbolLayoutAttributes, a6),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolLayoutAttributes),
|
||||
gfx::AttributeDataType::UShort2);
|
||||
}
|
||||
#else
|
||||
if (const auto& attr = attribs.set(idSymbolPosOffsetAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedAttributeData,
|
||||
offsetof(SymbolLayoutAttributes, a1),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolLayoutAttributes),
|
||||
gfx::AttributeDataType::Short4);
|
||||
}
|
||||
if (const auto& attr = attribs.set(idSymbolDataAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedAttributeData,
|
||||
offsetof(SymbolLayoutAttributes, a2),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolLayoutAttributes),
|
||||
gfx::AttributeDataType::UShort4);
|
||||
}
|
||||
if (const auto& attr = attribs.set(idSymbolPixelOffsetAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedAttributeData,
|
||||
offsetof(SymbolLayoutAttributes, a3),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolLayoutAttributes),
|
||||
gfx::AttributeDataType::Short4);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (const auto& attr = attribs.set(idSymbolProjectedPosAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedDynamicAttributeData,
|
||||
offsetof(SymbolDynamicLayoutAttributes, a1),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolDynamicLayoutAttributes),
|
||||
gfx::AttributeDataType::Float3);
|
||||
}
|
||||
if (const auto& attr = attribs.set(idSymbolFadeOpacityAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedOpacityAttributeData,
|
||||
offsetof(SymbolOpacityAttributes, a1),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolOpacityAttributes),
|
||||
gfx::AttributeDataType::Float);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,59 +365,62 @@ void updateTileDrawable(gfx::Drawable& drawable,
|
||||
drawData.bucketVariablePlacement = bucket.hasVariablePlacement;
|
||||
|
||||
const auto& buffer = isText ? bucket.text : (sdfIcons ? bucket.sdfIcon : bucket.icon);
|
||||
const auto vertexCount = buffer.vertices().elements();
|
||||
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
if (auto& instanceAttribs = drawable.getInstanceAttributes()) {
|
||||
updateTileAttributes(buffer, isText, paintProps, evaluated, *instanceAttribs, nullptr);
|
||||
}
|
||||
#else
|
||||
const auto vertexCount = buffer.attributeData().elements();
|
||||
drawable.setVertices({}, vertexCount, gfx::AttributeDataType::Short4);
|
||||
|
||||
// TODO: detect whether anything has actually changed
|
||||
// See `Placement::updateBucketDynamicVertices`
|
||||
// See `Placement::updateBucketDynamicAttributeData`
|
||||
|
||||
if (auto& attribs = drawable.getVertexAttributes()) {
|
||||
updateTileAttributes(buffer, isText, paintProps, evaluated, *attribs, nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
gfx::VertexAttributeArrayPtr getCollisionVertexAttributes(gfx::Context& context,
|
||||
const SymbolBucket::CollisionBuffer& buffer) {
|
||||
auto vertexAttrs = context.createVertexAttributeArray();
|
||||
using LayoutVertex = gfx::Vertex<CollisionBoxLayoutAttributes>;
|
||||
|
||||
if (const auto& attr = vertexAttrs->set(idCollisionPosVertexAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedVertices,
|
||||
offsetof(LayoutVertex, a1),
|
||||
offsetof(CollisionBoxLayoutVertexAttributes, a1),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(LayoutVertex),
|
||||
sizeof(CollisionBoxLayoutVertexAttributes),
|
||||
gfx::AttributeDataType::Short2);
|
||||
}
|
||||
if (const auto& attr = vertexAttrs->set(idCollisionAnchorPosVertexAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedVertices,
|
||||
offsetof(LayoutVertex, a2),
|
||||
offsetof(CollisionBoxLayoutVertexAttributes, a2),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(LayoutVertex),
|
||||
sizeof(CollisionBoxLayoutVertexAttributes),
|
||||
gfx::AttributeDataType::Short2);
|
||||
}
|
||||
if (const auto& attr = vertexAttrs->set(idCollisionExtrudeVertexAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedVertices,
|
||||
offsetof(LayoutVertex, a3),
|
||||
offsetof(CollisionBoxLayoutVertexAttributes, a3),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(LayoutVertex),
|
||||
sizeof(CollisionBoxLayoutVertexAttributes),
|
||||
gfx::AttributeDataType::Short2);
|
||||
}
|
||||
|
||||
using DynamicVertex = gfx::Vertex<CollisionBoxDynamicAttributes>;
|
||||
|
||||
if (const auto& attr = vertexAttrs->set(idCollisionPlacedVertexAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedDynamicVertices,
|
||||
offsetof(DynamicVertex, a1),
|
||||
offsetof(CollisionBoxDynamicVertexAttributes, a1),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(DynamicVertex),
|
||||
sizeof(CollisionBoxDynamicVertexAttributes),
|
||||
gfx::AttributeDataType::UShort2);
|
||||
}
|
||||
if (const auto& attr = vertexAttrs->set(idCollisionShiftVertexAttribute)) {
|
||||
attr->setSharedRawData(buffer.sharedDynamicVertices,
|
||||
offsetof(DynamicVertex, a2),
|
||||
offsetof(CollisionBoxDynamicVertexAttributes, a2),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(DynamicVertex),
|
||||
sizeof(CollisionBoxDynamicVertexAttributes),
|
||||
gfx::AttributeDataType::Float2);
|
||||
}
|
||||
|
||||
@@ -492,6 +528,15 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
|
||||
collisionCircleGroup = shaders.getShaderGroup(std::string(CollisionCircleShaderName));
|
||||
}
|
||||
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
if (!staticDataVertices) {
|
||||
staticDataVertices = std::make_shared<SymbolVertexVector>(RenderStaticData::symbolVertices());
|
||||
}
|
||||
if (!staticDataIndices) {
|
||||
staticDataIndices = std::make_shared<TriangleIndexVector>(RenderStaticData::symbolTriangleIndices());
|
||||
}
|
||||
#endif
|
||||
|
||||
// remove drawables that are dropped out of scope
|
||||
auto* tileLayerGroup = static_cast<TileLayerGroup*>(layerGroup.get());
|
||||
stats.drawablesRemoved += tileLayerGroup->removeDrawablesIf([&](gfx::Drawable& drawable) {
|
||||
@@ -648,7 +693,11 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
|
||||
if (sortFeaturesByKey) {
|
||||
// Features need to be rendered in a specific order, so we add each segment individually
|
||||
for (const auto& segment : buffer.segments) {
|
||||
assert(segment.vertexOffset + segment.vertexLength <= buffer.vertices().elements());
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
assert(segment.baseInstance + segment.instanceCount <= buffer.attributeData().elements());
|
||||
#else
|
||||
assert(segment.vertexOffset + segment.vertexLength <= buffer.attributeData().elements());
|
||||
#endif
|
||||
renderableSegments.emplace(SegmentGroup{
|
||||
.renderable = {segment, tile, renderData, bucketPaintProperties, segment.sortKey, type},
|
||||
.segments = emptySegmentVector});
|
||||
@@ -705,9 +754,15 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
|
||||
auto& bucket = static_cast<SymbolBucket&>(*renderable.renderData.bucket);
|
||||
const auto& buffer = isText ? bucket.text : (sdfIcons ? bucket.sdfIcon : bucket.icon);
|
||||
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
if (!buffer.attributeData().elements()) {
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
if (!buffer.sharedTriangles->elements()) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderable.renderData.layerProperties);
|
||||
auto& bucketPaintProperties = bucket.paintProperties.at(getID());
|
||||
@@ -724,13 +779,25 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
|
||||
|
||||
auto& tileInfo = tileCache[tile.id];
|
||||
|
||||
const auto vertexCount = buffer.vertices().elements();
|
||||
|
||||
propertiesAsUniforms.first.clear();
|
||||
propertiesAsUniforms.second.clear();
|
||||
|
||||
auto attribs = context.createVertexAttributeArray();
|
||||
updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, *attribs, &propertiesAsUniforms);
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
auto vertexAttribs = context.createVertexAttributeArray();
|
||||
if (const auto& attr = vertexAttribs->set(idSymbolPosAttribute)) {
|
||||
attr->setSharedRawData(staticDataVertices,
|
||||
offsetof(SymbolStaticVertexAttributes, a1),
|
||||
/*vertexOffset=*/0,
|
||||
sizeof(SymbolStaticVertexAttributes),
|
||||
gfx::AttributeDataType::Short2);
|
||||
}
|
||||
|
||||
auto instanceAttribs = context.createVertexAttributeArray();
|
||||
updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, *instanceAttribs, &propertiesAsUniforms);
|
||||
#else
|
||||
auto vertexAttribs = context.createVertexAttributeArray();
|
||||
updateTileAttributes(buffer, isText, bucketPaintProperties, evaluated, *vertexAttribs, &propertiesAsUniforms);
|
||||
#endif
|
||||
|
||||
const auto textHalo = evaluated.get<style::TextHaloColor>().constantOr(Color::black()).a > 0.0f &&
|
||||
evaluated.get<style::TextHaloWidth>().constantOr(1);
|
||||
@@ -796,14 +863,24 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
|
||||
|
||||
builder->clearTweakers();
|
||||
builder->addTweaker(isText ? tileInfo.textTweaker : tileInfo.iconTweaker);
|
||||
builder->setRawVertices({}, vertexCount, gfx::AttributeDataType::Short4);
|
||||
builder->setDrawableName(layerPrefix + std::string(suffix));
|
||||
builder->setVertexAttributes(attribs);
|
||||
builder->setVertexAttributes(vertexAttribs);
|
||||
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
builder->setInstanceAttributes(instanceAttribs);
|
||||
builder->setRawVertices({}, staticDataVertices->elements(), gfx::AttributeDataType::Short2);
|
||||
|
||||
auto& triangleIndices = staticDataIndices;
|
||||
#else
|
||||
builder->setRawVertices({}, buffer.attributeData().elements(), gfx::AttributeDataType::Short4);
|
||||
|
||||
auto& triangleIndices = buffer.sharedTriangles;
|
||||
#endif
|
||||
|
||||
if (segments.empty()) {
|
||||
builder->setSegments(gfx::Triangles(), buffer.sharedTriangles, &renderable.segment.get(), 1);
|
||||
builder->setSegments(gfx::Triangles(), triangleIndices, &renderable.segment.get(), 1);
|
||||
} else {
|
||||
builder->setSegments(gfx::Triangles(), buffer.sharedTriangles, segments.data(), segments.size());
|
||||
builder->setSegments(gfx::Triangles(), triangleIndices, segments.data(), segments.size());
|
||||
}
|
||||
|
||||
builder->flush(context);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <mln/text/glyph.hpp>
|
||||
#include <mln/renderer/render_layer.hpp>
|
||||
#include <mln/renderer/buckets/symbol_bucket.hpp>
|
||||
#include <mln/style/image_impl.hpp>
|
||||
#include <mln/style/layers/symbol_layer_impl.hpp>
|
||||
#include <mln/style/layers/symbol_layer_properties.hpp>
|
||||
@@ -12,25 +13,6 @@ namespace mln {
|
||||
|
||||
namespace style {
|
||||
|
||||
// {icon,text}-specific paint-property packs for use in the symbol Programs.
|
||||
// Since each program deals either with icons or text, using a smaller property set
|
||||
// lets us avoid unnecessarily binding attributes for properties the program wouldn't use.
|
||||
class IconPaintProperties : public Properties<IconOpacity,
|
||||
IconColor,
|
||||
IconHaloColor,
|
||||
IconHaloWidth,
|
||||
IconHaloBlur,
|
||||
IconTranslate,
|
||||
IconTranslateAnchor> {};
|
||||
|
||||
class TextPaintProperties : public Properties<TextOpacity,
|
||||
TextColor,
|
||||
TextHaloColor,
|
||||
TextHaloWidth,
|
||||
TextHaloBlur,
|
||||
TextTranslate,
|
||||
TextTranslateAnchor> {};
|
||||
|
||||
// Repackaging evaluated values from SymbolLayoutProperties +
|
||||
// SymbolPaintProperties for genericity over icons vs. text.
|
||||
class SymbolPropertyValues {
|
||||
@@ -64,11 +46,6 @@ public:
|
||||
explicit RenderSymbolLayer(Immutable<style::SymbolLayer::Impl>);
|
||||
~RenderSymbolLayer() override;
|
||||
|
||||
static style::IconPaintProperties::PossiblyEvaluated iconPaintProperties(
|
||||
const style::SymbolPaintProperties::PossiblyEvaluated &);
|
||||
static style::TextPaintProperties::PossiblyEvaluated textPaintProperties(
|
||||
const style::SymbolPaintProperties::PossiblyEvaluated &);
|
||||
|
||||
/// Generate any changes needed by the layer
|
||||
void update(gfx::ShaderRegistry &,
|
||||
gfx::Context &,
|
||||
@@ -126,6 +103,14 @@ private:
|
||||
std::shared_ptr<TileLayerGroup> collisionTileLayerGroup;
|
||||
|
||||
LayerTweakerPtr collisionLayerTweaker;
|
||||
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
using SymbolVertexVector = gfx::VertexVector<SymbolStaticVertexAttributes>;
|
||||
using TriangleIndexVector = gfx::IndexVector<gfx::Triangles>;
|
||||
|
||||
std::shared_ptr<SymbolVertexVector> staticDataVertices;
|
||||
std::shared_ptr<TriangleIndexVector> staticDataIndices;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace mln
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <mln/renderer/layer_group.hpp>
|
||||
#include <mln/renderer/paint_parameters.hpp>
|
||||
#include <mln/renderer/paint_property_binder.hpp>
|
||||
#include <mln/renderer/layers/render_symbol_layer.hpp>
|
||||
#include <mln/renderer/render_tree.hpp>
|
||||
#include <mln/shaders/shader_program_base.hpp>
|
||||
#include <mln/shaders/symbol_layer_ubo.hpp>
|
||||
|
||||
@@ -175,8 +175,9 @@ public:
|
||||
void setInterleavedBuffer(InterleavedVertexBuffer& buffer) {
|
||||
interleavedVertexBuffer = &buffer;
|
||||
|
||||
if (vertexOffset == 0) {
|
||||
vertexOffset = interleavedVertexBuffer->extendVertexFormat<VertexFormat>();
|
||||
auto newVertexOffset = interleavedVertexBuffer->extendVertexFormat<VertexFormat>();
|
||||
if (vertexOffset == std::numeric_limits<size_t>::max()) {
|
||||
vertexOffset = newVertexOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +185,7 @@ public:
|
||||
|
||||
PaintPropertyStatistics<T> statistics;
|
||||
InterleavedVertexBuffer* interleavedVertexBuffer = nullptr;
|
||||
std::size_t vertexOffset = 0;
|
||||
std::size_t vertexOffset = std::numeric_limits<size_t>::max();
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
@@ -56,6 +56,15 @@ gfx::VertexVector<FillExtrusionStaticVertex> RenderStaticData::fillExtrusionVert
|
||||
return vertices;
|
||||
}
|
||||
|
||||
gfx::VertexVector<SymbolStaticVertexAttributes> RenderStaticData::symbolVertices() {
|
||||
gfx::VertexVector<HeatmapTextureLayoutVertex> vertices;
|
||||
vertices.emplace_back(FillExtrusionStaticVertex{0, 0});
|
||||
vertices.emplace_back(FillExtrusionStaticVertex{1, 0});
|
||||
vertices.emplace_back(FillExtrusionStaticVertex{0, 1});
|
||||
vertices.emplace_back(FillExtrusionStaticVertex{1, 1});
|
||||
return vertices;
|
||||
}
|
||||
|
||||
gfx::IndexVector<gfx::Triangles> RenderStaticData::quadTriangleIndices() {
|
||||
gfx::IndexVector<gfx::Triangles> indices;
|
||||
indices.emplace_back(0, 1, 2);
|
||||
@@ -85,6 +94,13 @@ gfx::IndexVector<gfx::Triangles> RenderStaticData::fillExtrusionTriangleIndices(
|
||||
return indices;
|
||||
}
|
||||
|
||||
gfx::IndexVector<gfx::Triangles> RenderStaticData::symbolTriangleIndices() {
|
||||
gfx::IndexVector<gfx::Triangles> indices;
|
||||
indices.emplace_back(0, 1, 2);
|
||||
indices.emplace_back(1, 2, 3);
|
||||
return indices;
|
||||
}
|
||||
|
||||
SegmentVector RenderStaticData::tileTriangleSegments() {
|
||||
SegmentVector segments;
|
||||
segments.emplace_back(0, 0, 4, 6);
|
||||
@@ -109,10 +125,12 @@ SegmentVector RenderStaticData::heatmapTextureSegments() {
|
||||
return segments;
|
||||
}
|
||||
|
||||
SegmentVector RenderStaticData::fillExtrusionSegments() {
|
||||
SegmentVector segments;
|
||||
segments.emplace_back(0, 0, 4, 6);
|
||||
return segments;
|
||||
SegmentBase RenderStaticData::fillExtrusionSegment() {
|
||||
return SegmentBase(0, 0, 4, 6, 0, 0);
|
||||
}
|
||||
|
||||
SegmentBase RenderStaticData::symbolSegment(std::size_t baseInstance, float sortKey) {
|
||||
return SegmentBase(0, 0, 4, 6, baseInstance, 0, sortKey);
|
||||
}
|
||||
|
||||
} // namespace mln
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <mln/renderer/buckets/heatmap_bucket.hpp>
|
||||
#include <mln/renderer/buckets/raster_bucket.hpp>
|
||||
#include <mln/renderer/buckets/fill_extrusion_bucket.hpp>
|
||||
#include <mln/renderer/buckets/symbol_bucket.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
@@ -30,16 +31,19 @@ public:
|
||||
static gfx::VertexVector<RasterLayoutVertex> rasterVertices();
|
||||
static gfx::VertexVector<HeatmapTextureLayoutVertex> heatmapTextureVertices();
|
||||
static gfx::VertexVector<FillExtrusionStaticVertex> fillExtrusionVertices();
|
||||
static gfx::VertexVector<SymbolStaticVertexAttributes> symbolVertices();
|
||||
|
||||
static gfx::IndexVector<gfx::Triangles> quadTriangleIndices();
|
||||
static gfx::IndexVector<gfx::LineStrip> tileLineStripIndices();
|
||||
static gfx::IndexVector<gfx::Triangles> fillExtrusionTriangleIndices();
|
||||
static gfx::IndexVector<gfx::Triangles> symbolTriangleIndices();
|
||||
|
||||
static SegmentVector tileTriangleSegments();
|
||||
static SegmentVector tileBorderSegments();
|
||||
static SegmentVector rasterSegments();
|
||||
static SegmentVector heatmapTextureSegments();
|
||||
static SegmentVector fillExtrusionSegments();
|
||||
static SegmentBase fillExtrusionSegment();
|
||||
static SegmentBase symbolSegment(std::size_t baseInstance, float sortKey);
|
||||
|
||||
std::optional<gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>> depthRenderbuffer;
|
||||
bool has3D = false;
|
||||
|
||||
@@ -25,6 +25,15 @@ MBGL_DEFINE_ATTRIBUTE(float, 2, shift);
|
||||
MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, decimals_ed);
|
||||
MBGL_DEFINE_ATTRIBUTE(int16_t, 2, normal2d);
|
||||
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
MBGL_DEFINE_ATTRIBUTE(uint16_t, 1, sorted_instance);
|
||||
MBGL_DEFINE_ATTRIBUTE(int16_t, 4, pos_scale);
|
||||
MBGL_DEFINE_ATTRIBUTE(int16_t, 4, offset_tltr);
|
||||
MBGL_DEFINE_ATTRIBUTE(int16_t, 4, offset_blbr);
|
||||
MBGL_DEFINE_ATTRIBUTE(uint16_t, 4, texture_rect);
|
||||
MBGL_DEFINE_ATTRIBUTE(uint16_t, 2, size_sdf);
|
||||
#endif
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
struct data {
|
||||
using Type = gfx::AttributeType<T, N>;
|
||||
|
||||
@@ -475,12 +475,12 @@ const std::vector<UniformBlockInfo> SymbolIconShaderInfo::uniformBlocks = {
|
||||
UniformBlockInfo{"SymbolEvaluatedPropsUBO", idSymbolEvaluatedPropsUBO},
|
||||
};
|
||||
const std::vector<AttributeInfo> SymbolIconShaderInfo::attributes = {
|
||||
AttributeInfo{"a_pos_offset", idSymbolPosOffsetVertexAttribute},
|
||||
AttributeInfo{"a_data", idSymbolDataVertexAttribute},
|
||||
AttributeInfo{"a_pixeloffset", idSymbolPixelOffsetVertexAttribute},
|
||||
AttributeInfo{"a_projected_pos", idSymbolProjectedPosVertexAttribute},
|
||||
AttributeInfo{"a_fade_opacity", idSymbolFadeOpacityVertexAttribute},
|
||||
AttributeInfo{"a_opacity", idSymbolOpacityVertexAttribute},
|
||||
AttributeInfo{"a_pos_offset", idSymbolPosOffsetAttribute},
|
||||
AttributeInfo{"a_data", idSymbolDataAttribute},
|
||||
AttributeInfo{"a_pixeloffset", idSymbolPixelOffsetAttribute},
|
||||
AttributeInfo{"a_projected_pos", idSymbolProjectedPosAttribute},
|
||||
AttributeInfo{"a_fade_opacity", idSymbolFadeOpacityAttribute},
|
||||
AttributeInfo{"a_opacity", idSymbolOpacityAttribute},
|
||||
};
|
||||
const std::vector<TextureInfo> SymbolIconShaderInfo::textures = {
|
||||
TextureInfo{"u_texture", idSymbolImageTexture},
|
||||
@@ -496,16 +496,16 @@ const std::vector<UniformBlockInfo> SymbolSDFShaderInfo::uniformBlocks = {
|
||||
UniformBlockInfo{"SymbolEvaluatedPropsUBO", idSymbolEvaluatedPropsUBO},
|
||||
};
|
||||
const std::vector<AttributeInfo> SymbolSDFShaderInfo::attributes = {
|
||||
AttributeInfo{"a_pos_offset", idSymbolPosOffsetVertexAttribute},
|
||||
AttributeInfo{"a_data", idSymbolDataVertexAttribute},
|
||||
AttributeInfo{"a_pixeloffset", idSymbolPixelOffsetVertexAttribute},
|
||||
AttributeInfo{"a_projected_pos", idSymbolProjectedPosVertexAttribute},
|
||||
AttributeInfo{"a_fade_opacity", idSymbolFadeOpacityVertexAttribute},
|
||||
AttributeInfo{"a_fill_color", idSymbolColorVertexAttribute},
|
||||
AttributeInfo{"a_halo_color", idSymbolHaloColorVertexAttribute},
|
||||
AttributeInfo{"a_opacity", idSymbolOpacityVertexAttribute},
|
||||
AttributeInfo{"a_halo_width", idSymbolHaloWidthVertexAttribute},
|
||||
AttributeInfo{"a_halo_blur", idSymbolHaloBlurVertexAttribute},
|
||||
AttributeInfo{"a_pos_offset", idSymbolPosOffsetAttribute},
|
||||
AttributeInfo{"a_data", idSymbolDataAttribute},
|
||||
AttributeInfo{"a_pixeloffset", idSymbolPixelOffsetAttribute},
|
||||
AttributeInfo{"a_projected_pos", idSymbolProjectedPosAttribute},
|
||||
AttributeInfo{"a_fade_opacity", idSymbolFadeOpacityAttribute},
|
||||
AttributeInfo{"a_fill_color", idSymbolColorAttribute},
|
||||
AttributeInfo{"a_halo_color", idSymbolHaloColorAttribute},
|
||||
AttributeInfo{"a_opacity", idSymbolOpacityAttribute},
|
||||
AttributeInfo{"a_halo_width", idSymbolHaloWidthAttribute},
|
||||
AttributeInfo{"a_halo_blur", idSymbolHaloBlurAttribute},
|
||||
};
|
||||
const std::vector<TextureInfo> SymbolSDFShaderInfo::textures = {
|
||||
TextureInfo{"u_texture", idSymbolImageTexture},
|
||||
@@ -521,15 +521,15 @@ const std::vector<UniformBlockInfo> SymbolTextAndIconShaderInfo::uniformBlocks =
|
||||
UniformBlockInfo{"SymbolEvaluatedPropsUBO", idSymbolEvaluatedPropsUBO},
|
||||
};
|
||||
const std::vector<AttributeInfo> SymbolTextAndIconShaderInfo::attributes = {
|
||||
AttributeInfo{"a_pos_offset", idSymbolPosOffsetVertexAttribute},
|
||||
AttributeInfo{"a_data", idSymbolDataVertexAttribute},
|
||||
AttributeInfo{"a_projected_pos", idSymbolProjectedPosVertexAttribute},
|
||||
AttributeInfo{"a_fade_opacity", idSymbolFadeOpacityVertexAttribute},
|
||||
AttributeInfo{"a_fill_color", idSymbolColorVertexAttribute},
|
||||
AttributeInfo{"a_halo_color", idSymbolHaloColorVertexAttribute},
|
||||
AttributeInfo{"a_opacity", idSymbolOpacityVertexAttribute},
|
||||
AttributeInfo{"a_halo_width", idSymbolHaloWidthVertexAttribute},
|
||||
AttributeInfo{"a_halo_blur", idSymbolHaloBlurVertexAttribute},
|
||||
AttributeInfo{"a_pos_offset", idSymbolPosOffsetAttribute},
|
||||
AttributeInfo{"a_data", idSymbolDataAttribute},
|
||||
AttributeInfo{"a_projected_pos", idSymbolProjectedPosAttribute},
|
||||
AttributeInfo{"a_fade_opacity", idSymbolFadeOpacityAttribute},
|
||||
AttributeInfo{"a_fill_color", idSymbolColorAttribute},
|
||||
AttributeInfo{"a_halo_color", idSymbolHaloColorAttribute},
|
||||
AttributeInfo{"a_opacity", idSymbolOpacityAttribute},
|
||||
AttributeInfo{"a_halo_width", idSymbolHaloWidthAttribute},
|
||||
AttributeInfo{"a_halo_blur", idSymbolHaloBlurAttribute},
|
||||
};
|
||||
const std::vector<TextureInfo> SymbolTextAndIconShaderInfo::textures = {
|
||||
TextureInfo{"u_texture", idSymbolImageTexture},
|
||||
|
||||
@@ -15,8 +15,8 @@ const std::array<AttributeInfo, 5> FillExtrusionShaderSource::attributes = {
|
||||
|
||||
// Data driven
|
||||
AttributeInfo{2, gfx::AttributeDataType::Float4, fillExtrusionUBOCount + 1, idFillExtrusionColorVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 1, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 1, idFillExtrusionHeightVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 1, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 1, idFillExtrusionHeightVertexAttribute},
|
||||
};
|
||||
const std::array<TextureInfo, 0> FillExtrusionShaderSource::textures = {};
|
||||
|
||||
@@ -35,8 +35,8 @@ const std::array<AttributeInfo, 5> FillExtrusionInstancedShaderSource::instanceA
|
||||
|
||||
// Data driven
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float4, fillExtrusionUBOCount + 2, idFillExtrusionColorVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 2, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 2, idFillExtrusionHeightVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 2, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 2, idFillExtrusionHeightVertexAttribute},
|
||||
};
|
||||
const std::array<TextureInfo, 0> FillExtrusionInstancedShaderSource::textures = {};
|
||||
|
||||
@@ -50,8 +50,8 @@ const std::array<AttributeInfo, 6> FillExtrusionPatternShaderSource::attributes
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort2, fillExtrusionUBOCount + 0, idFillExtrusionDecimalsEdAttribute},
|
||||
|
||||
// Data driven
|
||||
AttributeInfo{2, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 1, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 1, idFillExtrusionHeightVertexAttribute},
|
||||
AttributeInfo{2, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 1, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 1, idFillExtrusionHeightVertexAttribute},
|
||||
AttributeInfo{
|
||||
4, gfx::AttributeDataType::UShort4, fillExtrusionUBOCount + 1, idFillExtrusionPatternFromVertexAttribute},
|
||||
AttributeInfo{
|
||||
@@ -75,8 +75,8 @@ const std::array<AttributeInfo, 6> FillExtrusionPatternInstancedShaderSource::in
|
||||
AttributeInfo{2, gfx::AttributeDataType::UShort2, fillExtrusionUBOCount + 1, idFillExtrusionDecimalsEdAttribute},
|
||||
|
||||
// Data driven
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 2, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float, fillExtrusionUBOCount + 2, idFillExtrusionHeightVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 2, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float2, fillExtrusionUBOCount + 2, idFillExtrusionHeightVertexAttribute},
|
||||
AttributeInfo{
|
||||
5, gfx::AttributeDataType::UShort4, fillExtrusionUBOCount + 2, idFillExtrusionPatternFromVertexAttribute},
|
||||
AttributeInfo{
|
||||
|
||||
@@ -9,19 +9,28 @@ namespace shaders {
|
||||
|
||||
using SymbolIconShaderSource = ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::Metal>;
|
||||
|
||||
const std::array<AttributeInfo, 6> SymbolIconShaderSource::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short4, symbolUBOCount + 0, idSymbolPosOffsetVertexAttribute},
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort4, symbolUBOCount + 0, idSymbolDataVertexAttribute},
|
||||
AttributeInfo{2, gfx::AttributeDataType::Short4, symbolUBOCount + 0, idSymbolPixelOffsetVertexAttribute},
|
||||
const std::array<AttributeInfo, 1> SymbolIconShaderSource::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short2, symbolUBOCount + 0, idSymbolPosAttribute},
|
||||
|
||||
};
|
||||
const std::array<AttributeInfo, 10> SymbolIconShaderSource::instanceAttributes = {
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort, symbolUBOCount + 1, idSymbolSortedInstanceAttribute},
|
||||
|
||||
AttributeInfo{2, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolPosScaleAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolOffsetTlTrAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolOffsetBlBrAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::UShort4, symbolUBOCount + 2, idSymbolTextureRectAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolPixelOffsetAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::UShort4, symbolUBOCount + 2, idSymbolSizeSdfAttribute},
|
||||
|
||||
// Dynamic
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float3, symbolUBOCount + 1, idSymbolProjectedPosVertexAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float3, symbolUBOCount + 3, idSymbolProjectedPosAttribute},
|
||||
|
||||
// Opacity
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float, symbolUBOCount + 2, idSymbolFadeOpacityVertexAttribute},
|
||||
AttributeInfo{9, gfx::AttributeDataType::Float, symbolUBOCount + 4, idSymbolFadeOpacityAttribute},
|
||||
|
||||
// Data driven
|
||||
AttributeInfo{5, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolOpacityVertexAttribute},
|
||||
AttributeInfo{10, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolOpacityAttribute},
|
||||
};
|
||||
const std::array<TextureInfo, 1> SymbolIconShaderSource::textures = {
|
||||
TextureInfo{0, idSymbolImageTexture},
|
||||
@@ -32,23 +41,32 @@ const std::array<TextureInfo, 1> SymbolIconShaderSource::textures = {
|
||||
|
||||
using SymbolSDFShaderSource = ShaderSource<BuiltIn::SymbolSDFShader, gfx::Backend::Type::Metal>;
|
||||
|
||||
const std::array<AttributeInfo, 10> SymbolSDFShaderSource::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short4, symbolUBOCount + 0, idSymbolPosOffsetVertexAttribute},
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort4, symbolUBOCount + 0, idSymbolDataVertexAttribute},
|
||||
AttributeInfo{2, gfx::AttributeDataType::Short4, symbolUBOCount + 0, idSymbolPixelOffsetVertexAttribute},
|
||||
const std::array<AttributeInfo, 1> SymbolSDFShaderSource::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short2, symbolUBOCount + 0, idSymbolPosAttribute},
|
||||
|
||||
};
|
||||
const std::array<AttributeInfo, 14> SymbolSDFShaderSource::instanceAttributes = {
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort, symbolUBOCount + 1, idSymbolSortedInstanceAttribute},
|
||||
|
||||
AttributeInfo{2, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolPosScaleAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolOffsetTlTrAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolOffsetBlBrAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::UShort4, symbolUBOCount + 2, idSymbolTextureRectAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolPixelOffsetAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::UShort2, symbolUBOCount + 2, idSymbolSizeSdfAttribute},
|
||||
|
||||
// Dynamic
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float3, symbolUBOCount + 1, idSymbolProjectedPosVertexAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float3, symbolUBOCount + 3, idSymbolProjectedPosAttribute},
|
||||
|
||||
// Opacity
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float, symbolUBOCount + 2, idSymbolFadeOpacityVertexAttribute},
|
||||
AttributeInfo{9, gfx::AttributeDataType::Float, symbolUBOCount + 4, idSymbolFadeOpacityAttribute},
|
||||
|
||||
// Data driven
|
||||
AttributeInfo{5, gfx::AttributeDataType::Float4, symbolUBOCount + 3, idSymbolColorVertexAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Float4, symbolUBOCount + 3, idSymbolHaloColorVertexAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolOpacityVertexAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolHaloWidthVertexAttribute},
|
||||
AttributeInfo{9, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolHaloBlurVertexAttribute},
|
||||
AttributeInfo{10, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolOpacityAttribute},
|
||||
AttributeInfo{11, gfx::AttributeDataType::Float4, symbolUBOCount + 5, idSymbolColorAttribute},
|
||||
AttributeInfo{12, gfx::AttributeDataType::Float4, symbolUBOCount + 5, idSymbolHaloColorAttribute},
|
||||
AttributeInfo{13, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolHaloWidthAttribute},
|
||||
AttributeInfo{14, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolHaloBlurAttribute},
|
||||
};
|
||||
const std::array<TextureInfo, 1> SymbolSDFShaderSource::textures = {
|
||||
TextureInfo{0, idSymbolImageTexture},
|
||||
@@ -59,22 +77,32 @@ const std::array<TextureInfo, 1> SymbolSDFShaderSource::textures = {
|
||||
|
||||
using SymbolTextAndIconShaderSource = ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Metal>;
|
||||
|
||||
const std::array<AttributeInfo, 9> SymbolTextAndIconShaderSource::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short4, symbolUBOCount + 0, idSymbolPosOffsetVertexAttribute},
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort4, symbolUBOCount + 0, idSymbolDataVertexAttribute},
|
||||
const std::array<AttributeInfo, 1> SymbolTextAndIconShaderSource::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short2, symbolUBOCount + 0, idSymbolPosAttribute},
|
||||
|
||||
};
|
||||
const std::array<AttributeInfo, 14> SymbolTextAndIconShaderSource::instanceAttributes = {
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort, symbolUBOCount + 1, idSymbolSortedInstanceAttribute},
|
||||
|
||||
AttributeInfo{2, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolPosScaleAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolOffsetTlTrAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolOffsetBlBrAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::UShort4, symbolUBOCount + 2, idSymbolTextureRectAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Short4, symbolUBOCount + 2, idSymbolPixelOffsetAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::UShort2, symbolUBOCount + 2, idSymbolSizeSdfAttribute},
|
||||
|
||||
// Dynamic
|
||||
AttributeInfo{2, gfx::AttributeDataType::Float3, symbolUBOCount + 1, idSymbolProjectedPosVertexAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float3, symbolUBOCount + 3, idSymbolProjectedPosAttribute},
|
||||
|
||||
// Opacity
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float, symbolUBOCount + 2, idSymbolFadeOpacityVertexAttribute},
|
||||
AttributeInfo{9, gfx::AttributeDataType::Float, symbolUBOCount + 4, idSymbolFadeOpacityAttribute},
|
||||
|
||||
// Data driven
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float4, symbolUBOCount + 3, idSymbolColorVertexAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Float4, symbolUBOCount + 3, idSymbolHaloColorVertexAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolOpacityVertexAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolHaloWidthVertexAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float, symbolUBOCount + 3, idSymbolHaloBlurVertexAttribute},
|
||||
AttributeInfo{10, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolOpacityAttribute},
|
||||
AttributeInfo{11, gfx::AttributeDataType::Float4, symbolUBOCount + 5, idSymbolColorAttribute},
|
||||
AttributeInfo{12, gfx::AttributeDataType::Float4, symbolUBOCount + 5, idSymbolHaloColorAttribute},
|
||||
AttributeInfo{13, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolHaloWidthAttribute},
|
||||
AttributeInfo{14, gfx::AttributeDataType::Float2, symbolUBOCount + 5, idSymbolHaloBlurAttribute},
|
||||
};
|
||||
const std::array<TextureInfo, 2> SymbolTextAndIconShaderSource::textures = {
|
||||
TextureInfo{0, idSymbolImageTexture},
|
||||
|
||||
@@ -15,11 +15,15 @@ public:
|
||||
std::size_t indexOffset_,
|
||||
std::size_t vertexLength_ = 0,
|
||||
std::size_t indexLength_ = 0,
|
||||
std::size_t baseInstance_ = 0,
|
||||
std::size_t instanceCount_ = 1,
|
||||
float sortKey_ = 0.0f)
|
||||
: vertexOffset(vertexOffset_),
|
||||
indexOffset(indexOffset_),
|
||||
vertexLength(vertexLength_),
|
||||
indexLength(indexLength_),
|
||||
baseInstance(baseInstance_),
|
||||
instanceCount(instanceCount_),
|
||||
sortKey(sortKey_) {}
|
||||
|
||||
// FIXME: clang-tidy-8 still complains here and clang-cl
|
||||
@@ -35,6 +39,9 @@ public:
|
||||
std::size_t vertexLength;
|
||||
std::size_t indexLength;
|
||||
|
||||
const std::size_t baseInstance;
|
||||
std::size_t instanceCount;
|
||||
|
||||
// One DrawScope per layer ID. This minimizes rebinding in cases where
|
||||
// several layers share buckets but have different sets of active
|
||||
// attributes. This can happen:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
namespace mln {
|
||||
namespace shaders {
|
||||
|
||||
// idFillExtrusionInstanced is shared between instanced and non-instanced drawables
|
||||
// idFillExtrusionInstancedDrawableUBO is shared between instanced and non-instanced drawables
|
||||
|
||||
//
|
||||
// Fill extrusion
|
||||
@@ -13,11 +13,13 @@ namespace shaders {
|
||||
using FillExtrusionShaderSource = ShaderSource<BuiltIn::FillExtrusionShader, gfx::Backend::Type::Vulkan>;
|
||||
|
||||
const std::array<AttributeInfo, 5> FillExtrusionShaderSource::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute, idFillExtrusionInstanced},
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstanced},
|
||||
AttributeInfo{
|
||||
0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute, idFillExtrusionInstancedDrawableUBO},
|
||||
AttributeInfo{
|
||||
1, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstancedDrawableUBO},
|
||||
AttributeInfo{2, gfx::AttributeDataType::Float4, idFillExtrusionColorVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float2, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float2, idFillExtrusionHeightVertexAttribute},
|
||||
};
|
||||
const std::array<TextureInfo, 0> FillExtrusionShaderSource::textures = {};
|
||||
|
||||
@@ -31,13 +33,15 @@ const std::array<AttributeInfo, 1> FillExtrusionInstancedShaderSource::attribute
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute},
|
||||
};
|
||||
const std::array<AttributeInfo, 5> FillExtrusionInstancedShaderSource::instanceAttributes = {
|
||||
AttributeInfo{1, gfx::AttributeDataType::Short2, idFillExtrusionOutlinePosAttribute, idFillExtrusionInstanced},
|
||||
AttributeInfo{2, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstanced},
|
||||
AttributeInfo{
|
||||
1, gfx::AttributeDataType::Short2, idFillExtrusionOutlinePosAttribute, idFillExtrusionInstancedDrawableUBO},
|
||||
AttributeInfo{
|
||||
2, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstancedDrawableUBO},
|
||||
|
||||
// Data driven
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float4, idFillExtrusionColorVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float2, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Float2, idFillExtrusionHeightVertexAttribute},
|
||||
};
|
||||
const std::array<TextureInfo, 0> FillExtrusionInstancedShaderSource::textures = {};
|
||||
|
||||
@@ -47,10 +51,12 @@ const std::array<TextureInfo, 0> FillExtrusionInstancedShaderSource::textures =
|
||||
using FillExtrusionPatternShaderSource = ShaderSource<BuiltIn::FillExtrusionPatternShader, gfx::Backend::Type::Vulkan>;
|
||||
|
||||
const std::array<AttributeInfo, 6> FillExtrusionPatternShaderSource::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute, idFillExtrusionInstanced},
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstanced},
|
||||
AttributeInfo{2, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute},
|
||||
AttributeInfo{
|
||||
0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute, idFillExtrusionInstancedDrawableUBO},
|
||||
AttributeInfo{
|
||||
1, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstancedDrawableUBO},
|
||||
AttributeInfo{2, gfx::AttributeDataType::Float2, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float2, idFillExtrusionHeightVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::UShort4, idFillExtrusionPatternFromVertexAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::UShort4, idFillExtrusionPatternToVertexAttribute},
|
||||
};
|
||||
@@ -68,12 +74,14 @@ const std::array<AttributeInfo, 1> FillExtrusionPatternInstancedShaderSource::at
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute},
|
||||
};
|
||||
const std::array<AttributeInfo, 6> FillExtrusionPatternInstancedShaderSource::instanceAttributes = {
|
||||
AttributeInfo{1, gfx::AttributeDataType::Short2, idFillExtrusionOutlinePosAttribute, idFillExtrusionInstanced},
|
||||
AttributeInfo{2, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstanced},
|
||||
AttributeInfo{
|
||||
1, gfx::AttributeDataType::Short2, idFillExtrusionOutlinePosAttribute, idFillExtrusionInstancedDrawableUBO},
|
||||
AttributeInfo{
|
||||
2, gfx::AttributeDataType::UShort2, idFillExtrusionDecimalsEdAttribute, idFillExtrusionInstancedDrawableUBO},
|
||||
|
||||
// Data driven
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float, idFillExtrusionHeightVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float2, idFillExtrusionBaseVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float2, idFillExtrusionHeightVertexAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::UShort4, idFillExtrusionPatternFromVertexAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::UShort4, idFillExtrusionPatternToVertexAttribute},
|
||||
};
|
||||
|
||||
@@ -10,16 +10,27 @@ namespace shaders {
|
||||
|
||||
using SymbolIconShaderSource = ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::Vulkan>;
|
||||
|
||||
const std::array<AttributeInfo, 6> SymbolIconShaderSource::attributes = {
|
||||
const std::array<AttributeInfo, 1> SymbolIconShaderSource::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short2, idSymbolPosAttribute},
|
||||
};
|
||||
const std::array<AttributeInfo, 10> SymbolIconShaderSource::instanceAttributes = {
|
||||
// always attributes
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short4, idSymbolPosOffsetVertexAttribute},
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort4, idSymbolDataVertexAttribute},
|
||||
AttributeInfo{2, gfx::AttributeDataType::Short4, idSymbolPixelOffsetVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float3, idSymbolProjectedPosVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float, idSymbolFadeOpacityVertexAttribute},
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort, idSymbolSortedInstanceAttribute},
|
||||
|
||||
AttributeInfo{2, gfx::AttributeDataType::Short4, idSymbolPosScaleAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolOffsetTlTrAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Short4, idSymbolOffsetBlBrAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{5, gfx::AttributeDataType::UShort4, idSymbolTextureRectAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Short4, idSymbolPixelOffsetAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{7, gfx::AttributeDataType::UShort4, idSymbolSizeSdfAttribute, idSymbolInstancedDrawableUBO},
|
||||
|
||||
AttributeInfo{
|
||||
8, gfx::AttributeDataType::Float3, idSymbolProjectedPosAttribute, idSymbolDynamicInstancedDrawableUBO},
|
||||
|
||||
AttributeInfo{9, gfx::AttributeDataType::Float, idSymbolFadeOpacityAttribute, idSymbolOpacityInstancedDrawableUBO},
|
||||
|
||||
// sometimes uniforms
|
||||
AttributeInfo{5, gfx::AttributeDataType::Float, idSymbolOpacityVertexAttribute},
|
||||
AttributeInfo{10, gfx::AttributeDataType::Float2, idSymbolOpacityAttribute, idSymbolDataInstancedDrawableUBO},
|
||||
};
|
||||
const std::array<TextureInfo, 1> SymbolIconShaderSource::textures = {
|
||||
TextureInfo{0, idSymbolImageTexture},
|
||||
@@ -30,20 +41,32 @@ const std::array<TextureInfo, 1> SymbolIconShaderSource::textures = {
|
||||
|
||||
using SymbolSDFShaderSource = ShaderSource<BuiltIn::SymbolSDFShader, gfx::Backend::Type::Vulkan>;
|
||||
|
||||
const std::array<AttributeInfo, 10> SymbolSDFShaderSource::attributes = {
|
||||
const std::array<AttributeInfo, 1> SymbolSDFShaderSource::attributes = {
|
||||
// always attributes
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short4, idSymbolPosOffsetVertexAttribute},
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort4, idSymbolDataVertexAttribute},
|
||||
AttributeInfo{2, gfx::AttributeDataType::Short4, idSymbolPixelOffsetVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float3, idSymbolProjectedPosVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float, idSymbolFadeOpacityVertexAttribute},
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short2, idSymbolPosAttribute},
|
||||
};
|
||||
const std::array<AttributeInfo, 14> SymbolSDFShaderSource::instanceAttributes = {
|
||||
// always attributes
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort, idSymbolSortedInstanceAttribute},
|
||||
|
||||
AttributeInfo{2, gfx::AttributeDataType::Short4, idSymbolPosScaleAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolOffsetTlTrAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Short4, idSymbolOffsetBlBrAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{5, gfx::AttributeDataType::UShort4, idSymbolTextureRectAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Short4, idSymbolPixelOffsetAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{7, gfx::AttributeDataType::UShort4, idSymbolSizeSdfAttribute, idSymbolInstancedDrawableUBO},
|
||||
|
||||
AttributeInfo{
|
||||
8, gfx::AttributeDataType::Float3, idSymbolProjectedPosAttribute, idSymbolDynamicInstancedDrawableUBO},
|
||||
|
||||
AttributeInfo{9, gfx::AttributeDataType::Float, idSymbolFadeOpacityAttribute, idSymbolOpacityInstancedDrawableUBO},
|
||||
|
||||
// sometimes uniforms
|
||||
AttributeInfo{5, gfx::AttributeDataType::Float4, idSymbolColorVertexAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Float4, idSymbolHaloColorVertexAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::Float, idSymbolOpacityVertexAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float, idSymbolHaloWidthVertexAttribute},
|
||||
AttributeInfo{9, gfx::AttributeDataType::Float, idSymbolHaloBlurVertexAttribute},
|
||||
AttributeInfo{10, gfx::AttributeDataType::Float2, idSymbolOpacityAttribute, idSymbolDataInstancedDrawableUBO},
|
||||
AttributeInfo{11, gfx::AttributeDataType::Float4, idSymbolColorAttribute, idSymbolDataInstancedDrawableUBO},
|
||||
AttributeInfo{12, gfx::AttributeDataType::Float4, idSymbolHaloColorAttribute, idSymbolDataInstancedDrawableUBO},
|
||||
AttributeInfo{13, gfx::AttributeDataType::Float2, idSymbolHaloWidthAttribute, idSymbolDataInstancedDrawableUBO},
|
||||
AttributeInfo{14, gfx::AttributeDataType::Float2, idSymbolHaloBlurAttribute, idSymbolDataInstancedDrawableUBO},
|
||||
};
|
||||
const std::array<TextureInfo, 1> SymbolSDFShaderSource::textures = {
|
||||
TextureInfo{0, idSymbolImageTexture},
|
||||
@@ -54,19 +77,32 @@ const std::array<TextureInfo, 1> SymbolSDFShaderSource::textures = {
|
||||
|
||||
using SymbolTextAndIconShaderSource = ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::Vulkan>;
|
||||
|
||||
const std::array<AttributeInfo, 9> SymbolTextAndIconShaderSource::attributes = {
|
||||
const std::array<AttributeInfo, 1> SymbolTextAndIconShaderSource::attributes = {
|
||||
// always attributes
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short4, idSymbolPosOffsetVertexAttribute},
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort4, idSymbolDataVertexAttribute},
|
||||
AttributeInfo{2, gfx::AttributeDataType::Float3, idSymbolProjectedPosVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float, idSymbolFadeOpacityVertexAttribute},
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short2, idSymbolPosAttribute},
|
||||
};
|
||||
const std::array<AttributeInfo, 14> SymbolTextAndIconShaderSource::instanceAttributes = {
|
||||
// always attributes
|
||||
AttributeInfo{1, gfx::AttributeDataType::UShort, idSymbolSortedInstanceAttribute},
|
||||
|
||||
AttributeInfo{2, gfx::AttributeDataType::Short4, idSymbolPosScaleAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolOffsetTlTrAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Short4, idSymbolOffsetBlBrAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{5, gfx::AttributeDataType::UShort4, idSymbolTextureRectAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Short4, idSymbolPixelOffsetAttribute, idSymbolInstancedDrawableUBO},
|
||||
AttributeInfo{7, gfx::AttributeDataType::UShort4, idSymbolSizeSdfAttribute, idSymbolInstancedDrawableUBO},
|
||||
|
||||
AttributeInfo{
|
||||
8, gfx::AttributeDataType::Float3, idSymbolProjectedPosAttribute, idSymbolDynamicInstancedDrawableUBO},
|
||||
|
||||
AttributeInfo{9, gfx::AttributeDataType::Float, idSymbolFadeOpacityAttribute, idSymbolOpacityInstancedDrawableUBO},
|
||||
|
||||
// sometimes uniforms
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float4, idSymbolColorVertexAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Float4, idSymbolHaloColorVertexAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Float, idSymbolOpacityVertexAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::Float, idSymbolHaloWidthVertexAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float, idSymbolHaloBlurVertexAttribute},
|
||||
AttributeInfo{10, gfx::AttributeDataType::Float2, idSymbolOpacityAttribute, idSymbolDataInstancedDrawableUBO},
|
||||
AttributeInfo{11, gfx::AttributeDataType::Float4, idSymbolColorAttribute, idSymbolDataInstancedDrawableUBO},
|
||||
AttributeInfo{12, gfx::AttributeDataType::Float4, idSymbolHaloColorAttribute, idSymbolDataInstancedDrawableUBO},
|
||||
AttributeInfo{13, gfx::AttributeDataType::Float2, idSymbolHaloWidthAttribute, idSymbolDataInstancedDrawableUBO},
|
||||
AttributeInfo{14, gfx::AttributeDataType::Float2, idSymbolHaloBlurAttribute, idSymbolDataInstancedDrawableUBO},
|
||||
};
|
||||
const std::array<TextureInfo, 2> SymbolTextAndIconShaderSource::textures = {
|
||||
TextureInfo{0, idSymbolImageTexture},
|
||||
|
||||
@@ -9,12 +9,12 @@ namespace shaders {
|
||||
using SymbolIconShaderSource = ShaderSource<BuiltIn::SymbolIconShader, gfx::Backend::Type::WebGPU>;
|
||||
|
||||
const std::array<AttributeInfo, 6> SymbolIconShaderSource::attributes = {
|
||||
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolPosOffsetVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::UShort4, idSymbolDataVertexAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Short4, idSymbolPixelOffsetVertexAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Float3, idSymbolProjectedPosVertexAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::Float, idSymbolFadeOpacityVertexAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float, idSymbolOpacityVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolPosOffsetAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::UShort4, idSymbolDataAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Short4, idSymbolPixelOffsetAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Float3, idSymbolProjectedPosAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::Float, idSymbolFadeOpacityAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float, idSymbolOpacityAttribute},
|
||||
};
|
||||
|
||||
const std::array<TextureInfo, 1> SymbolIconShaderSource::textures = {
|
||||
@@ -25,16 +25,16 @@ const std::array<TextureInfo, 1> SymbolIconShaderSource::textures = {
|
||||
using SymbolSDFShaderSource = ShaderSource<BuiltIn::SymbolSDFShader, gfx::Backend::Type::WebGPU>;
|
||||
|
||||
const std::array<AttributeInfo, 10> SymbolSDFShaderSource::attributes = {
|
||||
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolPosOffsetVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::UShort4, idSymbolDataVertexAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Short4, idSymbolPixelOffsetVertexAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Float3, idSymbolProjectedPosVertexAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::Float, idSymbolFadeOpacityVertexAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float4, idSymbolColorVertexAttribute},
|
||||
AttributeInfo{9, gfx::AttributeDataType::Float4, idSymbolHaloColorVertexAttribute},
|
||||
AttributeInfo{10, gfx::AttributeDataType::Float, idSymbolOpacityVertexAttribute},
|
||||
AttributeInfo{11, gfx::AttributeDataType::Float, idSymbolHaloWidthVertexAttribute},
|
||||
AttributeInfo{12, gfx::AttributeDataType::Float, idSymbolHaloBlurVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolPosOffsetAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::UShort4, idSymbolDataAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Short4, idSymbolPixelOffsetAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Float3, idSymbolProjectedPosAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::Float, idSymbolFadeOpacityAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float4, idSymbolColorAttribute},
|
||||
AttributeInfo{9, gfx::AttributeDataType::Float4, idSymbolHaloColorAttribute},
|
||||
AttributeInfo{10, gfx::AttributeDataType::Float, idSymbolOpacityAttribute},
|
||||
AttributeInfo{11, gfx::AttributeDataType::Float, idSymbolHaloWidthAttribute},
|
||||
AttributeInfo{12, gfx::AttributeDataType::Float, idSymbolHaloBlurAttribute},
|
||||
};
|
||||
|
||||
const std::array<TextureInfo, 1> SymbolSDFShaderSource::textures = {
|
||||
@@ -45,15 +45,15 @@ const std::array<TextureInfo, 1> SymbolSDFShaderSource::textures = {
|
||||
using SymbolTextAndIconShaderSource = ShaderSource<BuiltIn::SymbolTextAndIconShader, gfx::Backend::Type::WebGPU>;
|
||||
|
||||
const std::array<AttributeInfo, 9> SymbolTextAndIconShaderSource::attributes = {
|
||||
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolPosOffsetVertexAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::UShort4, idSymbolDataVertexAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Float3, idSymbolProjectedPosVertexAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Float, idSymbolFadeOpacityVertexAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::Float4, idSymbolColorVertexAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float4, idSymbolHaloColorVertexAttribute},
|
||||
AttributeInfo{9, gfx::AttributeDataType::Float, idSymbolOpacityVertexAttribute},
|
||||
AttributeInfo{10, gfx::AttributeDataType::Float, idSymbolHaloWidthVertexAttribute},
|
||||
AttributeInfo{11, gfx::AttributeDataType::Float, idSymbolHaloBlurVertexAttribute},
|
||||
AttributeInfo{3, gfx::AttributeDataType::Short4, idSymbolPosOffsetAttribute},
|
||||
AttributeInfo{4, gfx::AttributeDataType::UShort4, idSymbolDataAttribute},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Float3, idSymbolProjectedPosAttribute},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Float, idSymbolFadeOpacityAttribute},
|
||||
AttributeInfo{7, gfx::AttributeDataType::Float4, idSymbolColorAttribute},
|
||||
AttributeInfo{8, gfx::AttributeDataType::Float4, idSymbolHaloColorAttribute},
|
||||
AttributeInfo{9, gfx::AttributeDataType::Float, idSymbolOpacityAttribute},
|
||||
AttributeInfo{10, gfx::AttributeDataType::Float, idSymbolHaloWidthAttribute},
|
||||
AttributeInfo{11, gfx::AttributeDataType::Float, idSymbolHaloBlurAttribute},
|
||||
};
|
||||
|
||||
const std::array<TextureInfo, 2> SymbolTextAndIconShaderSource::textures = {
|
||||
|
||||
@@ -773,9 +773,9 @@ Point<float> calculateVariableRenderShift(style::SymbolAnchorType anchor,
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
|
||||
const TransformState& state,
|
||||
const RenderTile& tile) const {
|
||||
bool Placement::updateBucketDynamicAttributeData(SymbolBucket& bucket,
|
||||
const TransformState& state,
|
||||
const RenderTile& tile) const {
|
||||
using namespace style;
|
||||
const auto& layout = *bucket.layout;
|
||||
const bool alongLine = layout.get<SymbolPlacement>() != SymbolPlacementType::Point;
|
||||
@@ -790,7 +790,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
|
||||
const bool pitchWithMap = layout.get<style::IconPitchAlignment>() == style::AlignmentType::Map;
|
||||
const bool keepUpright = layout.get<style::IconKeepUpright>();
|
||||
if (bucket.hasSdfIconData()) {
|
||||
reprojectLineLabels(bucket.sdfIcon.dynamicVertices(),
|
||||
reprojectLineLabels(bucket.sdfIcon.dynamicAttributeData(),
|
||||
bucket.sdfIcon.placedSymbols,
|
||||
tile.matrix,
|
||||
pitchWithMap,
|
||||
@@ -802,7 +802,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
|
||||
result = true;
|
||||
}
|
||||
if (bucket.hasIconData()) {
|
||||
reprojectLineLabels(bucket.icon.dynamicVertices(),
|
||||
reprojectLineLabels(bucket.icon.dynamicAttributeData(),
|
||||
bucket.icon.placedSymbols,
|
||||
tile.matrix,
|
||||
pitchWithMap,
|
||||
@@ -818,7 +818,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
|
||||
if (bucket.hasTextData() && layout.get<TextRotationAlignment>() == AlignmentType::Map) {
|
||||
const bool pitchWithMap = layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map;
|
||||
const bool keepUpright = layout.get<style::TextKeepUpright>();
|
||||
reprojectLineLabels(bucket.text.dynamicVertices(),
|
||||
reprojectLineLabels(bucket.text.dynamicAttributeData(),
|
||||
bucket.text.placedSymbols,
|
||||
tile.matrix,
|
||||
pitchWithMap,
|
||||
@@ -830,7 +830,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
|
||||
result = true;
|
||||
}
|
||||
} else if (hasVariableAnchors) {
|
||||
bucket.text.sharedDynamicVertices->clear();
|
||||
bucket.text.sharedDynamicAttributeData->clear();
|
||||
bucket.hasVariablePlacement = false;
|
||||
|
||||
const auto partiallyEvaluatedSize = bucket.textSizeBinder->evaluateForZoom(static_cast<float>(state.getZoom()));
|
||||
@@ -859,7 +859,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
|
||||
// These symbols are from a justification that is not being
|
||||
// used, or a label that wasn't placed so we don't need to do
|
||||
// the extra math to figure out what incremental shift to apply.
|
||||
hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicVertices());
|
||||
hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicAttributeData());
|
||||
} else {
|
||||
const Point<float> tileAnchor = symbol.anchorPoint;
|
||||
const auto projectedAnchor = project(tileAnchor, pitchWithMap ? tile.matrix : labelPlaneMatrix);
|
||||
@@ -902,26 +902,26 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
|
||||
}
|
||||
|
||||
for (std::size_t j = 0; j < symbol.glyphOffsets.size(); ++j) {
|
||||
addDynamicAttributes(shiftedAnchor, symbol.angle, bucket.text.dynamicVertices());
|
||||
addDynamicAttributes(shiftedAnchor, symbol.angle, bucket.text.dynamicAttributeData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updateTextFitIcon && bucket.hasVariablePlacement) {
|
||||
auto updateIcon = [&](SymbolBucket::Buffer& iconBuffer) {
|
||||
iconBuffer.sharedDynamicVertices->clear();
|
||||
iconBuffer.sharedDynamicAttributeData->clear();
|
||||
for (std::size_t i = 0; i < iconBuffer.placedSymbols.size(); ++i) {
|
||||
const PlacedSymbol& placedIcon = iconBuffer.placedSymbols[i];
|
||||
if (placedIcon.hidden || (!placedIcon.placedOrientation && bucket.allowVerticalPlacement)) {
|
||||
hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicVertices());
|
||||
hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicAttributeData());
|
||||
} else {
|
||||
const auto& pair = placedTextShifts.find(i);
|
||||
if (pair == placedTextShifts.end()) {
|
||||
hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicVertices());
|
||||
hideGlyphs(placedIcon.glyphOffsets.size(), iconBuffer.dynamicAttributeData());
|
||||
} else {
|
||||
for (std::size_t j = 0; j < placedIcon.glyphOffsets.size(); ++j) {
|
||||
addDynamicAttributes(
|
||||
pair->second.second, placedIcon.angle, iconBuffer.dynamicVertices());
|
||||
pair->second.second, placedIcon.angle, iconBuffer.dynamicAttributeData());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -933,24 +933,24 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
|
||||
|
||||
result = true;
|
||||
} else if (bucket.allowVerticalPlacement && bucket.hasTextData()) {
|
||||
const auto updateDynamicVertices = [](SymbolBucket::Buffer& buffer) {
|
||||
buffer.sharedDynamicVertices->clear();
|
||||
const auto updateDynamicAttributeData = [](SymbolBucket::Buffer& buffer) {
|
||||
buffer.sharedDynamicAttributeData->clear();
|
||||
for (const PlacedSymbol& symbol : buffer.placedSymbols) {
|
||||
if (symbol.hidden || !symbol.placedOrientation) {
|
||||
hideGlyphs(symbol.glyphOffsets.size(), buffer.dynamicVertices());
|
||||
hideGlyphs(symbol.glyphOffsets.size(), buffer.dynamicAttributeData());
|
||||
} else {
|
||||
for (std::size_t j = 0; j < symbol.glyphOffsets.size(); ++j) {
|
||||
addDynamicAttributes(symbol.anchorPoint, symbol.angle, buffer.dynamicVertices());
|
||||
addDynamicAttributes(symbol.anchorPoint, symbol.angle, buffer.dynamicAttributeData());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
updateDynamicVertices(bucket.text);
|
||||
updateDynamicAttributeData(bucket.text);
|
||||
// When text box is rotated, icon-text-fit icon must be rotated as well.
|
||||
if (updateTextFitIcon) {
|
||||
updateDynamicVertices(bucket.icon);
|
||||
updateDynamicVertices(bucket.sdfIcon);
|
||||
updateDynamicAttributeData(bucket.icon);
|
||||
updateDynamicAttributeData(bucket.sdfIcon);
|
||||
}
|
||||
|
||||
result = true;
|
||||
@@ -962,9 +962,9 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket,
|
||||
void Placement::updateBucketOpacities(SymbolBucket& bucket,
|
||||
const TransformState& state,
|
||||
std::set<uint32_t>& seenCrossTileIDs) const {
|
||||
if (bucket.hasTextData()) bucket.text.sharedOpacityVertices->clear();
|
||||
if (bucket.hasIconData()) bucket.icon.sharedOpacityVertices->clear();
|
||||
if (bucket.hasSdfIconData()) bucket.sdfIcon.sharedOpacityVertices->clear();
|
||||
if (bucket.hasTextData()) bucket.text.sharedOpacityAttributeData->clear();
|
||||
if (bucket.hasIconData()) bucket.icon.sharedOpacityAttributeData->clear();
|
||||
if (bucket.hasSdfIconData()) bucket.sdfIcon.sharedOpacityAttributeData->clear();
|
||||
if (bucket.hasIconCollisionBoxData()) bucket.iconCollisionBox->dynamicVertices().clear();
|
||||
if (bucket.hasIconCollisionCircleData()) bucket.iconCollisionCircle->dynamicVertices().clear();
|
||||
if (bucket.hasTextCollisionBoxData()) bucket.textCollisionBox->dynamicVertices().clear();
|
||||
@@ -1014,32 +1014,37 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket,
|
||||
SYM_GUARD_LOC))
|
||||
return;
|
||||
}
|
||||
#if MLN_USE_SYMBOL_INSTANCING
|
||||
const size_t count = 1;
|
||||
#else
|
||||
const size_t count = 4;
|
||||
#endif
|
||||
if (symbolInstance.hasText()) {
|
||||
size_t textOpacityVerticesSize = 0u;
|
||||
const auto& opacityVertex = SymbolBucket::opacityVertex(opacityState.text.placed,
|
||||
opacityState.text.opacity);
|
||||
const auto& opacityAttributes = SymbolBucket::opacityAttributes(opacityState.text.placed,
|
||||
opacityState.text.opacity);
|
||||
if (symbolInstance.getPlacedRightTextIndex()) {
|
||||
textOpacityVerticesSize += symbolInstance.getRightJustifiedGlyphQuadsSize() * 4;
|
||||
textOpacityVerticesSize += symbolInstance.getRightJustifiedGlyphQuadsSize() * count;
|
||||
PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.getPlacedRightTextIndex()];
|
||||
placed.hidden = opacityState.isHidden();
|
||||
}
|
||||
if (symbolInstance.getPlacedCenterTextIndex() && !symbolInstance.getSingleLine()) {
|
||||
textOpacityVerticesSize += symbolInstance.getCenterJustifiedGlyphQuadsSize() * 4;
|
||||
textOpacityVerticesSize += symbolInstance.getCenterJustifiedGlyphQuadsSize() * count;
|
||||
PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.getPlacedCenterTextIndex()];
|
||||
placed.hidden = opacityState.isHidden();
|
||||
}
|
||||
if (symbolInstance.getPlacedLeftTextIndex() && !symbolInstance.getSingleLine()) {
|
||||
textOpacityVerticesSize += symbolInstance.getLeftJustifiedGlyphQuadsSize() * 4;
|
||||
textOpacityVerticesSize += symbolInstance.getLeftJustifiedGlyphQuadsSize() * count;
|
||||
PlacedSymbol& placed = bucket.text.placedSymbols[*symbolInstance.getPlacedLeftTextIndex()];
|
||||
placed.hidden = opacityState.isHidden();
|
||||
}
|
||||
if (symbolInstance.getPlacedVerticalTextIndex()) {
|
||||
textOpacityVerticesSize += symbolInstance.getVerticalGlyphQuadsSize() * 4;
|
||||
textOpacityVerticesSize += symbolInstance.getVerticalGlyphQuadsSize() * count;
|
||||
bucket.text.placedSymbols[*symbolInstance.getPlacedVerticalTextIndex()].hidden =
|
||||
opacityState.isHidden();
|
||||
}
|
||||
|
||||
bucket.text.opacityVertices().extend(textOpacityVerticesSize, opacityVertex);
|
||||
bucket.text.opacityAttributeData().extend(textOpacityVerticesSize, opacityAttributes);
|
||||
|
||||
style::TextWritingModeType previousOrientation = style::TextWritingModeType::Horizontal;
|
||||
if (bucket.allowVerticalPlacement) {
|
||||
@@ -1057,21 +1062,21 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket,
|
||||
}
|
||||
if (symbolInstance.hasIcon()) {
|
||||
size_t iconOpacityVerticesSize = 0u;
|
||||
const auto& opacityVertex = SymbolBucket::opacityVertex(opacityState.icon.placed,
|
||||
opacityState.icon.opacity);
|
||||
const auto& opacityAttributes = SymbolBucket::opacityAttributes(opacityState.icon.placed,
|
||||
opacityState.icon.opacity);
|
||||
auto& iconBuffer = symbolInstance.hasSdfIcon() ? bucket.sdfIcon : bucket.icon;
|
||||
|
||||
if (symbolInstance.getPlacedIconIndex()) {
|
||||
iconOpacityVerticesSize += symbolInstance.getIconQuadsSize() * 4;
|
||||
iconOpacityVerticesSize += symbolInstance.getIconQuadsSize() * count;
|
||||
iconBuffer.placedSymbols[*symbolInstance.getPlacedIconIndex()].hidden = opacityState.isHidden();
|
||||
}
|
||||
|
||||
if (symbolInstance.getPlacedVerticalIconIndex()) {
|
||||
iconOpacityVerticesSize += symbolInstance.getIconQuadsSize() * 4;
|
||||
iconOpacityVerticesSize += symbolInstance.getIconQuadsSize() * count;
|
||||
iconBuffer.placedSymbols[*symbolInstance.getPlacedVerticalIconIndex()].hidden = opacityState.isHidden();
|
||||
}
|
||||
|
||||
iconBuffer.opacityVertices().extend(iconOpacityVerticesSize, opacityVertex);
|
||||
iconBuffer.opacityAttributeData().extend(iconOpacityVerticesSize, opacityAttributes);
|
||||
}
|
||||
|
||||
auto updateIconCollisionBox = [&](const auto& feature, const bool placed, const Point<float>& shift) {
|
||||
|
||||
@@ -171,7 +171,7 @@ protected:
|
||||
}
|
||||
|
||||
// Returns `true` if bucket vertices were updated; returns `false` otherwise.
|
||||
bool updateBucketDynamicVertices(SymbolBucket&, const TransformState&, const RenderTile& tile) const;
|
||||
bool updateBucketDynamicAttributeData(SymbolBucket&, const TransformState&, const RenderTile& tile) const;
|
||||
void updateBucketOpacities(SymbolBucket&, const TransformState&, std::set<uint32_t>&) const;
|
||||
void markUsedJustification(SymbolBucket&,
|
||||
style::TextVariableAnchorType,
|
||||
|
||||
@@ -120,6 +120,8 @@ void Drawable::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices,
|
||||
seg.indexOffset,
|
||||
seg.vertexLength,
|
||||
seg.indexLength,
|
||||
seg.baseInstance,
|
||||
seg.instanceCount,
|
||||
seg.sortKey,
|
||||
};
|
||||
drawSegs.push_back(std::make_unique<Drawable::DrawSegment>(mode, std::move(segCopy)));
|
||||
@@ -337,8 +339,6 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
|
||||
impl->pipelineInfo.setRenderable(renderPass_.getDescriptor().renderable);
|
||||
|
||||
const auto instances = instanceAttributes ? instanceAttributes->getMinCount() : 1;
|
||||
|
||||
for (const auto& seg : impl->segments) {
|
||||
const auto& segment = seg->getSegment();
|
||||
|
||||
@@ -354,16 +354,16 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
|
||||
if (segment.indexLength) {
|
||||
commandBuffer->drawIndexed(static_cast<uint32_t>(segment.indexLength),
|
||||
static_cast<uint32_t>(instances),
|
||||
static_cast<uint32_t>(segment.instanceCount),
|
||||
static_cast<uint32_t>(segment.indexOffset),
|
||||
static_cast<int32_t>(segment.vertexOffset),
|
||||
0,
|
||||
static_cast<uint32_t>(segment.baseInstance),
|
||||
dispatcher);
|
||||
} else {
|
||||
commandBuffer->draw(static_cast<uint32_t>(segment.vertexLength),
|
||||
static_cast<uint32_t>(instances),
|
||||
static_cast<uint32_t>(segment.instanceCount),
|
||||
static_cast<uint32_t>(segment.vertexOffset),
|
||||
0,
|
||||
static_cast<uint32_t>(segment.baseInstance),
|
||||
dispatcher);
|
||||
}
|
||||
|
||||
@@ -411,7 +411,7 @@ void Drawable::setSharedBuffers(const gfx::VertexAttributeArray& attribs, const
|
||||
const auto& vkAttrib = static_cast<const VertexAttribute&>(attrib);
|
||||
int ubo = vkAttrib.getUBO();
|
||||
|
||||
if (ubo == -1 || impl->uniformBuffers.get(ubo) != nullptr) {
|
||||
if (ubo == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1029,8 +1029,14 @@ void Drawable::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices,
|
||||
drawSegs.reserve(segmentCount);
|
||||
for (std::size_t i = 0; i < segmentCount; ++i) {
|
||||
const auto& seg = segments[i];
|
||||
drawSegs.push_back(std::make_unique<DrawSegment>(
|
||||
mode, SegmentBase{seg.vertexOffset, seg.indexOffset, seg.vertexLength, seg.indexLength, seg.sortKey}));
|
||||
drawSegs.push_back(std::make_unique<DrawSegment>(mode,
|
||||
SegmentBase{seg.vertexOffset,
|
||||
seg.indexOffset,
|
||||
seg.vertexLength,
|
||||
seg.indexLength,
|
||||
seg.baseInstance,
|
||||
seg.instanceCount,
|
||||
seg.sortKey}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user