Files
vpinball-wasm/patches/vpinball/0003-renderdevice-vsync-no-thread-emscripten.patch
T
valknar a5e5b6f34a Phase A/B: fix the game loop and trim the asset payload
Phase A (the hard blocker): the engine now plays a real table live in
the browser via a real per-frame game loop, not just a static render.

Two real, previously-unknown upstream bugs found and fixed along the way:
- RenderDevice::WaitForVSync() unconditionally spawned a real std::thread
  every frame, even on __STANDALONE__ builds - a hard crash under
  Emscripten's single-threaded runtime (0003).
- The desktop game loop is a blocking native while loop with manual
  uSleep throttling, incompatible with a single-threaded WASM main
  thread. Adds Player::EmscriptenStepFrame() (one frame, no internal
  loop) driven by emscripten_set_main_loop, plus new JS-callable
  lifecycle entry points (vpinball_wasm_start/stop/dispose in the new
  src/core/EmscriptenBridge.cpp) that bypass the desktop main()/WinMain()
  chain entirely, since that chain assumes the process runs exactly one
  table to completion then exits (0004).

Verified end-to-end in Chrome: real .vpx load, real shader compilation,
real physics/script engine init, a real running frame loop (observed
advancing), and a clean stop() -> ~Player() teardown mid-session with
no crash or hang.

Phase B: trims the preloaded asset payload from ~51MB to ~11MB by
excluding editor-only bundled example tables and a Monaco code editor
never used by the player runtime, and adds real link-time optimization
(-O2 --closure 1) and --use-preload-cache for repeat visits.
2026-08-22 16:06:17 +02:00

25 lines
957 B
Diff

diff --git a/src/renderer/RenderDevice.cpp b/src/renderer/RenderDevice.cpp
index 1fedf4e..3ccc87f 100644
--- a/src/renderer/RenderDevice.cpp
+++ b/src/renderer/RenderDevice.cpp
@@ -2168,10 +2168,19 @@ void RenderDevice::WaitForVSync(const bool asynchronous)
m_vsyncCount++;
m_presentTimestampReference = usec();
};
+#ifndef __EMSCRIPTEN__
if (asynchronous)
std::thread(lambda).detach(); // Reuse thread ? (we always at most one running at a time)
else
lambda();
+#else
+ // vpinball-wasm: a single-threaded Emscripten build (no -pthread /
+ // SharedArrayBuffer) cannot construct real std::thread workers - run
+ // synchronously inline instead. This only updates m_vsyncCount/timestamp
+ // bookkeeping (the real vblank-wait branches above are already excluded
+ // for __STANDALONE__ builds), so synchronous execution is equivalent.
+ lambda();
+#endif
}
#if defined(ENABLE_BGFX)