perf: faster chunk visibility testing#665
Merged
Merged
Conversation
|
🎉 This PR is included in version 0.22.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
aganders3
added a commit
that referenced
this pull request
May 21, 2026
…dering case) (#667) ### Summary When working with remote rendering, I noticed a bug I introduced in #665 that results in the volume layer stalling until the entire prefetch queue drains. That PR rewrote `updateChunksForVolume` and replaced the per-chunk `isCurrentLOD = chunk.lod === currentLOD_` derivation with a `markVolumeChunkVisible(chunk, isFallbackLOD)` helper that computes `isCurrentLOD = !isFallbackLOD`. When `currentLOD === fallbackLOD`, only the current-LOD pass runs, so every chunk is marked with `isFallbackLOD=false, isCurrentLOD=true`. `computePriority` then returns `visibleCurrent` (priority 2 under `createPlaybackPolicy`) instead of `fallbackVisible` (priority 0) — and since `prefetchTime` is priority 1 in the same policy, the current frame's chunks land in the queue *behind* the entire prefetch backlog. This restores previous behavior by getting both `isFallbackLOD` and `isCurrentLOD` from the chunk's own `chunk.lod` inside `markVolumeChunkVisible`, so for single LOD (we configure this typically by setting min LOD === max LOD in the policy) both flags are true and `computePriority` returns `fallbackVisible` as it did before #665. ### Tests & Checks I confirmed this fix restores the expected (previous) behavior in a reef idetik-remote session.
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
This restructures the
chunksarray toChunk[lod][t][c][z][y][x]and uses direct indexing to reduce the total number of intersection tests used to determine chunk visibility and priority.On
main,updateChunksForImageiterates every chunk at the current time index testing each against the view bounds, channel filter, and LOD predicate. This is O(chunks_per_timepoint) per-frame work. With the new layout,chunkIndexRange(bounds, lod)converts the world-space view bounds directly to a chunk-index range, anditerateChunksInBoxwalks only the chunks the view actually overlaps. Per-frame work now scales with the visible region instead of the dataset.The fallback LOD runs through the same bounded path against the prefetch AABB, so in-view fallback chunks act as a backdrop while current-LOD chunks load, and the prefetch padding stays warm for short pans. Datasets whose coarsest LOD is still pretty large (e.g. OPS) no longer pay an O(all_fallback_lod_chunks) cost per frame.
With this refactor,
getChunksToRenderandallVisibleFallbackLODLoadediteratechunkViewStates_(the per-view output map, already reflecting the latest update) instead of re-scanning all chunks on every render call. They also no longer takesliceCoords, they just operate on the state established by the priorupdateChunksFor{Image,Volume}call.The volume path (
updateChunksForVolume) is intentionally left unchanged, just re-expressed through the new iterators. Extending bound-visibility to the volume layer is a natural follow-up.Related Issue
Closes #663
Tests & Checks
I instrumented the code with
performance.measureand saw the per-frame visibility checking cost drop from 300ms+ to <1ms. I did not include these measurement spans in this PR because they add noise, but I think it would be helpful to instrument the code thoroughly in a follow-up to allow us to track regressions, etc. Possibly related to #602 #166 and other perf-related issues.The difference is easily felt with the exaSPIM data in the main
image_2dexample. You can also see the FPS in the stats.js overlay go from 3-5fps to 100+fps. Here are before/after comparisons of zooming and panning.on
mainScreen.Recording.2026-05-13.at.9.35.17.AM.mov
with this PR
Screen.Recording.2026-05-13.at.9.34.41.AM.mov