Skip to content

Commit c75319f

Browse files
bghgaryCopilot
andcommitted
Complete sync CreateForJavaScript migration after master merge
The master merge brought in #1716's RestoreAfterDeviceLoss test using the async AddToContextAsync + frame-pump pattern (added by #1652). With #1646's synchronous CreateForJavaScript, that test runs startup() in the same JS task as the texture wrap, so the frame-pump is unnecessary; migrate it to match the other ExternalTexture tests. Also correct a now-stale comment in AddToContextAsyncAndUpdate: the deprecated AddToContextAsync shim resolves synchronously via CreateForJavaScript, so the frame finish no longer drives its completion. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 2876eb1 commit c75319f

2 files changed

Lines changed: 29 additions & 51 deletions

File tree

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

Lines changed: 28 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,6 @@ TEST(ExternalTexture, RestoreAfterDeviceLoss)
9090
device.GetPlatformInfo().Device, TEX_SIZE, TEX_SIZE, 1, true);
9191
Babylon::Plugins::ExternalTexture externalTexture{nativeTexture1};
9292

93-
std::promise<void> startupDone;
94-
9593
Babylon::AppRuntime::Options options{};
9694
options.UnhandledExceptionHandler = [](const Napi::Error& error) {
9795
std::cerr << "[Uncaught Error] " << Napi::GetErrorString(error) << std::endl;
@@ -114,43 +112,33 @@ TEST(ExternalTexture, RestoreAfterDeviceLoss)
114112
loader.LoadScript("app:///Assets/babylon.max.js");
115113
loader.LoadScript("app:///Assets/tests.externalTexture.deviceLoss.js");
116114

117-
// Queue AddToContextAsync and call startup() with the wrapped texture.
118-
std::promise<void> addToContextCalled;
119-
loader.Dispatch([&externalTexture, &addToContextCalled, &startupDone](Napi::Env env) {
120-
auto jsPromise = externalTexture.AddToContextAsync(env);
121-
addToContextCalled.set_value();
122-
123-
auto jsOnFulfilled = Napi::Function::New(env, [&startupDone](const Napi::CallbackInfo& info) {
124-
auto jsNativeTexture = info[0];
125-
info.Env().Global().Get("startup").As<Napi::Function>().Call({
115+
// CreateForJavaScript is synchronous so startup() runs in the same JS task as the texture wrap.
116+
std::promise<void> startupDone;
117+
loader.Dispatch([&externalTexture, &startupDone](Napi::Env env) {
118+
try
119+
{
120+
auto jsNativeTexture = externalTexture.CreateForJavaScript(env);
121+
env.Global().Get("startup").As<Napi::Function>().Call({
126122
jsNativeTexture,
127-
Napi::Number::New(info.Env(), TEX_SIZE),
128-
Napi::Number::New(info.Env(), TEX_SIZE),
123+
Napi::Number::New(env, TEX_SIZE),
124+
Napi::Number::New(env, TEX_SIZE),
129125
});
130126
startupDone.set_value();
131-
});
132-
133-
auto jsOnRejected = Napi::Function::New(env, [&startupDone](const Napi::CallbackInfo& info) {
134-
startupDone.set_exception(std::make_exception_ptr(
135-
std::runtime_error{Napi::GetErrorString(info[0].As<Napi::Error>())}));
136-
});
137-
138-
jsPromise.Get("then").As<Napi::Function>().Call(jsPromise, {jsOnFulfilled, jsOnRejected});
127+
}
128+
catch (...)
129+
{
130+
startupDone.set_exception(std::current_exception());
131+
}
139132
});
140133

141-
addToContextCalled.get_future().wait();
134+
startupDone.get_future().get();
142135
update.Finish();
143136
device.FinishRenderingCurrentFrame();
144137

145-
// Open the next frame BEFORE waiting on startup(): under the reworked single-frame-encoder
146-
// model the AddToContextAsync .then() runs startup() on the JS thread, whose SubmitCommands
147-
// blocks until a frame is in progress. The same frame is reused for Phase 1's renderFrame.
138+
// --- Phase 1: render red into texture 1, readback ---
148139
device.StartRenderingCurrentFrame();
149140
update.Start();
150141

151-
startupDone.get_future().get();
152-
153-
// --- Phase 1: render red into texture 1, readback (reuses the open frame) ---
154142
std::promise<void> render1Done;
155143
loader.Dispatch([&render1Done](Napi::Env env) {
156144
auto jsPromise = env.Global().Get("renderFrame").As<Napi::Function>().Call({}).As<Napi::Promise>();
@@ -203,37 +191,27 @@ TEST(ExternalTexture, RestoreAfterDeviceLoss)
203191
update.Start();
204192

205193
std::promise<void> restoreDone;
206-
std::promise<void> addToContext2Called;
207-
loader.Dispatch([&externalTexture2, &addToContext2Called, &restoreDone](Napi::Env env) {
208-
auto jsPromise = externalTexture2.AddToContextAsync(env);
209-
addToContext2Called.set_value();
210-
211-
auto jsOnFulfilled = Napi::Function::New(env, [&restoreDone](const Napi::CallbackInfo& info) {
212-
auto jsNewNativeTexture = info[0];
213-
info.Env().Global().Get("restoreTexture").As<Napi::Function>().Call({jsNewNativeTexture});
194+
loader.Dispatch([&externalTexture2, &restoreDone](Napi::Env env) {
195+
try
196+
{
197+
auto jsNewNativeTexture = externalTexture2.CreateForJavaScript(env);
198+
env.Global().Get("restoreTexture").As<Napi::Function>().Call({jsNewNativeTexture});
214199
restoreDone.set_value();
215-
});
216-
217-
auto jsOnRejected = Napi::Function::New(env, [&restoreDone](const Napi::CallbackInfo& info) {
218-
restoreDone.set_exception(std::make_exception_ptr(
219-
std::runtime_error{Napi::GetErrorString(info[0].As<Napi::Error>())}));
220-
});
221-
222-
jsPromise.Get("then").As<Napi::Function>().Call(jsPromise, {jsOnFulfilled, jsOnRejected});
200+
}
201+
catch (...)
202+
{
203+
restoreDone.set_exception(std::current_exception());
204+
}
223205
});
224206

225-
addToContext2Called.get_future().wait();
207+
restoreDone.get_future().get();
226208
update.Finish();
227209
device.FinishRenderingCurrentFrame();
228210

229-
// Open the next frame before waiting on restoreTexture(): SubmitCommands needs an open frame
230-
// under the reworked model. The same frame is reused for the blue render below.
211+
// Render blue into restored RTT.
231212
device.StartRenderingCurrentFrame();
232213
update.Start();
233214

234-
restoreDone.get_future().get();
235-
236-
// Render blue into restored RTT (reuses the open frame).
237215
std::promise<void> render2Done;
238216
loader.Dispatch([&render2Done](Napi::Env env) {
239217
auto jsPromise = env.Global().Get("renderFrame").As<Napi::Function>().Call({}).As<Napi::Promise>();

Apps/UnitTests/Source/Tests.ExternalTexture.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ TEST(ExternalTexture, AddToContextAsyncAndUpdate)
162162
// Wait for AddToContextAsync to be called.
163163
addToContext.get_future().wait();
164164

165-
// Render a frame so that AddToContextAsync will complete.
165+
// Close the frame in which the deprecated shim's synchronous CreateForJavaScript ran.
166166
update.Finish();
167167
device.FinishRenderingCurrentFrame();
168168

0 commit comments

Comments
 (0)