Async CTX virtual texture tile loading#2517
Draft
juliendms wants to merge 3 commits into
Draft
Conversation
Today every cache miss in VirtualTexture::getTile synchronously reads a tile file, decodes it, and uploads it to GL inside the patch render loop -- so a pan that reveals a dozen new patches stalls the frame for a dozen load+upload roundtrips. After this change, file I/O and image decode happen on a single shared worker thread (TileLoader, in an anonymous namespace inside virtualtex.cpp); the render thread only performs bounded GL uploads (kMaxUploadsPerFrame = 4 per VirtualTexture per frame) from a per-owner result queue at the start of beginUsage(). The Tile struct gains a State enum (NotLoaded / Queued / Ready / Failed) that replaces the implicit tex==nullptr / loadFailed pair. State is read and written exclusively on the render thread; the worker treats Tile* as an opaque cookie that round-trips through the request/result pair unchanged. Cancellation is by id: each VirtualTexture registers a uint64_t with the loader on construction and deregisters on destruction. Worker results are delivered under the registry mutex, so a destroyed owner never sees a stale callback. Eviction (issue CelestiaProject#2447) is intentionally out of scope; ticks / tilesRequested are kept around for the follow-up.
Replace std::lock_guard with std::scoped_lock with CTAD throughout the TileLoader singleton and beginUsage drain. Drop redundant nResolutionLevels initializer (in-class init covers it). Use std::atomic default seq_cst memory order for the shutdown flag (the flag is not on a hot path, sequential consistency is the safer default). Mark requestLoad const since it doesn't mutate *this. Make readyTile in getTile a const Tile* since only ImageTexture::getName() (which is const) is called on it. Convert the bounded-upload for-loop in beginUsage to a while-loop and use auto/auto* for the iterator locals. Extract the post-increment in registerOwner so the read and write are on separate lines. No behavioural change.
54820b7 to
6621bc8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Move CTX (virtual texture) tile loading off the render thread. Today, every cache miss in
VirtualTexture::getTilesynchronously reads a tile file, decodes it, and uploads it to GL inside the patch render loop -- so a pan that reveals a dozen new patches stalls the frame for a dozen load+upload roundtrips.After this change:
TileLoader, in an anonymous namespace insidevirtualtex.cpp) handles file I/O and image decode for allVirtualTextureinstances in the process.kMaxUploadsPerFrame = 4perVirtualTextureper frame) from a per-owner result queue at the start ofbeginUsage().Tilegains aStateenum (NotLoaded/Queued/Ready/Failed) that replaces the implicittex == nullptr/loadFailedpair. State is read and written exclusively on the render thread; the worker treatsTile*as an opaque cookie that round-trips through the request/result pair unchanged.VirtualTextureregisters auint64_twith the loader on construction and deregisters on destruction. Worker results are delivered under the registry mutex, so a destroyed owner can never see a stale callback.Design notes
LODSphereMeshis untouched.getTile,beginUsage,endUsage,bindsignatures are unchanged.Image::loadis the only worker-side call;ImageTextureconstruction is exclusively inbeginUsage.getTilebecomes non-blocking. On a miss it enqueues a request (idempotent via the state check) and returns the deepest already-Readyancestor. The first frame after a tile becomes visible may show a coarser ancestor; once the worker delivers andbeginUsageuploads, subsequent frames show the finer tile.unregisterOwnertakes, so result-queue lifetime and registry membership are kept consistent.User-visible effect
Smooth panning across high-LOD CTX surfaces. Freshly-revealed patches show a brief lower-LOD blur for a handful of frames instead of a per-pan freeze.