From cbe4681ef1ee71f8b8cc8bc03aa337cab3145a2a Mon Sep 17 00:00:00 2001 From: Alex Cristici Date: Thu, 27 Aug 2026 00:12:07 +0300 Subject: [PATCH] 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> --- include/mln/gfx/vertex_attribute.hpp | 2 +- include/mln/shaders/layer_ubo.hpp | 1 + include/mln/shaders/mtl/common.hpp | 7 + include/mln/shaders/mtl/fill_extrusion.hpp | 16 +- include/mln/shaders/mtl/symbol.hpp | 249 +++++++++---- include/mln/shaders/shader_defines.hpp | 57 ++- include/mln/shaders/vulkan/common.hpp | 12 +- include/mln/shaders/vulkan/symbol.hpp | 328 +++++++++++++----- src/mln/gfx/attribute.hpp | 11 + src/mln/gfx/drawable_builder.cpp | 2 + src/mln/gfx/drawable_builder_impl.cpp | 2 +- src/mln/gl/drawable_gl.cpp | 2 + src/mln/layout/circle_layout.hpp | 2 +- src/mln/layout/symbol_layout.cpp | 147 +++++--- src/mln/layout/symbol_projection.cpp | 27 +- src/mln/layout/symbol_projection.hpp | 7 +- src/mln/mtl/drawable.cpp | 171 ++++----- .../buckets/fill_extrusion_bucket.cpp | 6 + .../buckets/fill_extrusion_bucket.hpp | 1 + src/mln/renderer/buckets/symbol_bucket.cpp | 93 +++-- src/mln/renderer/buckets/symbol_bucket.hpp | 197 ++++++++--- .../layers/render_fill_extrusion_layer.cpp | 5 +- .../layers/render_fill_extrusion_layer.hpp | 1 - .../renderer/layers/render_symbol_layer.cpp | 255 +++++++++----- .../renderer/layers/render_symbol_layer.hpp | 33 +- .../renderer/layers/symbol_layer_tweaker.cpp | 1 + src/mln/renderer/paint_property_binder.hpp | 7 +- src/mln/renderer/render_static_data.cpp | 26 +- src/mln/renderer/render_static_data.hpp | 6 +- src/mln/shaders/attributes.hpp | 9 + src/mln/shaders/gl/shader_info.cpp | 50 +-- src/mln/shaders/mtl/fill_extrusion.cpp | 16 +- src/mln/shaders/mtl/symbol.cpp | 84 +++-- src/mln/shaders/segment.hpp | 7 + src/mln/shaders/vulkan/fill_extrusion.cpp | 42 ++- src/mln/shaders/vulkan/symbol.cpp | 92 +++-- src/mln/shaders/webgpu/symbol.cpp | 50 +-- src/mln/text/placement.cpp | 75 ++-- src/mln/text/placement.hpp | 2 +- src/mln/vulkan/drawable.cpp | 14 +- src/mln/webgpu/drawable.cpp | 10 +- 41 files changed, 1398 insertions(+), 727 deletions(-) diff --git a/include/mln/gfx/vertex_attribute.hpp b/include/mln/gfx/vertex_attribute.hpp index 46e2e6a27..f7e5b5bb4 100644 --- a/include/mln/gfx/vertex_attribute.hpp +++ b/include/mln/gfx/vertex_attribute.hpp @@ -289,7 +289,7 @@ protected: /// Stores a collection of vertex attributes by name class VertexAttributeArray { public: - using AttributeVector = std::array, shaders::maxVertexAttributeCountPerShader>; + using AttributeVector = std::array, shaders::maxAttributeCountPerShader>; VertexAttributeArray() = default; VertexAttributeArray(VertexAttributeArray&&); VertexAttributeArray(const VertexAttributeArray&) = delete; // Would need to use the virtual assignment operator diff --git a/include/mln/shaders/layer_ubo.hpp b/include/mln/shaders/layer_ubo.hpp index 0fe169af2..ba6e8b77a 100644 --- a/include/mln/shaders/layer_ubo.hpp +++ b/include/mln/shaders/layer_ubo.hpp @@ -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 diff --git a/include/mln/shaders/mtl/common.hpp b/include/mln/shaders/mtl/common.hpp index cc571606e..a3f8e2703 100644 --- a/include/mln/shaders/mtl/common.hpp +++ b/include/mln/shaders/mtl/common.hpp @@ -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); diff --git a/include/mln/shaders/mtl/fill_extrusion.hpp b/include/mln/shaders/mtl/fill_extrusion.hpp index 414cf450b..e79ca21e4 100644 --- a/include/mln/shaders/mtl/fill_extrusion.hpp +++ b/include/mln/shaders/mtl/fill_extrusion.hpp @@ -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)]]; diff --git a/include/mln/shaders/mtl/symbol.hpp b/include/mln/shaders/mtl/symbol.hpp index f271d8582..4925afd7f 100644 --- a/include/mln/shaders/mtl/symbol.hpp +++ b/include/mln/shaders/mtl/symbol.hpp @@ -81,22 +81,41 @@ struct ShaderSource { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static const std::array attributes; - static constexpr std::array instanceAttributes{}; + static const std::array attributes; + static const std::array instanceAttributes; static const std::array 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 { static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static const std::array attributes; - static constexpr std::array instanceAttributes{}; + static const std::array attributes; + static const std::array instanceAttributes; static const std::array 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 static constexpr auto vertexMainFunction = "vertexMain"; static constexpr auto fragmentMainFunction = "fragmentMain"; - static const std::array attributes; - static constexpr std::array instanceAttributes{}; + static const std::array attributes; + static const std::array instanceAttributes; static const std::array textures; static constexpr auto prelude = symbolShaderPrelude; @@ -481,25 +549,45 @@ struct ShaderSource #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 }; } diff --git a/include/mln/shaders/shader_defines.hpp b/include/mln/shaders/shader_defines.hpp index 0b4eb9f15..9cf6a7cdb 100644 --- a/include/mln/shaders/shader_defines.hpp +++ b/include/mln/shaders/shader_defines.hpp @@ -163,15 +163,26 @@ static constexpr uint32_t drawableSSBOStartId = std::max({static_cast( 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(drawableSSBOStartId), static_cast(fillExtrusionDrawableSSBOCount)}); +static constexpr uint32_t drawableUBOStartId = std::max({static_cast(drawableSSBOStartId), + static_cast(fillExtrusionDrawableSSBOCount), + static_cast(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(backgroundVertexAttributeCount), static_cast(circleVertexAttributeCount), static_cast(clippingMaskVertexAttributeCount), @@ -570,7 +595,7 @@ static constexpr uint32_t maxVertexAttributeCountPerShader = std::max({ static_cast(lineVertexAttributeCount), static_cast(locationIndicatorVertexAttributeCount), static_cast(rasterVertexAttributeCount), - static_cast(symbolVertexAttributeCount), + static_cast(symbolAttributeCount), static_cast(wideVectorAttributeCount), static_cast(wideVectorInstanceAttributeCount), }); diff --git a/include/mln/shaders/vulkan/common.hpp b/include/mln/shaders/vulkan/common.hpp index 11be003f9..bd1818ca6 100644 --- a/include/mln/shaders/vulkan/common.hpp +++ b/include/mln/shaders/vulkan/common.hpp @@ -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 diff --git a/include/mln/shaders/vulkan/symbol.hpp b/include/mln/shaders/vulkan/symbol.hpp index 502345e9b..1f4973962 100644 --- a/include/mln/shaders/vulkan/symbol.hpp +++ b/include/mln/shaders/vulkan/symbol.hpp @@ -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 { static constexpr const char* name = "SymbolIconShader"; - static const std::array attributes; - static constexpr std::array instanceAttributes{}; + static const std::array attributes; + static const std::array instanceAttributes; static const std::array 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 { static constexpr const char* name = "SymbolSDFShader"; - static const std::array attributes; - static constexpr std::array instanceAttributes{}; + static const std::array attributes; + static const std::array instanceAttributes; static const std::array 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 { static constexpr const char* name = "SymbolTextAndIconShader"; - static const std::array attributes; - static constexpr std::array instanceAttributes{}; + static const std::array attributes; + static const std::array instanceAttributes; static const std::array textures; static constexpr auto prelude = symbolShaderPrelude; @@ -527,29 +619,10 @@ struct ShaderSource 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 } )"; diff --git a/src/mln/gfx/attribute.hpp b/src/mln/gfx/attribute.hpp index daf03b806..14172d92d 100644 --- a/src/mln/gfx/attribute.hpp +++ b/src/mln/gfx/attribute.hpp @@ -182,6 +182,17 @@ struct MBGL_VERTEX_ALIGN VertexType { typename A5::Value a5; }; +template +struct MBGL_VERTEX_ALIGN VertexType { + using Type = VertexType; + 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 struct Descriptor; diff --git a/src/mln/gfx/drawable_builder.cpp b/src/mln/gfx/drawable_builder.cpp index c06818e21..15318abf8 100644 --- a/src/mln/gfx/drawable_builder.cpp +++ b/src/mln/gfx/drawable_builder.cpp @@ -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))); diff --git a/src/mln/gfx/drawable_builder_impl.cpp b/src/mln/gfx/drawable_builder_impl.cpp index 42ea490cc..fa33ce6d2 100644 --- a/src/mln/gfx/drawable_builder_impl.cpp +++ b/src/mln/gfx/drawable_builder_impl.cpp @@ -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 { diff --git a/src/mln/gl/drawable_gl.cpp b/src/mln/gl/drawable_gl.cpp index 77d4b4c25..baad49459 100644 --- a/src/mln/gl/drawable_gl.cpp +++ b/src/mln/gl/drawable_gl.cpp @@ -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( diff --git a/src/mln/layout/circle_layout.hpp b/src/mln/layout/circle_layout.hpp index fd506f831..e84f3672f 100644 --- a/src/mln/layout/circle_layout.hpp +++ b/src/mln/layout/circle_layout.hpp @@ -115,7 +115,7 @@ private: if (segments.empty() || segments.back().vertexLength + vertexLength > std::numeric_limits::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 diff --git a/src/mln/layout/symbol_layout.cpp b/src/mln/layout/symbol_layout.cpp index 17e2c79a6..8a6471b45 100644 --- a/src/mln/layout/symbol_layout.cpp +++ b/src/mln/layout/symbol_layout.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -1064,7 +1065,7 @@ void SymbolLayout::createBucket(const ImagePositions&, iconSymbol.angle = (allowVerticalPlacement && writingMode == WritingModeType::Vertical) ? pi_v / 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 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::max() || + std::fabs(buffer.segments.back().sortKey - sortKey) > std::numeric_limits::epsilon()) { + buffer.segments.emplace_back(RenderStaticData::symbolSegment(baseInstance, sortKey)); + } + + auto& segment = buffer.segments.back(); + auto index = static_cast(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 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::max() || std::fabs(buffer.segments.back().sortKey - sortKey) > std::numeric_limits::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(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 sizeData, diff --git a/src/mln/layout/symbol_projection.cpp b/src/mln/layout/symbol_projection.cpp index e651c963c..f762ba76d 100644 --- a/src/mln/layout/symbol_projection.cpp +++ b/src/mln/layout/symbol_projection.cpp @@ -180,18 +180,25 @@ bool isVisible(const vec4& anchorPos, const std::array& clippingBuffe void addDynamicAttributes(const Point& anchorPoint, const float angle, - gfx::VertexVector>& 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>& 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 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>& dynamicVertexArray, + SymbolBucket::DynamicAttributeVector& dynamicVertexArray, const Point& 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>& dynamicVertexArray, +void reprojectLineLabels(SymbolBucket::DynamicAttributeVector& dynamicVertexArray, const std::vector& placedSymbols, const mat4& posMatrix, bool pitchWithMap, diff --git a/src/mln/layout/symbol_projection.hpp b/src/mln/layout/symbol_projection.hpp index 49093483b..cce434033 100644 --- a/src/mln/layout/symbol_projection.hpp +++ b/src/mln/layout/symbol_projection.hpp @@ -48,7 +48,7 @@ mat4 getGlCoordMatrix( using PointAndCameraDistance = std::pair, float>; PointAndCameraDistance project(const Point& point, const mat4& matrix); -void reprojectLineLabels(gfx::VertexVector>&, +void reprojectLineLabels(SymbolBucket::DynamicAttributeVector&, const std::vector&, const mat4& posMatrix, bool pitchWithMap, @@ -68,10 +68,9 @@ std::optional> placeFirstAndLastGlyph(float const mat4& labelPlaneMatrix, bool returnTileDistance); -void hideGlyphs(std::size_t numGlyphs, - gfx::VertexVector>& dynamicVertexArray); +void hideGlyphs(std::size_t numGlyphs, SymbolBucket::DynamicAttributeVector& dynamicVertexArray); void addDynamicAttributes(const Point& anchorPoint, float angle, - gfx::VertexVector>& dynamicVertexArray); + SymbolBucket::DynamicAttributeVector& dynamicAttributeData); } // end namespace mln diff --git a/src/mln/mtl/drawable.cpp b/src/mln/mtl/drawable.cpp index 80c0a79e2..14c764be0 100644 --- a/src/mln/mtl/drawable.cpp +++ b/src/mln/mtl/drawable.cpp @@ -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(indexSize * mlSegment.indexOffset); // in bytes, not indexes const NS::Integer baseVertex = static_cast(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(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> 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(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(binding->vertexStride)); - layoutDesc->setStepFunction(binding->vertexBufferResource ? stepFunction - : MTL::VertexStepFunctionConstant); - layoutDesc->setStepRate(binding->vertexBufferResource ? 1 : 0); - } else { - assert(layoutDesc->stride() == static_cast(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(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> 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(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(binding->vertexStride)); + layoutDesc->setStepFunction(binding->vertexBufferResource ? stepFunction + : MTL::VertexStepFunctionConstant); + layoutDesc->setStepRate(binding->vertexBufferResource ? 1 : 0); + } else { + assert(layoutDesc->stride() == static_cast(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(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(); }); diff --git a/src/mln/renderer/buckets/fill_extrusion_bucket.cpp b/src/mln/renderer/buckets/fill_extrusion_bucket.cpp index 67101fc8c..c49e53b8b 100644 --- a/src/mln/renderer/buckets/fill_extrusion_bucket.cpp +++ b/src/mln/renderer/buckets/fill_extrusion_bucket.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -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) { diff --git a/src/mln/renderer/buckets/fill_extrusion_bucket.hpp b/src/mln/renderer/buckets/fill_extrusion_bucket.hpp index 3eba3c295..5bd25e6ec 100644 --- a/src/mln/renderer/buckets/fill_extrusion_bucket.hpp +++ b/src/mln/renderer/buckets/fill_extrusion_bucket.hpp @@ -97,6 +97,7 @@ public: TriangleIndexVector& triangles = *sharedTriangles; SegmentVector triangleSegments; + SegmentVector instanceSegments; std::unordered_map paintPropertyBinders; }; diff --git a/src/mln/renderer/buckets/symbol_bucket.cpp b/src/mln/renderer/buckets/symbol_bucket.cpp index 686b19604..e072cf3e5 100644 --- a/src/mln/renderer/buckets/symbol_bucket.cpp +++ b/src/mln/renderer/buckets/symbol_bucket.cpp @@ -73,16 +73,40 @@ SymbolBucket::SymbolBucket(Immutable(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(), + evaluated_.get(), + evaluated_.get(), + evaluated_.get(), + evaluated_.get(), + evaluated_.get(), + evaluated_.get()}; +} + +// static +style::TextPaintProperties::PossiblyEvaluated SymbolBucket::textPaintProperties( + const style::SymbolPaintProperties::PossiblyEvaluated& evaluated_) { + return style::TextPaintProperties::PossiblyEvaluated{evaluated_.get(), + evaluated_.get(), + evaluated_.get(), + evaluated_.get(), + evaluated_.get(), + evaluated_.get(), + evaluated_.get()}; +} + 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& 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(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(vertexIndex + 0), static_cast(vertexIndex + 1), static_cast(vertexIndex + 2)); @@ -147,6 +179,7 @@ void addPlacedSymbol(gfx::IndexVector& triangles, const PlacedSy static_cast(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>(); 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 #include #include -#include #include #include @@ -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 {}; + +class TextPaintProperties : public Properties {}; + +} // namespace style + class CrossTileSymbolLayerIndex; using SymbolIconBinders = PaintPropertyBinders; using SymbolTextBinders = PaintPropertyBinders; -using SymbolLayoutVertex = - gfx::Vertex, attributes::pixeloffset>>; -using SymbolDynamicLayoutAttributes = TypeList; -using SymbolOpacityAttributes = TypeList; +using SymbolStaticVertexAttributes = gfx::Vertex>; -using CollisionBoxLayoutAttributes = TypeList; -using CollisionBoxDynamicAttributes = TypeList; +#if MLN_USE_SYMBOL_INSTANCING +using SymbolSortedInstance = gfx::Vertex>; +using SymbolLayoutAttributes = gfx::Vertex>; +#else +using SymbolLayoutAttributes = + gfx::Vertex, attributes::pixeloffset>>; +#endif + +using SymbolDynamicLayoutAttributes = gfx::Vertex>; +using SymbolOpacityAttributes = gfx::Vertex>; + +using CollisionBoxLayoutVertexAttributes = + gfx::Vertex>; +using CollisionBoxDynamicVertexAttributes = gfx::Vertex>; 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 anchorPoint; std::size_t segment; @@ -196,7 +232,7 @@ public: std::vector tileDistances; std::vector 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 labelAnchor, - Point o, - float glyphOffsetY, - uint16_t tx, - uint16_t ty, - const Range& sizeData, - bool isSDF, - Point pixelOffset, - Point minFontScale) { +#if MLN_USE_SYMBOL_INSTANCING + static SymbolLayoutAttributes layoutAttributes(const SymbolQuad& symbol, + const Anchor& labelAnchor, + const Range& sizeData) { + const uint16_t aSizeMin = (std::min(MAX_PACKED_SIZE, static_cast(sizeData.min * SIZE_PACK_FACTOR)) + << 1) + + uint16_t(symbol.isSDF); + const uint16_t aSizeMax = std::min(MAX_PACKED_SIZE, static_cast(sizeData.max * SIZE_PACK_FACTOR)); + + return {{static_cast(labelAnchor.point.x), + static_cast(labelAnchor.point.y), + static_cast(symbol.minFontScale.x * 256), + static_cast(symbol.minFontScale.y * 256)}, + + {static_cast(std::round(symbol.tl.x * 32)), + static_cast(std::round((symbol.tl.y + symbol.glyphOffset.y) * 32)), + static_cast(std::round(symbol.tr.x * 32)), + static_cast(std::round((symbol.tr.y + symbol.glyphOffset.y) * 32))}, + + {static_cast(std::round(symbol.bl.x * 32)), + static_cast(std::round((symbol.bl.y + symbol.glyphOffset.y) * 32)), + static_cast(std::round(symbol.br.x * 32)), + static_cast(std::round((symbol.br.y + symbol.glyphOffset.y) * 32))}, + + {symbol.tex.x, symbol.tex.y, symbol.tex.w, symbol.tex.h}, + + {static_cast(symbol.pixelOffsetTL.x * 16), + static_cast(symbol.pixelOffsetTL.y * 16), + static_cast(symbol.pixelOffsetBR.x * 16), + static_cast(symbol.pixelOffsetBR.y * 16)}, + + { aSizeMin, + aSizeMax }}; + } +#else + static SymbolLayoutAttributes layoutAttributes(Point labelAnchor, + Point o, + float glyphOffsetY, + uint16_t tx, + uint16_t ty, + const Range& sizeData, + bool isSDF, + Point pixelOffset, + Point minFontScale) { const uint16_t aSizeMin = (std::min(MAX_PACKED_SIZE, static_cast(sizeData.min * SIZE_PACK_FACTOR)) << 1) + uint16_t(isSDF); @@ -282,12 +358,13 @@ public: static_cast(minFontScale.y * 256)}}, }; } +#endif - static gfx::Vertex dynamicLayoutVertex(Point anchorPoint, float labelAngle) { + static SymbolDynamicLayoutAttributes dynamicLayoutAttributes(Point anchorPoint, float labelAngle) { return {{{anchorPoint.x, anchorPoint.y, labelAngle}}}; } - static gfx::Vertex opacityVertex(bool placed, float opacity) { + static SymbolOpacityAttributes opacityAttributes(bool placed, float opacity) { return {{{static_cast((static_cast(opacity * 127) << 1) | static_cast(placed))}}}; } @@ -319,47 +396,63 @@ public: std::unique_ptr textSizeBinder; - using VertexVector = gfx::VertexVector; - using VertexBuffer = gfx::VertexBuffer; - using DynamicVertexVector = gfx::VertexVector>; - using DynamicVertexBuffer = gfx::VertexBuffer>; - using OpacityVertexVector = gfx::VertexVector>; - using OpacityVertexBuffer = gfx::VertexBuffer>; + using AttributeVector = gfx::VertexVector; + using DynamicAttributeVector = gfx::VertexVector; + using OpacityAttributeVector = gfx::VertexVector; + +#if MLN_USE_SYMBOL_INSTANCING + using SortedInstanceVector = gfx::VertexVector; +#else + using TriangleIndexVector = gfx::IndexVector; +#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 sharedVertices = std::make_shared(); - VertexVector& vertices() { return *sharedVertices; } - const VertexVector& vertices() const { return *sharedVertices; } + std::shared_ptr sharedAttributeData = std::make_shared(); + AttributeVector& attributeData() { return *sharedAttributeData; } + const AttributeVector& attributeData() const { return *sharedAttributeData; } - std::shared_ptr sharedDynamicVertices = std::make_shared(); - DynamicVertexVector& dynamicVertices() { return *sharedDynamicVertices; } - const DynamicVertexVector& dynamicVertices() const { return *sharedDynamicVertices; } + std::shared_ptr sharedDynamicAttributeData = std::make_shared(); + DynamicAttributeVector& dynamicAttributeData() { return *sharedDynamicAttributeData; } + const DynamicAttributeVector& dynamicAttributeData() const { return *sharedDynamicAttributeData; } - std::shared_ptr sharedOpacityVertices = std::make_shared(); - OpacityVertexVector& opacityVertices() { return *sharedOpacityVertices; } - const OpacityVertexVector& opacityVertices() const { return *sharedOpacityVertices; } + std::shared_ptr sharedOpacityAttributeData = std::make_shared(); + OpacityAttributeVector& opacityAttributeData() { return *sharedOpacityAttributeData; } + const OpacityAttributeVector& opacityAttributeData() const { return *sharedOpacityAttributeData; } - using TriangleIndexVector = gfx::IndexVector; +#if MLN_USE_SYMBOL_INSTANCING + std::shared_ptr sharedSortedInstances = std::make_shared(); + SortedInstanceVector& sortedInstances() { return *sharedSortedInstances; } + const SortedInstanceVector& sortedInstances() const { return *sharedSortedInstances; } +#else const std::shared_ptr sharedTriangles = std::make_shared(); TriangleIndexVector& triangles = *sharedTriangles; +#endif SegmentVector segments; std::vector placedSymbols; @@ -370,8 +463,8 @@ public: Buffer icon; Buffer sdfIcon; - using CollisionVertexVector = gfx::VertexVector>; - using CollisionDynamicVertexVector = gfx::VertexVector>; + using CollisionVertexVector = gfx::VertexVector; + using CollisionDynamicVertexVector = gfx::VertexVector; struct CollisionBuffer { std::shared_ptr sharedVertices = std::make_shared(); @@ -422,17 +515,15 @@ public: return *textCollisionCircle; } - static gfx::Vertex collisionLayoutVertex(Point a, - Point anchor, - Point o) { + static CollisionBoxLayoutVertexAttributes collisionLayoutVertex(Point a, + Point anchor, + Point o) { return {{{static_cast(a.x), static_cast(a.y)}}, {{static_cast(anchor.x), static_cast(anchor.y)}}, {{static_cast(::round(o.x)), static_cast(::round(o.y))}}}; } - static gfx::Vertex collisionDynamicVertex(bool placed, - bool notUsed, - Point shift) { + static CollisionBoxDynamicVertexAttributes collisionDynamicVertex(bool placed, bool notUsed, Point shift) { return {{{static_cast(placed), static_cast(notUsed)}}, {{shift.x, shift.y}}}; } diff --git a/src/mln/renderer/layers/render_fill_extrusion_layer.cpp b/src/mln/renderer/layers/render_fill_extrusion_layer.cpp index 2eccb3e92..a105a8137 100644 --- a/src/mln/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mln/renderer/layers/render_fill_extrusion_layer.cpp @@ -178,9 +178,6 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders, if (!staticDataIndices) { staticDataIndices = std::make_shared(RenderStaticData::fillExtrusionTriangleIndices()); } - if (!staticDataSegments) { - staticDataSegments = std::make_shared(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); diff --git a/src/mln/renderer/layers/render_fill_extrusion_layer.hpp b/src/mln/renderer/layers/render_fill_extrusion_layer.hpp index 6c2cb14d5..f94b9c5b4 100644 --- a/src/mln/renderer/layers/render_fill_extrusion_layer.hpp +++ b/src/mln/renderer/layers/render_fill_extrusion_layer.hpp @@ -51,7 +51,6 @@ private: std::shared_ptr staticDataVertices; std::shared_ptr staticDataIndices; - std::shared_ptr staticDataSegments; #endif }; diff --git a/src/mln/renderer/layers/render_symbol_layer.cpp b/src/mln/renderer/layers/render_symbol_layer.cpp index 30fa5c2de..cbfea31be 100644 --- a/src/mln/renderer/layers/render_symbol_layer.cpp +++ b/src/mln/renderer/layers/render_symbol_layer.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -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(), - evaluated_.get(), - evaluated_.get(), - evaluated_.get(), - evaluated_.get(), - evaluated_.get(), - evaluated_.get()}; -} - -// static -style::TextPaintProperties::PossiblyEvaluated RenderSymbolLayer::textPaintProperties( - const style::SymbolPaintProperties::PossiblyEvaluated& evaluated_) { - return style::TextPaintProperties::PossiblyEvaluated{evaluated_.get(), - evaluated_.get(), - evaluated_.get(), - evaluated_.get(), - evaluated_.get(), - evaluated_.get(), - evaluated_.get()}; -} - 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; - 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; - attr->setSharedRawData(buffer.sharedOpacityVertices, - offsetof(Vertex, a1), - /*vertexOffset=*/0, - sizeof(Vertex), - gfx::AttributeDataType::Float); - } - if (isText) { attribs.readDataDrivenPaintProperties( - paintProps.textBinders, evaluated, propertiesAsUniforms, idSymbolOpacityVertexAttribute); + paintProps.textBinders, evaluated, propertiesAsUniforms, idSymbolOpacityAttribute); } else { attribs.readDataDrivenPaintProperties( - 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; 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; - 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(RenderStaticData::symbolVertices()); + } + if (!staticDataIndices) { + staticDataIndices = std::make_shared(RenderStaticData::symbolTriangleIndices()); + } +#endif + // remove drawables that are dropped out of scope auto* tileLayerGroup = static_cast(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(*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(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().constantOr(Color::black()).a > 0.0f && evaluated.get().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); diff --git a/src/mln/renderer/layers/render_symbol_layer.hpp b/src/mln/renderer/layers/render_symbol_layer.hpp index edbafe69e..cb75470d8 100644 --- a/src/mln/renderer/layers/render_symbol_layer.hpp +++ b/src/mln/renderer/layers/render_symbol_layer.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -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 {}; - -class TextPaintProperties : public Properties {}; - // Repackaging evaluated values from SymbolLayoutProperties + // SymbolPaintProperties for genericity over icons vs. text. class SymbolPropertyValues { @@ -64,11 +46,6 @@ public: explicit RenderSymbolLayer(Immutable); ~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 collisionTileLayerGroup; LayerTweakerPtr collisionLayerTweaker; + +#if MLN_USE_SYMBOL_INSTANCING + using SymbolVertexVector = gfx::VertexVector; + using TriangleIndexVector = gfx::IndexVector; + + std::shared_ptr staticDataVertices; + std::shared_ptr staticDataIndices; +#endif }; } // namespace mln diff --git a/src/mln/renderer/layers/symbol_layer_tweaker.cpp b/src/mln/renderer/layers/symbol_layer_tweaker.cpp index 65a00be0c..152cd7d3b 100644 --- a/src/mln/renderer/layers/symbol_layer_tweaker.cpp +++ b/src/mln/renderer/layers/symbol_layer_tweaker.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/src/mln/renderer/paint_property_binder.hpp b/src/mln/renderer/paint_property_binder.hpp index cf7086e10..e49f8f301 100644 --- a/src/mln/renderer/paint_property_binder.hpp +++ b/src/mln/renderer/paint_property_binder.hpp @@ -175,8 +175,9 @@ public: void setInterleavedBuffer(InterleavedVertexBuffer& buffer) { interleavedVertexBuffer = &buffer; - if (vertexOffset == 0) { - vertexOffset = interleavedVertexBuffer->extendVertexFormat(); + auto newVertexOffset = interleavedVertexBuffer->extendVertexFormat(); + if (vertexOffset == std::numeric_limits::max()) { + vertexOffset = newVertexOffset; } } @@ -184,7 +185,7 @@ public: PaintPropertyStatistics statistics; InterleavedVertexBuffer* interleavedVertexBuffer = nullptr; - std::size_t vertexOffset = 0; + std::size_t vertexOffset = std::numeric_limits::max(); }; namespace detail { diff --git a/src/mln/renderer/render_static_data.cpp b/src/mln/renderer/render_static_data.cpp index 0f477acc0..9d4b1d5a4 100644 --- a/src/mln/renderer/render_static_data.cpp +++ b/src/mln/renderer/render_static_data.cpp @@ -56,6 +56,15 @@ gfx::VertexVector RenderStaticData::fillExtrusionVert return vertices; } +gfx::VertexVector RenderStaticData::symbolVertices() { + gfx::VertexVector 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 RenderStaticData::quadTriangleIndices() { gfx::IndexVector indices; indices.emplace_back(0, 1, 2); @@ -85,6 +94,13 @@ gfx::IndexVector RenderStaticData::fillExtrusionTriangleIndices( return indices; } +gfx::IndexVector RenderStaticData::symbolTriangleIndices() { + gfx::IndexVector 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 diff --git a/src/mln/renderer/render_static_data.hpp b/src/mln/renderer/render_static_data.hpp index 52f70c1ac..797792e64 100644 --- a/src/mln/renderer/render_static_data.hpp +++ b/src/mln/renderer/render_static_data.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -30,16 +31,19 @@ public: static gfx::VertexVector rasterVertices(); static gfx::VertexVector heatmapTextureVertices(); static gfx::VertexVector fillExtrusionVertices(); + static gfx::VertexVector symbolVertices(); static gfx::IndexVector quadTriangleIndices(); static gfx::IndexVector tileLineStripIndices(); static gfx::IndexVector fillExtrusionTriangleIndices(); + static gfx::IndexVector 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> depthRenderbuffer; bool has3D = false; diff --git a/src/mln/shaders/attributes.hpp b/src/mln/shaders/attributes.hpp index 4c6cac653..99d5505a0 100644 --- a/src/mln/shaders/attributes.hpp +++ b/src/mln/shaders/attributes.hpp @@ -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 struct data { using Type = gfx::AttributeType; diff --git a/src/mln/shaders/gl/shader_info.cpp b/src/mln/shaders/gl/shader_info.cpp index 28f5c80ee..4557e22ab 100644 --- a/src/mln/shaders/gl/shader_info.cpp +++ b/src/mln/shaders/gl/shader_info.cpp @@ -475,12 +475,12 @@ const std::vector SymbolIconShaderInfo::uniformBlocks = { UniformBlockInfo{"SymbolEvaluatedPropsUBO", idSymbolEvaluatedPropsUBO}, }; const std::vector 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 SymbolIconShaderInfo::textures = { TextureInfo{"u_texture", idSymbolImageTexture}, @@ -496,16 +496,16 @@ const std::vector SymbolSDFShaderInfo::uniformBlocks = { UniformBlockInfo{"SymbolEvaluatedPropsUBO", idSymbolEvaluatedPropsUBO}, }; const std::vector 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 SymbolSDFShaderInfo::textures = { TextureInfo{"u_texture", idSymbolImageTexture}, @@ -521,15 +521,15 @@ const std::vector SymbolTextAndIconShaderInfo::uniformBlocks = UniformBlockInfo{"SymbolEvaluatedPropsUBO", idSymbolEvaluatedPropsUBO}, }; const std::vector 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 SymbolTextAndIconShaderInfo::textures = { TextureInfo{"u_texture", idSymbolImageTexture}, diff --git a/src/mln/shaders/mtl/fill_extrusion.cpp b/src/mln/shaders/mtl/fill_extrusion.cpp index 92a6ad029..6324a1173 100644 --- a/src/mln/shaders/mtl/fill_extrusion.cpp +++ b/src/mln/shaders/mtl/fill_extrusion.cpp @@ -15,8 +15,8 @@ const std::array 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 FillExtrusionShaderSource::textures = {}; @@ -35,8 +35,8 @@ const std::array 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 FillExtrusionInstancedShaderSource::textures = {}; @@ -50,8 +50,8 @@ const std::array 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 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{ diff --git a/src/mln/shaders/mtl/symbol.cpp b/src/mln/shaders/mtl/symbol.cpp index b7cfe2e09..b83ba2f81 100644 --- a/src/mln/shaders/mtl/symbol.cpp +++ b/src/mln/shaders/mtl/symbol.cpp @@ -9,19 +9,28 @@ namespace shaders { using SymbolIconShaderSource = ShaderSource; -const std::array 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 SymbolIconShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, symbolUBOCount + 0, idSymbolPosAttribute}, + +}; +const std::array 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 SymbolIconShaderSource::textures = { TextureInfo{0, idSymbolImageTexture}, @@ -32,23 +41,32 @@ const std::array SymbolIconShaderSource::textures = { using SymbolSDFShaderSource = ShaderSource; -const std::array 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 SymbolSDFShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, symbolUBOCount + 0, idSymbolPosAttribute}, + +}; +const std::array 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 SymbolSDFShaderSource::textures = { TextureInfo{0, idSymbolImageTexture}, @@ -59,22 +77,32 @@ const std::array SymbolSDFShaderSource::textures = { using SymbolTextAndIconShaderSource = ShaderSource; -const std::array SymbolTextAndIconShaderSource::attributes = { - AttributeInfo{0, gfx::AttributeDataType::Short4, symbolUBOCount + 0, idSymbolPosOffsetVertexAttribute}, - AttributeInfo{1, gfx::AttributeDataType::UShort4, symbolUBOCount + 0, idSymbolDataVertexAttribute}, +const std::array SymbolTextAndIconShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, symbolUBOCount + 0, idSymbolPosAttribute}, + +}; +const std::array 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 SymbolTextAndIconShaderSource::textures = { TextureInfo{0, idSymbolImageTexture}, diff --git a/src/mln/shaders/segment.hpp b/src/mln/shaders/segment.hpp index a8ce4ef8a..cfd36102a 100644 --- a/src/mln/shaders/segment.hpp +++ b/src/mln/shaders/segment.hpp @@ -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: diff --git a/src/mln/shaders/vulkan/fill_extrusion.cpp b/src/mln/shaders/vulkan/fill_extrusion.cpp index e72823bb4..2d6f5240f 100644 --- a/src/mln/shaders/vulkan/fill_extrusion.cpp +++ b/src/mln/shaders/vulkan/fill_extrusion.cpp @@ -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; const std::array 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 FillExtrusionShaderSource::textures = {}; @@ -31,13 +33,15 @@ const std::array FillExtrusionInstancedShaderSource::attribute AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute}, }; const std::array 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 FillExtrusionInstancedShaderSource::textures = {}; @@ -47,10 +51,12 @@ const std::array FillExtrusionInstancedShaderSource::textures = using FillExtrusionPatternShaderSource = ShaderSource; const std::array 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 FillExtrusionPatternInstancedShaderSource::at AttributeInfo{0, gfx::AttributeDataType::Short2, idFillExtrusionPosVertexAttribute}, }; const std::array 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}, }; diff --git a/src/mln/shaders/vulkan/symbol.cpp b/src/mln/shaders/vulkan/symbol.cpp index 7687bcc4c..86d7a7ab1 100644 --- a/src/mln/shaders/vulkan/symbol.cpp +++ b/src/mln/shaders/vulkan/symbol.cpp @@ -10,16 +10,27 @@ namespace shaders { using SymbolIconShaderSource = ShaderSource; -const std::array SymbolIconShaderSource::attributes = { +const std::array SymbolIconShaderSource::attributes = { + AttributeInfo{0, gfx::AttributeDataType::Short2, idSymbolPosAttribute}, +}; +const std::array 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 SymbolIconShaderSource::textures = { TextureInfo{0, idSymbolImageTexture}, @@ -30,20 +41,32 @@ const std::array SymbolIconShaderSource::textures = { using SymbolSDFShaderSource = ShaderSource; -const std::array SymbolSDFShaderSource::attributes = { +const std::array 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 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 SymbolSDFShaderSource::textures = { TextureInfo{0, idSymbolImageTexture}, @@ -54,19 +77,32 @@ const std::array SymbolSDFShaderSource::textures = { using SymbolTextAndIconShaderSource = ShaderSource; -const std::array SymbolTextAndIconShaderSource::attributes = { +const std::array 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 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 SymbolTextAndIconShaderSource::textures = { TextureInfo{0, idSymbolImageTexture}, diff --git a/src/mln/shaders/webgpu/symbol.cpp b/src/mln/shaders/webgpu/symbol.cpp index 6d2849865..af5826d08 100644 --- a/src/mln/shaders/webgpu/symbol.cpp +++ b/src/mln/shaders/webgpu/symbol.cpp @@ -9,12 +9,12 @@ namespace shaders { using SymbolIconShaderSource = ShaderSource; const std::array 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 SymbolIconShaderSource::textures = { @@ -25,16 +25,16 @@ const std::array SymbolIconShaderSource::textures = { using SymbolSDFShaderSource = ShaderSource; const std::array 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 SymbolSDFShaderSource::textures = { @@ -45,15 +45,15 @@ const std::array SymbolSDFShaderSource::textures = { using SymbolTextAndIconShaderSource = ShaderSource; const std::array 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 SymbolTextAndIconShaderSource::textures = { diff --git a/src/mln/text/placement.cpp b/src/mln/text/placement.cpp index e9bf630cd..2834336fe 100644 --- a/src/mln/text/placement.cpp +++ b/src/mln/text/placement.cpp @@ -773,9 +773,9 @@ Point 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() != SymbolPlacementType::Point; @@ -790,7 +790,7 @@ bool Placement::updateBucketDynamicVertices(SymbolBucket& bucket, const bool pitchWithMap = layout.get() == style::AlignmentType::Map; const bool keepUpright = layout.get(); 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() == AlignmentType::Map) { const bool pitchWithMap = layout.get() == style::AlignmentType::Map; const bool keepUpright = layout.get(); - 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(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 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& 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& shift) { diff --git a/src/mln/text/placement.hpp b/src/mln/text/placement.hpp index 50fc4b9f7..48e295d87 100644 --- a/src/mln/text/placement.hpp +++ b/src/mln/text/placement.hpp @@ -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&) const; void markUsedJustification(SymbolBucket&, style::TextVariableAnchorType, diff --git a/src/mln/vulkan/drawable.cpp b/src/mln/vulkan/drawable.cpp index 130e4ef77..0d8c863de 100644 --- a/src/mln/vulkan/drawable.cpp +++ b/src/mln/vulkan/drawable.cpp @@ -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(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(segment.indexLength), - static_cast(instances), + static_cast(segment.instanceCount), static_cast(segment.indexOffset), static_cast(segment.vertexOffset), - 0, + static_cast(segment.baseInstance), dispatcher); } else { commandBuffer->draw(static_cast(segment.vertexLength), - static_cast(instances), + static_cast(segment.instanceCount), static_cast(segment.vertexOffset), - 0, + static_cast(segment.baseInstance), dispatcher); } @@ -411,7 +411,7 @@ void Drawable::setSharedBuffers(const gfx::VertexAttributeArray& attribs, const const auto& vkAttrib = static_cast(attrib); int ubo = vkAttrib.getUBO(); - if (ubo == -1 || impl->uniformBuffers.get(ubo) != nullptr) { + if (ubo == -1) { return; } diff --git a/src/mln/webgpu/drawable.cpp b/src/mln/webgpu/drawable.cpp index 54568a76e..e562ccedb 100644 --- a/src/mln/webgpu/drawable.cpp +++ b/src/mln/webgpu/drawable.cpp @@ -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( - mode, SegmentBase{seg.vertexOffset, seg.indexOffset, seg.vertexLength, seg.indexLength, seg.sortKey})); + drawSegs.push_back(std::make_unique(mode, + SegmentBase{seg.vertexOffset, + seg.indexOffset, + seg.vertexLength, + seg.indexLength, + seg.baseInstance, + seg.instanceCount, + seg.sortKey})); } }