From a6ae1bc24c3d170f8df8ec0b0465e56dd76a5536 Mon Sep 17 00:00:00 2001 From: John Tur Date: Sat, 22 Jun 2024 00:16:45 -0400 Subject: [PATCH] Implement tile proper aging --- .../Controls/VirtualSurfaceControl.cs | 88 +++++++++---------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/BnbnavNetClient/Controls/VirtualSurfaceControl.cs b/BnbnavNetClient/Controls/VirtualSurfaceControl.cs index 41f9231..f379915 100644 --- a/BnbnavNetClient/Controls/VirtualSurfaceControl.cs +++ b/BnbnavNetClient/Controls/VirtualSurfaceControl.cs @@ -7,6 +7,7 @@ using SkiaSharp; +using System.Collections.Frozen; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -35,6 +36,14 @@ public readonly bool Contains(TileIndex p) public double Scale { get; set; } = 1; public Point Pan { get; set; } + public VirtualSurfaceControl() + { + for (var i = 0; i < _tileStandbyLists.Length; i++) + { + _tileStandbyLists[i] = []; + } + } + public abstract void DrawTile(TileSurface surface, Rect worldCoordinates); public void InvalidateTiles(Rect worldBounds) @@ -112,7 +121,10 @@ private static TileRect GetWorldExtends(Rect worldBounds) return new TileRect(new(left, top), new(right, bottom)); } - + + private const int TileStandbyListsCount = 16; + private readonly List[] _tileStandbyLists = new List[TileStandbyListsCount]; + public override void Render(DrawingContext context) { var dirtyTiles = new Dictionary(); @@ -149,67 +161,57 @@ public override void Render(DrawingContext context) } } + foreach (var list in _tileStandbyLists) + { + list.Clear(); + } // Trim old tiles var agedTiles = new List(); - foreach (var (coord, surface) in _tileMap) + int agedTileCount = 0; + foreach (var (tile, surface) in _tileMap) { - if (visibleTiles.Contains(coord)) + if (visibleTiles.Contains(tile)) { continue; } - var age = Stopwatch.GetElapsedTime(surface.Timestamp); - if (true || age.TotalSeconds > 2) + var age = Stopwatch.GetElapsedTime(surface.Timestamp, timestamp); + var ageBucket = (uint)age.TotalMilliseconds / 256; + + if (ageBucket >= TileStandbyListsCount) { - agedTiles.Add(coord); + agedTiles.Add(tile); } else { - // tilesStandbyList.Add(age, (coord, surface.Surface)); + _tileStandbyLists[ageBucket].Add(tile); + agedTileCount++; } } + for (int i = _tileStandbyLists.Length - 1; i >= 0; i--) + { + foreach (var tile in _tileStandbyLists[i]) + { + if (agedTileCount >= 16) + { + agedTiles.Add(tile); + agedTileCount--; + } + else + { + goto removedAll; + } + } + } + + removedAll: foreach (var tile in CollectionsMarshal.AsSpan(agedTiles)) { _tileMap.Remove(tile); } - //var tilesToFree = new List<(TileIndex, SKSurface)>(); - //var tilesStandbyList = new SortedDictionary( - // Comparer.Create((l, r) => -l.CompareTo(r))); - - //foreach (var (coord, surface) in tileMap) - //{ - // if (visibleTiles.Contains(coord)) - // { - // continue; - // } - - // var age = Stopwatch.GetElapsedTime(timestamp); - // if (age.TotalSeconds > 2) - // { - // tilesToFree.Add((coord, surface.Surface)); - // } - // else - // { - // tilesStandbyList.Add(age, (coord, surface.Surface)); - // } - //} - - //int count = tilesStandbyList.Count; - //foreach (var tile in tilesStandbyList) - //{ - // var (age, (coord, surface)) = tile; - // surface?.Dispose(); - // tileMap.Remove(coord); - - // if (++count > 16) - // { - // break; - // } - //} - context.Custom(new VirtualSurfaceRenderOperation(Bounds, Pan, Scale, dpiScale, _surfaceMap, dirtyTiles, agedTiles)); } @@ -270,12 +272,10 @@ public void Render(ImmediateDrawingContext context) dirtyTilePicture.Dispose(); } -#if DEBUG else { Debug.Assert(exists, "If a tile surface was just created, it must be dirty"); } -#endif canvas.DrawSurface(tile, new SKPoint((tileIndex.X << TileSideExponent) - (float)panX, (tileIndex.Y << TileSideExponent) - (float)panY)); }