@@ -665,9 +665,6 @@ class SymbolBucket implements Bucket {
665665 sortedAngle : number ;
666666 featureSortOrder : Array < number > ;
667667
668- // Cache for per-segment sorting optimization (symbols never change batches)
669- symbolsByBatch : Map < number , Array < { index : number ; rotatedY : number ; featureIndex : number } > > | null ;
670-
671668 collisionCircleArray : Array < number > ;
672669 placementInvProjMatrix : mat4 ;
673670 placementViewportMatrix : mat4 ;
@@ -2246,10 +2243,10 @@ class SymbolBucket implements Bucket {
22462243 // The index array buffer is rewritten to reference the (unchanged) vertices in the
22472244 // sorted order.
22482245
2249- // With multiple segments (from UBO batching), sort within each segment independently
2250- const hasMultipleSegments = this . text . segments . get ( ) . length > 1 || this . icon . segments . get ( ) . length > 1 ;
2251- if ( hasMultipleSegments ) {
2252- this . sortFeaturesWithinSegments ( ) ;
2246+ // Viewport-y sorting is not supported when symbols span multiple render segments.
2247+ // Multiple segments occur when a tile has enough symbols to overflow MAX_VERTEX_ARRAY_LENGTH.
2248+ if ( this . text . segments . get ( ) . length > 1 || this . icon . segments . get ( ) . length > 1 ) {
2249+ this . sortFeaturesByY = false ;
22532250 return ;
22542251 }
22552252
@@ -2286,166 +2283,6 @@ class SymbolBucket implements Bucket {
22862283 if ( this . icon . indexBuffer ) this . icon . indexBuffer . updateData ( this . icon . indexArray ) ;
22872284 }
22882285
2289- /**
2290- * Get or create the symbols-by-batch grouping with caching.
2291- * Symbols are grouped by UBO batch and sorted by viewport Y position.
2292- */
2293- private getOrCreateSortedSymbolsByBatch ( sin : number , cos : number ) : Map < number , Array < { index : number ; rotatedY : number ; featureIndex : number } > > {
2294- const activeBinder = ( this . text . uboBinder && this . text . uboBinder . maxFeaturesPerBatch > 0 ) ?
2295- this . text . uboBinder :
2296- ( this . icon . uboBinder && this . icon . uboBinder . maxFeaturesPerBatch > 0 ) ?
2297- this . icon . uboBinder : null ;
2298- assert ( activeBinder , 'sortFeaturesWithinSegments requires a valid UBO binder with maxFeaturesPerBatch > 0' ) ;
2299- const batchSize = activeBinder . maxFeaturesPerBatch ;
2300-
2301- if ( ! this . symbolsByBatch ) {
2302- // First time - create and cache the batch grouping
2303- this . symbolsByBatch = new Map ( ) ;
2304-
2305- for ( let i = 0 ; i < this . symbolInstances . length ; i ++ ) {
2306- const symbol = this . symbolInstances . get ( i ) ;
2307- const batchIndex = Math . floor ( i / batchSize ) ;
2308- const rotatedY = Math . round ( sin * symbol . tileAnchorX + cos * symbol . tileAnchorY ) | 0 ;
2309-
2310- if ( ! this . symbolsByBatch . has ( batchIndex ) ) {
2311- this . symbolsByBatch . set ( batchIndex , [ ] ) ;
2312- }
2313- this . symbolsByBatch . get ( batchIndex ) . push ( {
2314- index : i ,
2315- rotatedY,
2316- featureIndex : symbol . featureIndex
2317- } ) ;
2318- }
2319- } else {
2320- // Already grouped - just update rotatedY values for the new angle
2321- for ( const batch of this . symbolsByBatch . values ( ) ) {
2322- for ( const item of batch ) {
2323- const symbol = this . symbolInstances . get ( item . index ) ;
2324- item . rotatedY = Math . round ( sin * symbol . tileAnchorX + cos * symbol . tileAnchorY ) | 0 ;
2325- }
2326- }
2327- }
2328-
2329- // Sort each batch by viewport Y position
2330- for ( const batch of this . symbolsByBatch . values ( ) ) {
2331- batch . sort ( ( a , b ) => {
2332- return ( a . rotatedY - b . rotatedY ) || ( b . featureIndex - a . featureIndex ) ;
2333- } ) ;
2334- }
2335-
2336- return this . symbolsByBatch ;
2337- }
2338-
2339- /**
2340- * Rebuild text segment indices in sorted order within each segment.
2341- */
2342- private rebuildTextSegmentIndices (
2343- textSegments : Array < Segment > ,
2344- symbolsByBatch : Map < number , Array < { index : number ; rotatedY : number ; featureIndex : number } > >
2345- ) {
2346- for ( const textSegment of textSegments ) {
2347- const batchIndex = textSegment . batchIndex ;
2348- if ( batchIndex === undefined ) continue ;
2349-
2350- const batchSymbols = symbolsByBatch . get ( batchIndex ) ;
2351- if ( ! batchSymbols ) {
2352- textSegment . primitiveOffset = this . text . indexArray . length ;
2353- textSegment . primitiveLength = 0 ;
2354- continue ;
2355- }
2356-
2357- textSegment . primitiveOffset = this . text . indexArray . length ;
2358- const startLength = this . text . indexArray . length ;
2359-
2360- for ( const { index : symbolIndex } of batchSymbols ) {
2361- const symbol = this . symbolInstances . get ( symbolIndex ) ;
2362- const {
2363- rightJustifiedTextSymbolIndex : right ,
2364- centerJustifiedTextSymbolIndex : center ,
2365- leftJustifiedTextSymbolIndex : left ,
2366- verticalPlacedTextSymbolIndex : vertical
2367- } = symbol ;
2368-
2369- if ( right >= 0 ) this . addIndicesForPlacedSymbol ( this . text , right ) ;
2370- if ( center >= 0 && center !== right ) this . addIndicesForPlacedSymbol ( this . text , center ) ;
2371- if ( left >= 0 && left !== center && left !== right ) this . addIndicesForPlacedSymbol ( this . text , left ) ;
2372- if ( vertical >= 0 ) this . addIndicesForPlacedSymbol ( this . text , vertical ) ;
2373- }
2374-
2375- textSegment . primitiveLength = this . text . indexArray . length - startLength ;
2376- }
2377- }
2378-
2379- /**
2380- * Rebuild icon segment indices in sorted order within each segment.
2381- */
2382- private rebuildIconSegmentIndices (
2383- iconSegments : Array < Segment > ,
2384- symbolsByBatch : Map < number , Array < { index : number ; rotatedY : number ; featureIndex : number } > >
2385- ) {
2386- for ( const iconSegment of iconSegments ) {
2387- const batchIndex = iconSegment . batchIndex ;
2388- if ( batchIndex === undefined ) continue ;
2389-
2390- const batchSymbols = symbolsByBatch . get ( batchIndex ) ;
2391- if ( ! batchSymbols ) {
2392- iconSegment . primitiveOffset = this . icon . indexArray . length ;
2393- iconSegment . primitiveLength = 0 ;
2394- continue ;
2395- }
2396-
2397- iconSegment . primitiveOffset = this . icon . indexArray . length ;
2398- const startLength = this . icon . indexArray . length ;
2399-
2400- for ( const { index : symbolIndex } of batchSymbols ) {
2401- const symbol = this . symbolInstances . get ( symbolIndex ) ;
2402- const {
2403- placedIconSymbolIndex : icon ,
2404- verticalPlacedIconSymbolIndex : iconVertical
2405- } = symbol ;
2406-
2407- if ( icon >= 0 ) this . addIndicesForPlacedSymbol ( this . icon , icon ) ;
2408- if ( iconVertical >= 0 ) this . addIndicesForPlacedSymbol ( this . icon , iconVertical ) ;
2409- }
2410-
2411- iconSegment . primitiveLength = this . icon . indexArray . length - startLength ;
2412- }
2413- }
2414-
2415- /**
2416- * Sort features within each segment independently.
2417- * Each segment corresponds to a UBO batch - we rebuild index arrays per-segment.
2418- */
2419- sortFeaturesWithinSegments ( ) {
2420- this . featureSortOrder = [ ] ;
2421-
2422- const sin = Math . sin ( this . sortedAngle ) ;
2423- const cos = Math . cos ( this . sortedAngle ) ;
2424-
2425- // Get sorted symbols grouped by batch (cached for performance)
2426- const symbolsByBatch = this . getOrCreateSortedSymbolsByBatch ( sin , cos ) ;
2427-
2428- // Build featureSortOrder in batch order
2429- const sortedBatches = Array . from ( symbolsByBatch . keys ( ) ) . sort ( ( a , b ) => a - b ) ;
2430- for ( const batchIndex of sortedBatches ) {
2431- const batchSymbols = symbolsByBatch . get ( batchIndex ) ;
2432- for ( const { index : symbolIndex } of batchSymbols ) {
2433- const symbol = this . symbolInstances . get ( symbolIndex ) ;
2434- this . featureSortOrder . push ( symbol . featureIndex ) ;
2435- }
2436- }
2437-
2438- // Clear and rebuild index arrays with sorted symbols per segment
2439- this . text . indexArray . clear ( ) ;
2440- this . icon . indexArray . clear ( ) ;
2441-
2442- this . rebuildTextSegmentIndices ( this . text . segments . get ( ) , symbolsByBatch ) ;
2443- this . rebuildIconSegmentIndices ( this . icon . segments . get ( ) , symbolsByBatch ) ;
2444-
2445- if ( this . text . indexBuffer ) this . text . indexBuffer . updateData ( this . text . indexArray ) ;
2446- if ( this . icon . indexBuffer ) this . icon . indexBuffer . updateData ( this . icon . indexArray ) ;
2447- }
2448-
24492286}
24502287
24512288register ( SymbolBucket , 'SymbolBucket' , {
0 commit comments