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