mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-16 21:42:19 +00:00
wgpu backend: chunk vertex storage to fit browser limits + settle frame
Two pieces: 1. Per-chunk vertex storage (stage 13) WebGPU mandates maxStorageBufferBindingSize ≥ 128 MB. Real BIM models routinely exceed that (one of yours is 139 MB vertex). Without chunking, every browser load would fail with "exceeds max_storage_buffer_binding_size". Strategy: each model's vertex data is split into ≤ 128 MB chunks at applyCachedModel time. Each chunk gets its own vertex_storage buffer, visible_draws / prefix_sums buffers, per_chunk_uniform, and bind group. Index buffer, instance storage, and mesh storage stay single-per-model (they fit well under the cap on every scene we've seen). Mesh-to-chunk assignment is bake-time-deterministic (walks meshes in order, opens a new chunk when adding the next would overflow). Cull buckets visible instances by their mesh's chunk; render issues one drawcall per non-empty chunk per model. WGSL is unchanged — the binary-search vertex pulling works identically per chunk because base_vertex is now CHUNK-LOCAL (the chunk's bind group binds its own vertex_storage). Single code path: chunking is ALWAYS on at 128 MB regardless of target. Cost on desktop is a handful of extra drawcalls per frame (1 per non-empty chunk; typical models = 1-3 chunks). Negligible. A mesh whose vertex range is itself > 128 MB can't fit in any chunk and would need splitting — typical IFC meshes are nowhere near that (hundreds of verts), and applyCachedModel warns loudly if one ever appears. --web-limits CLI flag requests the WebGPU mandatory floor limits (128 MB max storage binding, 256 MB max buffer) instead of the adapter's actual max. Used to verify chunking actually fits through browser constraints — turns "trust me, web will work" into a hard test. The 139 MB scene loads cleanly with --web-limits. 2. Settle frame after motion (bug fix) Reported regression: after orbiting, sub-pixel instances dropped by motion-mode contribution culling stayed missing after the camera stopped. Event-driven rendering means no frame is scheduled after mouse-up, so the cull never re-ran at the still threshold. Fix: track last_cull_was_motion_. If this frame used the motion threshold, requestUpdate() after present to schedule one settle frame. Next frame: camera_moved = false → still threshold → small instances reappear. Matches GL's last_cull_was_motion_ behaviour. Verified pixel-identical on basic.ifc; loads the user's dense scene successfully under --web-limits (chunks=2 on the 139 MB model, chunks=1 on the others). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -50,11 +50,16 @@ int main(int argc, char* argv[]) {
|
||||
"params"});
|
||||
parser.addOption({"no-hiz",
|
||||
"Disable HiZ occlusion culling for perf diagnostics."});
|
||||
parser.addOption({"web-limits",
|
||||
"Request the WebGPU mandatory floor limits (128MB max storage binding) "
|
||||
"instead of the adapter's actual max. Use to verify scenes fit through "
|
||||
"browser constraints."});
|
||||
parser.process(app);
|
||||
|
||||
auto* viewport = new WgpuViewportWindow;
|
||||
viewport->resize(1280, 800);
|
||||
if (parser.isSet("no-hiz")) viewport->hiz_enabled_ = false;
|
||||
if (parser.isSet("no-hiz")) viewport->hiz_enabled_ = false;
|
||||
if (parser.isSet("web-limits")) viewport->web_limits_ = true;
|
||||
|
||||
QWidget* container = QWidget::createWindowContainer(viewport);
|
||||
container->setMinimumSize(320, 240);
|
||||
|
||||
Reference in New Issue
Block a user