ifcviewer: move scene state into ViewportCore (#84-c)

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<uint32_t, ModelGpuData> 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.
This commit is contained in:
Dion Moult
2026-06-05 10:00:58 +10:00
parent d0be7b775a
commit 303f903a10
3 changed files with 40 additions and 16 deletions
+27
View File
@@ -35,6 +35,12 @@
#include <webgpu/webgpu.h>
#include <cstdint>
#include <unordered_map>
#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<uint32_t, ModelGpuData> 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
+6 -1
View File
@@ -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.
//
+7 -15
View File
@@ -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<uint32_t, ModelGpuData> 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<uint32_t, ModelGpuData>& models_gpu_;
uint32_t& next_model_id_;
uint32_t& next_object_id_;
// Sidecar paths queued before init completes.
std::deque<std::string> pending_sidecars_;