From 303f903a1092ed8b7c604d36a02cad6cce635c1e Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 5 Jun 2026 10:00:58 +1000 Subject: [PATCH] ifcviewer: move scene state into ViewportCore (#84-c) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the five scene-state fields that drive per-model GPU upload + the streaming residency loop into ViewportCore: BufferPool pool_ — vertex+index sub-allocator StreamingThread streaming_thread_ — background chunk reader std::unordered_map models_gpu_ — per-model state uint32_t next_model_id_ — model-id allocator uint32_t next_object_id_ — globally-unique object-id allocator ViewportCore.h gains transitive includes for BufferPool / StreamingThread / ModelGpuData; ViewportWindow keeps the same names as reference aliases so existing method bodies that touch them don't have to change. Same risk profile as #84-a and #84-b: the storage moved but the values are still set and consumed by the same code paths, so behaviour stays identical. Builds: desktop / bonsai / web all green. Tests 100/100. --- src/ifcviewer/ViewportCore.h | 27 +++++++++++++++++++++++++++ src/ifcviewer/ViewportWindow.cpp | 7 ++++++- src/ifcviewer/ViewportWindow.h | 22 +++++++--------------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/ifcviewer/ViewportCore.h b/src/ifcviewer/ViewportCore.h index 8eda402cf0..30f128fbb2 100644 --- a/src/ifcviewer/ViewportCore.h +++ b/src/ifcviewer/ViewportCore.h @@ -35,6 +35,12 @@ #include +#include +#include + +#include "BufferPool.h" +#include "ModelGpuData.h" +#include "StreamingThread.h" #include "ViewportHost.h" class ViewportCore { @@ -102,6 +108,27 @@ private: // Pick pass. Reuses pipeline_layout_ — same set of bindings as the // main pass since the pick fragment also vertex-pulls instance data. WGPURenderPipeline pick_pipeline_ = nullptr; + + // ---- Scene state --------------------------------------------------------- + // + // Sub-allocator for chunk vertex + index buffers. All per-chunk + // pool slices come from here; nothing else uses it. Replaces the + // old hand-picked streaming_vram_budget_bytes_ knob entirely. + BufferPool pool_; + + // Background worker that does scatter-gather chunk reads off the + // render thread. driveStreamingLoads enqueues requests for visible + // non-resident chunks and drains completed results into the pool + // on subsequent frames. + StreamingThread streaming_thread_; + + // Per-model GPU + CPU state, keyed by viewport-assigned model_id. + std::unordered_map models_gpu_; + uint32_t next_model_id_ = 1; + // Globally-unique object_id allocator. Each applyCachedModel rebases + // the sidecar's local object_ids by base_object_id_so_far so picks + // are unambiguous across models. + uint32_t next_object_id_ = 1; }; #endif // VIEWPORTCORE_H diff --git a/src/ifcviewer/ViewportWindow.cpp b/src/ifcviewer/ViewportWindow.cpp index b7c7b45f1f..cc09eb9d1b 100644 --- a/src/ifcviewer/ViewportWindow.cpp +++ b/src/ifcviewer/ViewportWindow.cpp @@ -633,7 +633,12 @@ ViewportWindow::ViewportWindow(QWindow* parent) edge_bgl_ (core_.edge_bgl_), edge_pipeline_layout_ (core_.edge_pipeline_layout_), edge_pipeline_ (core_.edge_pipeline_), - pick_pipeline_(core_.pick_pipeline_) { + pick_pipeline_(core_.pick_pipeline_), + pool_ (core_.pool_), + streaming_thread_(core_.streaming_thread_), + models_gpu_ (core_.models_gpu_), + next_model_id_ (core_.next_model_id_), + next_object_id_ (core_.next_object_id_) { // wgpu doesn't need a GL context; we just need a real native window // whose backing layer matches the GPU API wgpu will drive. // diff --git a/src/ifcviewer/ViewportWindow.h b/src/ifcviewer/ViewportWindow.h index 3aed358e63..e2ed9351ba 100644 --- a/src/ifcviewer/ViewportWindow.h +++ b/src/ifcviewer/ViewportWindow.h @@ -984,14 +984,9 @@ public: // ceiling that one-WGPUBuffer-per-chunk would otherwise hit. All // chunk allocations land here; nothing else uses the pool. Replaces // the old hand-picked streaming_vram_budget_bytes_ knob entirely. - BufferPool pool_; - - // Background worker that does scatter-gather chunk reads off the - // render thread. driveStreamingLoads enqueues requests for visible - // non-resident chunks and drains completed results into the pool - // on subsequent frames. Kills the 100-300 ms per-frame stutters - // that synchronous disk reads caused during orbit. - StreamingThread streaming_thread_; + // Scene-state aliases (storage in core_). + BufferPool& pool_; + StreamingThread& streaming_thread_; // Per-frame streaming activity, written by driveStreamingLoads, // consumed by the benchmark harness to delay the orbit sweep until @@ -1025,13 +1020,10 @@ private: // mirror AppSettings::lod1PixelThreshold() in the GL backend. float lod1_pixel_threshold_ = 30.0f; - // Per-model state, keyed by viewport-assigned model_id. - std::unordered_map models_gpu_; - uint32_t next_model_id_ = 1; - // Globally-unique object_id allocator. Each applyCachedModel rebases - // the sidecar's local object_ids by base_object_id_so_far so picks - // are unambiguous across models. Selection flags index this range. - uint32_t next_object_id_ = 1; + // Per-model state aliases (storage in core_). + std::unordered_map& models_gpu_; + uint32_t& next_model_id_; + uint32_t& next_object_id_; // Sidecar paths queued before init completes. std::deque pending_sidecars_;