Skip to content

Commit cc58c2d

Browse files
bghgaryCopilot
andcommitted
Tests.ExternalTexture.Msaa: open frame 2 before waiting on startup()
The MSAA tests deadlocked after merging master into rework-thread-model. The render thread waits on startupDone while the JS thread runs the AddToContextAsync .then() callback. That callback calls startup() -> new NativeEngine() / new Scene() / new RenderTargetTexture(), which eventually hits SubmitCommands. SubmitCommands now synchronously acquires a FrameCompletionScope, which blocks while m_frameBlocked is true. The gate only opens on the next StartRenderingCurrentFrame -- but the render thread is stuck on startupDone. Deadlock. Fix: open frame 2 before waiting on startupDone, and reuse the same frame for renderFrame(). Any JS work that touches the engine has to run while a frame is in progress under the new model. This workaround is temporary. Once #1646 lands, the test should migrate from AddToContextAsync to the new synchronous CreateForJavaScript, at which point startup() runs in the same JS task as the texture creation and the cross-frame dance disappears entirely. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent dd76710 commit cc58c2d

1 file changed

Lines changed: 7 additions & 2 deletions

File tree

Apps/UnitTests/Source/Tests.ExternalTexture.Msaa.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,17 @@ namespace
8989
addToContextCalled.get_future().wait();
9090
update.Finish();
9191
device.FinishRenderingCurrentFrame();
92-
startupDone.get_future().get();
9392

94-
// New frame: drive a single renderFrame() on the JS side.
93+
// Open the next frame BEFORE waiting for startup() to complete. The AddToContextAsync .then()
94+
// callback runs on the JS thread and calls startup(), which constructs NativeEngine + Scene + RTT,
95+
// each step submitting bgfx commands. In the threading model from #1652, SubmitCommands
96+
// synchronously acquires a FrameCompletionScope and blocks until a frame is in progress, so a
97+
// frame must be open while startup() runs. The same frame is reused for renderFrame().
9598
device.StartRenderingCurrentFrame();
9699
update.Start();
97100

101+
startupDone.get_future().get();
102+
98103
std::promise<void> renderDone;
99104
loader.Dispatch([&renderDone](Napi::Env env) {
100105
auto jsPromise = env.Global().Get("renderFrame").As<Napi::Function>().Call({}).As<Napi::Promise>();

0 commit comments

Comments
 (0)