mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-23 03:10:06 +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:
@@ -80,12 +80,26 @@ add_executable(IfcViewerWeb
|
||||
WebViewportHost.h
|
||||
)
|
||||
target_link_libraries(IfcViewerWeb PRIVATE IfcViewerCore)
|
||||
|
||||
target_link_options(IfcViewerWeb PRIVATE
|
||||
# Asyncify lets us await wgpu's RequestAdapter/RequestDevice/MapAsync
|
||||
# as if they were synchronous. Adds ~30-50% wasm size and a small
|
||||
# per-await runtime cost; acceptable for the spike, revisit when
|
||||
# we ship.
|
||||
"-sASYNCIFY"
|
||||
# No -sASYNCIFY. The web init path is callback-driven
|
||||
# (initWgpuAsyncWeb chains RequestAdapter → RequestDevice via
|
||||
# WGPU's AllowSpontaneous mode + the JS event loop), so we don't
|
||||
# need to await wgpu calls as if they were sync. Asyncify would
|
||||
# also instrument every function reachable from emscripten_sleep,
|
||||
# adding ~30% to wasm size for no win here.
|
||||
#
|
||||
# EXIT_RUNTIME=0 + Module.noExitRuntime=true (set in shell.html)
|
||||
# keeps wasm alive after main() returns so Dawn-web's
|
||||
# RequestAdapter/RequestDevice promise callbacks land. The
|
||||
# alternative — calling emscripten_set_main_loop_arg early in
|
||||
# main() to set noExitRuntime as a side effect — registers a RAF
|
||||
# that starves the device promise (observed: ~10s delay in Firefox).
|
||||
"-sEXIT_RUNTIME=0"
|
||||
# Expose the C tick entry point to JS so shell.html's RAF loop
|
||||
# can call Module._raf_tick_c. EMSCRIPTEN_KEEPALIVE alone keeps
|
||||
# the symbol in the binary but doesn't add it to Module.
|
||||
"-sEXPORTED_FUNCTIONS=['_main','_raf_tick_c']"
|
||||
# Streaming + chunked geometry want a heap that can grow as buffers
|
||||
# arrive. 256 MB initial, 2 GB ceiling (matches the wasm32 pointer
|
||||
# cap; --shared64 / MEMORY64 would lift this later if we need it).
|
||||
@@ -96,6 +110,12 @@ target_link_options(IfcViewerWeb PRIVATE
|
||||
# sidecar byte-range loader. Not used yet by the scaffold but
|
||||
# needed by the upcoming #27 web streaming I/O backend.
|
||||
"-sFETCH=1"
|
||||
# Bundle a small sample sidecar into Emscripten's MEMFS so the
|
||||
# scaffold can prove the load path end-to-end without needing
|
||||
# emscripten_fetch + COOP/COEP wiring. The @ separator mounts the
|
||||
# file at the virtual path the wasm uses to fopen() it. Replaced
|
||||
# by an emscripten_fetch + Range backend in #88.
|
||||
"--embed-file=${CMAKE_CURRENT_SOURCE_DIR}/sample.ifcview@/sample.ifcview"
|
||||
# Shell template wraps the JS output in our canvas page.
|
||||
"--shell-file=${CMAKE_CURRENT_SOURCE_DIR}/shell.html"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user