mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-17 02:49:12 +00:00
ifcviewer-web: end-to-end rendering on Chrome + Firefox
Wire up wgpu init + scene load + RAF render so the embedded sample sidecar paints on the canvas in both browsers. Root-cause fix: BufferPool::addSubBuffer spin-waited on PopErrorScope, which resolves via JS microtask on Dawn-web. The spin blocked the JS event loop, so the microtask never fired and the first allocation hung the page indefinitely. Skip the error-scope dance on Emscripten; trust the buffer pointer. ViewportCore: add initWgpuAsyncWeb (nested-callback adapter→device chain with AllowSpontaneous mode, no spin) and loadSidecarFromPath (Qt-free entry point). waitTickInstance becomes a no-op shim on web; cull-threads / streaming_thread_ / wgpuSurfacePresent gated off; chunk I/O runs inline. main_web.cpp: AppState + initWgpuAsyncWeb → buildPipelines (+ HiZ/edge/pick) → loadSidecarFromPath → ready flag → Module._app_ptr handoff. The RAF loop lives in shell.html (NOT here) because any RAF helper called from inside Dawn-web's wgpu Promise.then chain stalls the device callback. CMakeLists.txt: EXIT_RUNTIME=0 + Module.noExitRuntime=true (shell) keeps wasm alive past main() so the device promise lands; no Asyncify; export _raf_tick_c so shell.html's RAF can call it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -257,6 +257,19 @@ public:
|
||||
bool initWgpu(bool web_limits);
|
||||
void shutdown();
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
// Async-init driver for the web. The spin-wait pattern in initWgpu()
|
||||
// doesn't work on Dawn-web — RequestDevice's callback never fires
|
||||
// when the caller is parked inside an Asyncify spin loop, even with
|
||||
// AllowSpontaneous + emscripten_sleep yields. The fix is to mirror
|
||||
// the original main_web.cpp spike: nested callbacks, no spin.
|
||||
// Fires `on_complete(true)` once instance + adapter + device + queue
|
||||
// + pool + surface_format_ are all in place; on any failure, fires
|
||||
// on_complete(false). Caller is responsible for calling
|
||||
// buildPipelines + buildHiz/Edge/Pick + scene-load after on_complete.
|
||||
void initWgpuAsyncWeb(std::function<void(bool ok)> on_complete);
|
||||
#endif
|
||||
|
||||
// ---- Chunk residency (#84-n) ------------------------------------------
|
||||
//
|
||||
// Build the per-chunk WGPUBindGroup over its current pool slices +
|
||||
@@ -315,6 +328,14 @@ public:
|
||||
// freshly-loaded scene frames itself).
|
||||
void applyCachedModel(std::uint32_t model_id, StreamingSidecar metadata);
|
||||
|
||||
// Qt-free sidecar load: readSidecarMetadataOnly + applyCachedModel.
|
||||
// Used by the web build (and any other non-Qt embedder) so the
|
||||
// public ViewportWindow::loadSidecar's QString + QFile triage
|
||||
// tilde-expansion doesn't have to be replicated. Returns 0 on
|
||||
// any failure (device not ready, file missing, magic / version
|
||||
// mismatch) and the freshly-assigned model_id on success.
|
||||
std::uint32_t loadSidecarFromPath(const std::string& path);
|
||||
|
||||
// Direct-load (bonsai-side) entry points. Bonsai's SceneLoader feeds
|
||||
// the viewer one mesh + one instance at a time, then calls
|
||||
// finalizeModel once everything's staged. The staging map lives on
|
||||
|
||||
Reference in New Issue
Block a user