From 90196dd51d0e055aebbc4bb0797ff0db9da67bfd Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Wed, 8 Jul 2026 19:43:07 +1000 Subject: [PATCH] viewport: idle the render loop when only unfetchable chunks remain The streaming settle burst re-armed the render loop whenever a non-resident chunk was frustum-visible, but the enqueue only fetches chunks that are contribution-visible (big enough on screen) and not in a blocked cooldown. A chunk that is in the frustum but sub-pixel is never loaded, so visible_pending stayed true forever and the loop spun at full frame rate with no input. Match visible_pending to the enqueue's eligibility test: a non-resident chunk keeps the loop alive only if it's actively loading, or is contribution-visible and past its cooldown. Sub-pixel / cooldown-blocked chunks no longer prevent idle; they still stream in when a camera move or eviction requests a frame. Co-Authored-By: Claude Opus 4.8 --- src/ifcviewer/ViewportCore.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/ifcviewer/ViewportCore.cpp b/src/ifcviewer/ViewportCore.cpp index f37e547cf0..8a753d26e5 100644 --- a/src/ifcviewer/ViewportCore.cpp +++ b/src/ifcviewer/ViewportCore.cpp @@ -2515,7 +2515,17 @@ void ViewportCore::driveStreamingLoads() { for (const auto& [session_model_id, m] : models_gpu_) { if (m.streaming_file_path.empty() || m.hidden) continue; for (const auto& c : m.chunks) { - if (!c.is_resident && (c.frustum_visible_count > 0 || c.is_loading)) { + if (c.is_resident) continue; + // Keep the loop alive only for chunks we're actually loading or that + // are eligible to enqueue — the same test the enqueue below uses + // (contribution-visible and not in a blocked cooldown). A chunk + // that's in the frustum but sub-pixel (contribution_visible_count + // == 0) is never fetched, so it must not keep the render loop + // spinning at idle; likewise a cooldown-blocked chunk only retries + // after real work (an eviction or camera move) requests a frame. + if (c.is_loading + || (c.contribution_visible_count > 0 + && c.blocked_cooldown_until_frame_idx <= streaming_frame_idx_)) { visible_pending = true; break; }