Skip to content

Commit ecba1f9

Browse files
committed
🔧
1 parent f58801e commit ecba1f9

3 files changed

Lines changed: 28 additions & 22 deletions

File tree

packages/webgpu/cpp/rnwgpu/RNWebGPUManager.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,21 @@
5050

5151
namespace rnwgpu {
5252

53+
namespace {
54+
jsi::Runtime *sMainJSRuntime = nullptr;
55+
} // namespace
56+
57+
jsi::Runtime *RNWebGPUManager::getMainJSRuntime() { return sMainJSRuntime; }
58+
5359
RNWebGPUManager::RNWebGPUManager(
5460
jsi::Runtime *jsRuntime,
5561
std::shared_ptr<facebook::react::CallInvoker> jsCallInvoker,
5662
std::shared_ptr<PlatformContext> platformContext)
5763
: _jsRuntime(jsRuntime), _jsCallInvoker(jsCallInvoker),
5864
_platformContext(platformContext) {
5965

66+
sMainJSRuntime = jsRuntime;
67+
6068
// Register main runtime for RuntimeAwareCache
6169
BaseRuntimeAwareCache::setMainJsRuntime(_jsRuntime);
6270

packages/webgpu/cpp/rnwgpu/RNWebGPUManager.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ class RNWebGPUManager {
3434
*/
3535
static void installWebGPUWorkletHelpers(jsi::Runtime &runtime);
3636

37+
/**
38+
* Returns the main JS runtime registered when the module was initialized.
39+
* Used to distinguish the JS thread (Hermes) from worklet runtimes.
40+
*/
41+
static jsi::Runtime *getMainJSRuntime();
42+
3743
private:
3844
jsi::Runtime *_jsRuntime;
3945
std::shared_ptr<facebook::react::CallInvoker> _jsCallInvoker;

packages/webgpu/cpp/rnwgpu/api/GPUCanvasContext.cpp

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,28 +55,20 @@ jsi::Value GPUCanvasContext::getCurrentTexture(jsi::Runtime &runtime,
5555
surfaceInfo->present();
5656
return jsi::Value::undefined();
5757
};
58-
auto makeFn = [&]() {
59-
return jsi::Function::createFromHostFunction(
60-
runtime, jsi::PropNameID::forAscii(runtime, "WebGPUPresent"), 0,
61-
presentCb);
62-
};
63-
// Try queueMicrotask first (Hermes JS thread). If the runtime disables
64-
// microtasks (e.g. Worklets), fall back to setImmediate, then setTimeout —
65-
// both have end-of-current-task semantics with no display latency.
66-
try {
67-
runtime.queueMicrotask(makeFn());
68-
return JSIConverter<std::shared_ptr<GPUTexture>>::toJSI(
69-
runtime, std::make_shared<GPUTexture>(texture, "", false));
70-
} catch (...) {
71-
// fall through
72-
}
73-
auto global = runtime.global();
74-
if (global.hasProperty(runtime, "setImmediate")) {
75-
auto setImmediate = global.getPropertyAsFunction(runtime, "setImmediate");
76-
setImmediate.call(runtime, makeFn());
77-
} else if (global.hasProperty(runtime, "setTimeout")) {
78-
auto setTimeout = global.getPropertyAsFunction(runtime, "setTimeout");
79-
setTimeout.call(runtime, makeFn(), jsi::Value(0));
58+
auto fn = jsi::Function::createFromHostFunction(
59+
runtime, jsi::PropNameID::forAscii(runtime, "WebGPUPresent"), 0,
60+
presentCb);
61+
62+
// On the main JS runtime (Hermes), schedule the present as a microtask —
63+
// it runs at end of current task with no display latency.
64+
// On other runtimes (Worklets), microtasks are disabled, so use
65+
// setTimeout(fn, 0) which gives the same end-of-task semantics.
66+
if (&runtime == RNWebGPUManager::getMainJSRuntime()) {
67+
runtime.queueMicrotask(std::move(fn));
68+
} else {
69+
auto setTimeout =
70+
runtime.global().getPropertyAsFunction(runtime, "setTimeout");
71+
setTimeout.call(runtime, fn, jsi::Value(0));
8072
}
8173

8274
// Pass reportsMemoryPressure=false to avoid triggering spurious Hermes GC

0 commit comments

Comments
 (0)