refactor(textures): split upload throttle into processOne / processUntil#104
Merged
Merged
Conversation
Replace the single `processSome(maxProcessingTime)` — a sliding,
numImageWorkers-sized prefetch window plus a re-queue-on-timeout pass —
with two focused methods:
- processOne() — upload a single texture; used while animating so
uploads don't steal time from the animation
- processUntil(maxProcessingTime) — upload serially until the per-frame
time budget is exhausted; used when idle
The per-texture work (dead-check, getTextureData guard, upload, try/catch)
is shared in a private `uploadQueued`; `isTextureDead` stays a method so TS
doesn't narrow `state` across the awaits.
Why the prefetch window was dead weight: `loadTexture` already awaits
`getTextureData` before enqueuing image textures, so queued textures are
already decoded — the prefetch's getTextureData calls resolved immediately
and the time budget really only bounds GPU upload time. The re-queue pass
only existed to recover decodes cut off mid-flight by that budget, which no
longer happens.
Behavior change: while animating, exactly one texture is uploaded per frame
(previously: as many as fit in half the time budget). The idle path keeps
the time-budgeted serial upload. Pre-init drain now uses
processUntil(Infinity).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
What changed
Replaces the single
CoreTextureManager.processSome(maxProcessingTime)— a sliding,numImageWorkers-sized prefetch window plus a re-queue-on-timeout pass — with two focused methods:processOne()processUntil(maxProcessingTime)Shared per-texture work (dead-check →
getTextureDataguard → upload →try/catch) lives in a privateuploadQueued.isTextureDeadis a method (not an inline check) so TypeScript doesn't narrowstateacross the awaits.Stage picks one based on animation state; the pre-init drain in CoreTextureManager now calls
processUntil(Infinity).Why
The prefetch window was effectively dead weight:
loadTexturealready awaitsgetTextureDatabefore enqueuing image textures, so a queued texture is already decoded — the prefetch'sgetTextureDatacalls resolved immediately, and the time budget really only bounds GPU upload time. The re-queue-on-timeout pass existed only to recover decodes cut off mid-flight by that budget, which no longer happens. Removing both leaves a straightforward serial drain that's far easier to reason about.Behavior change
textureProcessingTimeLimitsetting (default10, untouched here).removeTextureFromQueuestill has no callers, so a texture freed after enqueue stays in the queue until drained —uploadQueueddiscards it.Testing
tsc --buildclean; 243/243 unit tests pass.stress-images(1000 picsum images, idle path): full grid renders and the queue drains to a stable state; residual white squares are confirmed picsum-404 IDs, not stalled uploads. The animatingprocessOnereuses the same verifieduploadQueued.🤖 Generated with Claude Code