Class TileStreamer
- Namespace
- LansMap.Map.TilePipeline
Downloads, decodes, and uploads tiles into GPU residency each frame.
public sealed class TileStreamer : IDisposable, ITileResidency
- Inheritance
-
objectTileStreamer
- Implements
Remarks
Call Tick(MapViewTransform, double) once per frame from the main thread. This frame's
upload pin set is applied before inserts, so admitted keys cannot be
evicted this frame; PinHeadroomLayers layers stay evictable
when capacity allows, otherwise one less than capacity. Decode and GPU
upload share UploadBudgetMs;
PNG and JPEG decode go to a managed worker when
DecodeOffloadAllowed is true, and otherwise stay on the
calling thread unless the constructor's webWorkerDecode is true
(JS Worker; demo scenes turn this on). The cancel pass aborts in-flight
scheduler fetches that left the wanted set and are still below 0.7
complete; past 0.7 the download keeps going and can still land, and a
slot that already finished keeps its bytes. Parent, region, and floor
prefetch never enter the scheduler; if they did, the wanted-set pass
would cancel them every tick.
Constructors
TileStreamer(ITileDataSource, ITileAddressBuilder, TileBatchRenderer, ITileFetcher, string, int, TileCacheSettings?, bool, int, bool, bool, int, bool, IReadOnlyList<ITileBlockCodec>, bool, IWebTileDecodeBridge, bool, WebAstcEncoderQuality, Func<string, TileCacheSettings, ITilePersistentStore>)
Builds a streamer from any data source and address builder.
public TileStreamer(ITileDataSource source, ITileAddressBuilder addresses, TileBatchRenderer renderer, ITileFetcher fetcher, string cacheDirectory, int layerCount, TileCacheSettings? cacheSettings = null, bool startDecodeWorkerThread = true, int floorMaxZoom = 4, bool floorPrefetchEnabled = true, bool floorPinEnabled = true, int floorPinMaxZoom = 4, bool allowDecodeOffload = true, IReadOnlyList<ITileBlockCodec> extraCodecs = null, bool webWorkerDecode = false, IWebTileDecodeBridge webDecodeBridge = null, bool webGpuDirectUpload = false, WebAstcEncoderQuality webAstcEncoderQuality = WebAstcEncoderQuality.Fastest, Func<string, TileCacheSettings, ITilePersistentStore> storeFactory = null)
Parameters
sourceITileDataSourceTile metadata only (size, zoom range, cache key, attribution); bytes come from
fetcherviaaddresses.addressesITileAddressBuilderBuilds the fetch URL or path for each tile.
rendererTileBatchRendererGPU tile array this streamer uploads into.
fetcherITileFetcherTransport slots that download tile bytes.
cacheDirectorystringFolder for tiles.dat and tiles.idx.
layerCountintResident Texture2DArray layers; must be positive.
cacheSettingsTileCacheSettings?Disk-cache cap and compaction; null uses Default.
startDecodeWorkerThreadboolFalse only in tests that decode synchronously; ANDed with
allowDecodeOffload.floorMaxZoomintDeepest zoom of the idle disk-only world trickle.
floorPrefetchEnabledboolStarts the idle disk trickle when the provider allows it.
floorPinEnabledboolPins loaded world-floor tiles in GPU memory.
floorPinMaxZoomintRequested deepest pinned floor zoom; actual depth is capacity-derived.
allowDecodeOffloadboolTrue dispatches PNG/JPEG to a managed worker thread; false skips that worker, then PNG/JPEG stay inline unless
webWorkerDecodeis true.extraCodecsIReadOnlyList<ITileBlockCodec>Consumer-registered block codecs for disk-hit recognition; null is built-ins only.
webWorkerDecodeboolTrue probes a JS Worker decode path, only when
allowDecodeOffloadis false.webDecodeBridgeIWebTileDecodeBridgeInjected Web decode bridge for tests; null constructs the production bridge.
webGpuDirectUploadboolTrue additionally probes the WebGPU direct-texture-upload path, only when
webWorkerDecodeis also true and the browser proves it can bind the live array.webAstcEncoderQualityWebAstcEncoderQualitystoreFactoryFunc<string, TileCacheSettings, ITilePersistentStore>
TileStreamer(TileSource, TileBatchRenderer, ITileFetcher, string, int, TileCacheSettings?, bool, int, bool, bool, int, bool, IReadOnlyList<ITileBlockCodec>, bool, IWebTileDecodeBridge, bool, WebAstcEncoderQuality, Func<string, TileCacheSettings, ITilePersistentStore>)
Builds a streamer that derives fetch URLs from source.
public TileStreamer(TileSource source, TileBatchRenderer renderer, ITileFetcher fetcher, string cacheDirectory, int layerCount, TileCacheSettings? cacheSettings = null, bool startDecodeWorkerThread = true, int floorMaxZoom = 4, bool floorPrefetchEnabled = true, bool floorPinEnabled = true, int floorPinMaxZoom = 4, bool allowDecodeOffload = true, IReadOnlyList<ITileBlockCodec> extraCodecs = null, bool webWorkerDecode = false, IWebTileDecodeBridge webDecodeBridge = null, bool webGpuDirectUpload = false, WebAstcEncoderQuality webAstcEncoderQuality = WebAstcEncoderQuality.Fastest, Func<string, TileCacheSettings, ITilePersistentStore> storeFactory = null)
Parameters
sourceTileSourceTile metadata only (size, zoom range, cache key, attribution); bytes come from
fetcher.rendererTileBatchRendererGPU tile array this streamer uploads into.
fetcherITileFetcherTransport slots that download tile bytes.
cacheDirectorystringFolder for tiles.dat and tiles.idx.
layerCountintResident Texture2DArray layers; must be positive.
cacheSettingsTileCacheSettings?Disk-cache cap and compaction; null uses Default.
startDecodeWorkerThreadboolFalse only in tests that decode synchronously; ANDed with
allowDecodeOffload.floorMaxZoomintDeepest zoom of the idle disk-only world trickle.
floorPrefetchEnabledboolStarts the idle disk trickle when the provider allows it.
floorPinEnabledboolPins loaded world-floor tiles in GPU memory.
floorPinMaxZoomintRequested deepest pinned floor zoom; actual depth is capacity-derived.
allowDecodeOffloadboolTrue dispatches PNG/JPEG to a managed worker thread; false skips that worker, then PNG/JPEG stay inline unless
webWorkerDecodeis true.extraCodecsIReadOnlyList<ITileBlockCodec>Consumer-registered block codecs for disk-hit recognition; null is built-ins only.
webWorkerDecodeboolTrue probes a JS Worker decode path, only when
allowDecodeOffloadis false.webDecodeBridgeIWebTileDecodeBridgeInjected Web decode bridge for tests; null constructs the production bridge.
webGpuDirectUploadboolTrue additionally probes the WebGPU direct-texture-upload path, only when
webWorkerDecodeis also true and the browser proves it can bind the live array.webAstcEncoderQualityWebAstcEncoderQualitystoreFactoryFunc<string, TileCacheSettings, ITilePersistentStore>
Fields
AllowLocalCacheMigration
public bool AllowLocalCacheMigration
Field Value
CoarsePrefetchDelta
public int CoarsePrefetchDelta
Field Value
DefaultAllowDecodeOffload
public const bool DefaultAllowDecodeOffload = true
Field Value
DefaultAllowLocalCacheMigration
public const bool DefaultAllowLocalCacheMigration = true
Field Value
DefaultCoarsePrefetchDelta
public const int DefaultCoarsePrefetchDelta = 0
Field Value
DefaultFadeAllLoads
public const bool DefaultFadeAllLoads = true
Field Value
DefaultFetchDeadlineSeconds
public const double DefaultFetchDeadlineSeconds = 45
Field Value
DefaultInstanceTag
public const string DefaultInstanceTag = ""
Field Value
DefaultMaxDecodeQueue
public const int DefaultMaxDecodeQueue = 64
Field Value
DefaultPitchDistanceLodEnabled
public const bool DefaultPitchDistanceLodEnabled = false
Field Value
DefaultPrefetchParentTiles
public const bool DefaultPrefetchParentTiles = true
Field Value
DefaultTileFadeSeconds
public const double DefaultTileFadeSeconds = 0.2
Field Value
DefaultUploadBudgetMs
public const double DefaultUploadBudgetMs = 1.5
Field Value
DefaultVerbose
public const bool DefaultVerbose = false
Field Value
DefaultZoomBlendEnabled
public const bool DefaultZoomBlendEnabled = false
Field Value
DefaultZoomHysteresisSeconds
public const double DefaultZoomHysteresisSeconds = 30
Field Value
DefaultZoomLevelHysteresis
public const double DefaultZoomLevelHysteresis = 0.15
Field Value
FadeAllLoads
public bool FadeAllLoads
Field Value
FetchDeadlineSeconds
public double FetchDeadlineSeconds
Field Value
InstanceTag
public string InstanceTag
Field Value
MaxCapacityLevelDrops
public const int MaxCapacityLevelDrops = 2
Field Value
MaxDecodeQueue
public int MaxDecodeQueue
Field Value
PinHeadroomLayers
public const int PinHeadroomLayers = 4
Field Value
PitchDistanceLodEnabled
public bool PitchDistanceLodEnabled
Field Value
PrefetchParentTiles
public bool PrefetchParentTiles
Field Value
UploadBudgetMs
public double UploadBudgetMs
Field Value
Verbose
public bool Verbose
Field Value
ZoomBlendEnabled
public bool ZoomBlendEnabled
Field Value
ZoomHysteresisSeconds
public double ZoomHysteresisSeconds
Field Value
Properties
CacheStats
public TileCacheStats CacheStats { get; }
Property Value
CapacityLevelDrops
public int CapacityLevelDrops { get; }
Property Value
Cover
public TileCoverBuilder Cover { get; }
Property Value
CoverDroppedCount
public int CoverDroppedCount { get; }
Property Value
CoverExactCount
public int CoverExactCount { get; }
Property Value
CoverFallbackCount
public int CoverFallbackCount { get; }
Property Value
CoverPinTruncatedCount
public int CoverPinTruncatedCount { get; }
Property Value
CoverRefPinDroppedCount
public int CoverRefPinDroppedCount { get; }
Property Value
CoverUncoveredCount
public int CoverUncoveredCount { get; }
Property Value
DecodeDroppedCount
public int DecodeDroppedCount { get; }
Property Value
DecodeOffloadAllowed
public bool DecodeOffloadAllowed { get; }
Property Value
DecodeQueueCount
public int DecodeQueueCount { get; }
Property Value
DecodeRejectedCount
public int DecodeRejectedCount { get; }
Property Value
DecodeStaleDiscardCount
public int DecodeStaleDiscardCount { get; }
Property Value
DecodeWorkerFallbackCount
public int DecodeWorkerFallbackCount { get; }
Property Value
DecodeWorkerOffloadedCount
public int DecodeWorkerOffloadedCount { get; }
Property Value
DecodedTileCount
public int DecodedTileCount { get; }
Property Value
DiskCacheCompactionsRun
public int DiskCacheCompactionsRun { get; }
Property Value
DiskCacheDirectory
public string DiskCacheDirectory { get; }
Property Value
DiskCacheDisabled
public bool DiskCacheDisabled { get; }
Property Value
DiskCacheDroppedWrites
public int DiskCacheDroppedWrites { get; }
Property Value
DiskCacheIoFailures
public int DiskCacheIoFailures { get; }
Property Value
DiskCacheMaxBytes
public long DiskCacheMaxBytes { get; }
Property Value
DiskCacheShrinking
public bool DiskCacheShrinking { get; }
Property Value
DiskHitCount
public int DiskHitCount { get; }
Property Value
DrainedResultCount
public int DrainedResultCount { get; }
Property Value
DroppedDequeueCount
public int DroppedDequeueCount { get; }
Property Value
EvictedCount
public int EvictedCount { get; }
Property Value
Fades
public FadeTracker Fades { get; }
Property Value
FailedCount
public int FailedCount { get; }
Property Value
FloorMaxZoom
public int FloorMaxZoom { get; }
Property Value
FloorPinDroppedCount
public int FloorPinDroppedCount { get; }
Property Value
FloorPinEnabled
public bool FloorPinEnabled { get; set; }
Property Value
FloorPinKeyCount
public int FloorPinKeyCount { get; }
Property Value
FloorPinMaxZoom
public int FloorPinMaxZoom { get; }
Property Value
FloorPrefetchCachedCount
public int FloorPrefetchCachedCount { get; }
Property Value
FloorPrefetchEligible
public bool FloorPrefetchEligible { get; }
Property Value
FloorPrefetchEnabled
public bool FloorPrefetchEnabled { get; set; }
Property Value
FloorPrefetchRemaining
public int FloorPrefetchRemaining { get; }
Property Value
FloorPrefetchTotal
public int FloorPrefetchTotal { get; }
Property Value
FootprintPinDroppedCount
public int FootprintPinDroppedCount { get; }
Property Value
GrowCompletedCount
public int GrowCompletedCount { get; }
Property Value
GrowInFlight
public bool GrowInFlight { get; }
Property Value
HysteresisDroppedCount
public int HysteresisDroppedCount { get; }
Property Value
InFlightCount
public int InFlightCount { get; }
Property Value
IsBusy
public bool IsBusy { get; }
Property Value
LastDecodeMs
public double LastDecodeMs { get; }
Property Value
LastGrowCopyMs
public double LastGrowCopyMs { get; }
Property Value
LastUncappedFootprint
public int LastUncappedFootprint { get; }
Property Value
LastUploadMs
public double LastUploadMs { get; }
Property Value
LayerCapacity
public int LayerCapacity { get; }
Property Value
MaxStagingCopyMs
public double MaxStagingCopyMs { get; }
Property Value
MigrationCount
public int MigrationCount { get; }
Property Value
NetworkStartedCount
public int NetworkStartedCount { get; }
Property Value
PendingFailureCount
public int PendingFailureCount { get; }
Property Value
PendingLayerCapacity
public int PendingLayerCapacity { get; }
Property Value
PendingTransientFailureCount
public int PendingTransientFailureCount { get; }
Property Value
PermanentFailCount
public int PermanentFailCount { get; }
Property Value
PinBudget
public int PinBudget { get; }
Property Value
PinnedInsertFailures
public int PinnedInsertFailures { get; }
Property Value
PinnedKeyCount
public int PinnedKeyCount { get; }
Property Value
PrefetchFailStreak
public int PrefetchFailStreak { get; }
Property Value
PrefetchFloorInFlightCount
public int PrefetchFloorInFlightCount { get; }
Property Value
PrefetchInFlightCount
public int PrefetchInFlightCount { get; }
Property Value
QueuedForDecodeCount
public int QueuedForDecodeCount { get; }
Property Value
RegionFailStreak
public int RegionFailStreak { get; }
Property Value
RegionPrefetchRemaining
public int RegionPrefetchRemaining { get; }
Property Value
RegionPrefetchTotal
public int RegionPrefetchTotal { get; }
Property Value
ResidentLayerCount
public int ResidentLayerCount { get; }
Property Value
ResidentServedCount
public int ResidentServedCount { get; }
Property Value
RetainDroppedCount
public int RetainDroppedCount { get; }
Property Value
SelectionDownstreamSkipCount
public int SelectionDownstreamSkipCount { get; }
Property Value
SelectionLevel
public int SelectionLevel { get; }
Property Value
SelectionSweepCount
public int SelectionSweepCount { get; }
Property Value
StalledSlotReclaimedCount
public int StalledSlotReclaimedCount { get; }
Property Value
TileFadeSeconds
public double TileFadeSeconds { get; set; }
Property Value
TotalDecodeMs
public double TotalDecodeMs { get; }
Property Value
TotalUploadMs
public double TotalUploadMs { get; }
Property Value
UploadRollbackCount
public int UploadRollbackCount { get; }
Property Value
UploadedCount
public int UploadedCount { get; }
Property Value
VisibleCount
public int VisibleCount { get; }
Property Value
WebBlockEncodeFailed
public bool WebBlockEncodeFailed { get; }
Property Value
WebDecodeOffloadedCount
public int WebDecodeOffloadedCount { get; }
Property Value
WebGpuDirectUploadActive
public bool WebGpuDirectUploadActive { get; }
Property Value
WebGpuDirectUploadedCount
public int WebGpuDirectUploadedCount { get; }
Property Value
WebWorkerDecodeActive
public bool WebWorkerDecodeActive { get; }
Property Value
WindowDiskHitCount
public int WindowDiskHitCount { get; }
Property Value
WindowDownloadedCount
public int WindowDownloadedCount { get; }
Property Value
WindowFailedCount
public int WindowFailedCount { get; }
Property Value
WindowResidentServedCount
public int WindowResidentServedCount { get; }
Property Value
ZoomLevelHysteresis
public double ZoomLevelHysteresis { get; set; }
Property Value
Methods
ClearDiskCache()
Wipes the packed disk files; GPU residency is unchanged.
public void ClearDiskCache()
CompactDiskCacheNow()
Rewrites the packed file now to reclaim orphaned blobs, and returns true if the file shrank.
public bool CompactDiskCacheNow()
Returns
DetachDiskStore()
Releases this streamer's hold on its disk store, for a pool that is about to park this streamer rather than dispose it.
public void DetachDiskStore()
Remarks
A parked streamer that keeps holding tiles.dat/tiles.idx
(FileShare.None) blocks any other streamer built for the
same cache directory from ever opening it - the disk cache dies
for the rest of the session instead of just this one streamer's
idle stretch. This disposes the real store (which flushes before
closing), swaps in a degraded one (misses and drops, like any
other open failure), and re-arms the same reopen retry
TryAttachDiskStore already runs, restarting its backoff
from now. A later Checkout (Tick(MapViewTransform, double) via the pending
reopen flag) reattaches a real store without anyone else having
to have released one first.
Dispose()
Releases the fetcher, disk store, decode worker, and staging textures.
public void Dispose()
FloorStallSeconds(double)
Seconds until the idle world-floor trickle resumes; 0 when it is not stalled.
public double FloorStallSeconds(double now)
Parameters
nowdoubleCurrent time in seconds (realtimeSinceStartupAsDouble).
Returns
GrowCapacity(int)
Grows the GPU tile array and residency cache toward a larger layer count; never shrinks.
public void GrowCapacity(int newLayerCount)
Parameters
newLayerCountintTarget layer count; must be greater than the current capacity.
Remarks
Throws if the renderer and cache capacities already disagree, or if
newLayerCount is not greater than the current
capacity. A grow already in flight coalesces to the larger target.
Call from the main thread between Ticks.
HysteresisActiveCount(double)
How many previous-zoom keys are still inside their pin window.
public int HysteresisActiveCount(double now)
Parameters
nowdoubleCurrent time in seconds (realtimeSinceStartupAsDouble).
Returns
PeekPinned(long)
True when the packed key is GPU-resident and currently pinned; does not reorder eviction.
public bool PeekPinned(long key)
Parameters
keylongPacked tile key.
Returns
PeekResident(long)
True when the packed key is GPU-resident; does not reorder eviction.
public bool PeekResident(long key)
Parameters
keylongPacked tile key.
Returns
PrefetchStallSeconds(double)
Seconds until parent prefetch resumes; 0 when it is not stalled.
public double PrefetchStallSeconds(double now)
Parameters
nowdoubleCurrent time in seconds (realtimeSinceStartupAsDouble).
Returns
RegionStallSeconds(double)
Seconds until bulk region prefetch resumes; 0 when it is not stalled.
public double RegionStallSeconds(double now)
Parameters
nowdoubleCurrent time in seconds (realtimeSinceStartupAsDouble).
Returns
ResidentVisibleCount()
Count of currently selected tiles that are GPU-resident, without changing eviction order.
public int ResidentVisibleCount()
Returns
ResolveFetcherSlotCount(ITileDataSource)
Transport slots to construct this source's fetcher with, folding in its PrefetchReserveSlots additively unless the source's concurrency was already lowered for provider politeness.
public static int ResolveFetcherSlotCount(ITileDataSource source)
Parameters
sourceITileDataSourceThe tile source the fetcher will serve.
Returns
RunSelectionPassForTest(MapViewTransform, double)
public void RunSelectionPassForTest(MapViewTransform view, double now)
Parameters
viewMapViewTransformnowdouble
SetDiskCacheMaxBytes(long)
Changes the live disk cap in bytes; growth is immediate, shrink evicts across following ticks.
public void SetDiskCacheMaxBytes(long maxDataBytes)
Parameters
maxDataByteslongNew live-data cap in bytes.
SetPanVelocityTilesPerSecond(double, double)
Sets predicted pan velocity used to prioritize in-view fetches.
public void SetPanVelocityTilesPerSecond(double vx, double vy)
Parameters
vxdoublePan velocity X in tiles per second at the selection level.
vydoublePan velocity Y in tiles per second at the selection level.
StartRegionPrefetch(GeoBounds, int, int, int)
Queues the bounds/zoom range for idle disk-only download, returning false instead of starting when the tile count exceeds maxTiles.
public bool StartRegionPrefetch(GeoBounds bounds, int minZoom, int maxZoom, int maxTiles = 20000)
Parameters
boundsGeoBoundsGeographic extent to cache.
minZoomintInclusive coarsest zoom in Web Mercator zoom units.
maxZoomintInclusive finest zoom in Web Mercator zoom units.
maxTilesintHard cap on queued tiles; exceeding it returns false and queues nothing.
Returns
- bool
True when the job was queued.
Tick(MapViewTransform, double)
Advances selection, fetch, pin, budgeted decode/upload, and cover for one frame.
public void Tick(MapViewTransform view, double now)
Parameters
viewMapViewTransformCurrent map view.
nowdoubleCurrent time in seconds (realtimeSinceStartupAsDouble).
TryGetLayer(long, out int)
Looks up the packed key and marks it most-recently used.
public bool TryGetLayer(long key, out int layer)
Parameters
Returns
- bool
True when the key is GPU-resident.
TryReattachDiskStoreNow()
Attempts to reopen the real disk store right now, without waiting for the scheduled reopen backoff. Call on every Checkout.
public void TryReattachDiskStoreNow()
Remarks
The scheduled retry (DiskReopenDelaysSeconds, starting at
1 s) exists for a genuine external collision - another process, or
another live streamer, still holding the file - where waiting is
the only option. A pooled streamer coming back out of a Checkout
is usually not that case: DetachDiskStore() already
released this exact streamer's own hold on the file when it was
parked, so nothing else is actually contending for it, and a
reused streamer paying the first 1 s delay on every single reuse -
the common path pooling exists for - would silently drop every
disk write and disk hit during that window for no real reason.
This call does not count against the three-attempt budget and does
not touch the scheduled retry's own state: on failure (a real
collision after all), TryAttachDiskStore(double) still runs
on its normal schedule from the next Tick(MapViewTransform, double), exactly
as if this call had not happened.
VisibleContainsTile(TileCoord)
public bool VisibleContainsTile(TileCoord tile)
Parameters
tileTileCoord