Repository navigation
Queue NativeXr EndFrame on its own frame's AfterRender tick - #1957
Merged
CedricGuillemet merged 1 commit intoOct 22, 2026
Merged
Conversation
ScheduleFrame chained EndFrame as an AfterRenderScheduler continuation of the JS frame task. arcana releases the task's FrameCompletionScope before running its continuations, so the render thread could drain AfterRender before EndFrame was queued. EndFrame(N) then ran a frame late, consumed frame N+1 and left EndFrame(N+1) with a null Frame: NativeXrImpl.cpp:410 assert(m_sessionState->Frame != nullptr) Queue EndFrame on AfterRender from the FrameStart task instead. The frame completion scope acquired in that task still keeps the AfterRender tick from running until the JS callbacks are done, and FrameTask still completes only after EndFrame, which EndSessionAsync relies on. NativeXrFrameLifecycle.EndFrameAlwaysHasActiveFrame aborted 10/10 runs within 2.4 s before this change and passes 60 s runs with it. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 37730cd1-0d50-4d5f-b57b-f378fdfe9c8e
This was referenced Oct 21, 2026
CedricGuillemet
marked this pull request as ready for review
October 21, 2026 15:04
CedricGuillemet
requested review from
ryantrem
and
a balanced review from Copilot
October 21, 2026 15:04
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The focused scheduling change addresses the race while preserving callback synchronization and shutdown completion guarantees.
No open issues 🎉
What changed in this PR
Fixes NativeXr frame ordering so EndFrame runs on its own frame’s AfterRender tick.
Changes:
- Queues
EndFramedirectly from the FrameStart task instead of a JavaScript-task continuation. - Preserves frame-completion synchronization and session-shutdown ordering.
| File | Description |
|---|---|
| Plugins/NativeXr/Source/NativeXrImpl.cpp | Schedules EndFrame earlier and documents the timing race. |
Review effort: Balanced
ryantrem
approved these changes
Oct 21, 2026
CedricGuillemet
added a commit
to CedricGuillemet/BabylonReactNative-1
that referenced
this pull request
Oct 22, 2026
Use upstream BabylonNative commit 37d30f54649543290ad25c6c3626c247c1372773, the merged fix from BabylonJS/BabylonNative#1957. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 06586ce7-bc10-46c1-83b5-3334fc60600d
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ScheduleFrame chained EndFrame as an AfterRenderScheduler continuation of the JS frame task. arcana releases the task's FrameCompletionScope before running its continuations, so the render thread could drain AfterRender before EndFrame was queued. EndFrame(N) then ran a frame late, consumed frame N+1 and left EndFrame(N+1) with a null Frame:
NativeXrImpl.cpp:410 assert(m_sessionState->Frame != nullptr)
Queue EndFrame on AfterRender from the FrameStart task instead. The frame completion scope acquired in that task still keeps the AfterRender tick from running until the JS callbacks are done, and FrameTask still completes only after EndFrame, which EndSessionAsync relies on.
NativeXrFrameLifecycle.EndFrameAlwaysHasActiveFrame aborted 10/10 runs within 2.4 s before this change and passes 60 s runs with it.