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:
Alex Cristici
2026-08-27 00:12:07 +03:00
committed by GitHub
parent 1d0908bdaa
commit cbe4681ef1
41 changed files with 1398 additions and 727 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -97,6 +97,7 @@ public:
TriangleIndexVector& triangles = *sharedTriangles;
SegmentVector triangleSegments;
SegmentVector instanceSegments;
std::unordered_map<std::string, FillExtrusionBinders> paintPropertyBinders;
};

View File

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

View File

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

View File

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

View File

@@ -51,7 +51,6 @@ private:
std::shared_ptr<FillExtrusionVertexVector> staticDataVertices;
std::shared_ptr<TriangleIndexVector> staticDataIndices;
std::shared_ptr<SegmentVector> staticDataSegments;
#endif
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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