fix: eliminate 8-second teleport freeze on same-map teleport

Replace processAllReadyTiles() with bounded processReadyTiles() in the
same-map teleport and reconnect paths. processAllReadyTiles finalizes
every pending tile synchronously with a GPU sync wait, which caused
8+ second main-thread stalls when many tiles were queued. The bounded
version processes 1-4 tiles per call with async GPU upload — remaining
tiles finalize incrementally over subsequent frames.
This commit is contained in:
Kelsi 2026-03-18 07:54:05 -07:00
parent 14cd6c82b2
commit eca570140a
2 changed files with 10 additions and 9 deletions

View file

@ -279,6 +279,9 @@ public:
/** Process one ready tile (for loading screens with per-tile progress updates) */ /** Process one ready tile (for loading screens with per-tile progress updates) */
void processOneReadyTile(); void processOneReadyTile();
/** Process a bounded batch of ready tiles with async GPU upload (no sync wait) */
void processReadyTiles();
private: private:
/** /**
* Get tile coordinates from GL world position * Get tile coordinates from GL world position
@ -317,10 +320,6 @@ private:
*/ */
void workerLoop(); void workerLoop();
/**
* Main thread: poll for completed tiles and upload to GPU
*/
void processReadyTiles();
void ensureGroundEffectTablesLoaded(); void ensureGroundEffectTablesLoaded();
void generateGroundClutterPlacements(std::shared_ptr<PendingTile>& pending, void generateGroundClutterPlacements(std::shared_ptr<PendingTile>& pending,
std::unordered_set<uint32_t>& preparedModelIds); std::unordered_set<uint32_t>& preparedModelIds);

View file

@ -1990,7 +1990,7 @@ void Application::setupUICallbacks() {
worldEntryMovementGraceTimer_ = 2.0f; worldEntryMovementGraceTimer_ = 2.0f;
taxiLandingClampTimer_ = 0.0f; taxiLandingClampTimer_ = 0.0f;
lastTaxiFlight_ = false; lastTaxiFlight_ = false;
renderer->getTerrainManager()->processAllReadyTiles(); renderer->getTerrainManager()->processReadyTiles();
{ {
auto [tileX, tileY] = core::coords::worldToTile(renderPos.x, renderPos.y); auto [tileX, tileY] = core::coords::worldToTile(renderPos.x, renderPos.y);
std::vector<std::pair<int,int>> nearbyTiles; std::vector<std::pair<int,int>> nearbyTiles;
@ -2023,10 +2023,12 @@ void Application::setupUICallbacks() {
renderer->getCameraController()->clearMovementInputs(); renderer->getCameraController()->clearMovementInputs();
renderer->getCameraController()->suppressMovementFor(0.5f); renderer->getCameraController()->suppressMovementFor(0.5f);
} }
// Flush any tiles that finished background parsing during the cast // Kick off async upload for any tiles that finished background
// (e.g. Hearthstone pre-loaded them) so they're GPU-uploaded before // parsing. Use the bounded processReadyTiles() instead of
// the first frame at the new position. // processAllReadyTiles() to avoid multi-second main-thread stalls
renderer->getTerrainManager()->processAllReadyTiles(); // when many tiles are ready (the rest will finalize over subsequent
// frames via the normal terrain update loop).
renderer->getTerrainManager()->processReadyTiles();
// Queue all remaining tiles within the load radius (8 tiles = 17x17) // Queue all remaining tiles within the load radius (8 tiles = 17x17)
// at the new position. precacheTiles skips already-loaded/pending tiles, // at the new position. precacheTiles skips already-loaded/pending tiles,