Fix one-frame latency when a canvas texture feeds a same-frame consumer#1777
Merged
bghgary merged 3 commits intoJul 13, 2026
Merged
Conversation
Follow-up to BabylonJS/Babylon.js#18506, which fixed the two GUI unicode visualization playgrounds to return Promise<Scene> from createScene (the old revisions fire-and-forget parseFromSnippetAsync / parseFromURLAsync, racing the screenshot), re-saved them as new revisions, and dropped the renderCount: 50 settle-frame workaround on the Babylon.js side. The Native viz runner already awaits the promise returned by createScene, so move to the awaiting revisions and drop the same workaround here: - Load GUI snippet with unicode: #YS93KY#0 -> #YS93KY#1 - Parse GUI json with unicode: #ERVGT5#0 -> #ERVGT5#1 - Remove renderCount: 50 from both (no longer needed now that setup is awaited) Same playground content, so the reference images are unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Updates Babylon Native’s Playground validation configuration to use the newer GUI Unicode visualization playground revisions that properly return Promise<Scene> from createScene, allowing the native runner to wait for scene setup and removing the need for a frame-settle workaround.
Changes:
- Bump the two GUI Unicode visualization tests to newer playground revisions (
#0→#1). - Remove the
renderCount: 50workaround from those two tests.
CI showed the "Load GUI snippet with unicode" viz test fails without the settle frames: that GUI includes an async color-emoji image load that Babylon Native does not finish within a single frame (the button colors also haven't settled), so the emoji renders broken and the buttons render red. Babylon.js completes it fast enough, which is why #18506 could drop the settle frames there. Retain renderCount on that test; the "Parse GUI json with unicode" test has no image load and passes with the awaiting revision and no settle frames. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
NativeEngine::CopyTexture scheduled the canvas->texture blit on PeekNextViewId(). Once the scene/backbuffer view had already been acquired, that placed the copy on a view id AFTER the view that samples the destination. bgfx processes blits in numeric view-id order, so a fullscreen GUI AdvancedDynamicTexture layer sampled the previous frame's canvas content — a one-frame GUI latency (blank/stale first frame). The viz suite masked this by pinning the GUI unicode tests to large renderCount settle frames. Reserve the blit's view id in Context::Flush, immediately after the canvas draws but before the scene/backbuffer render is recorded, and hand it to the source texture so CopyTexture blits on a view ordered after the canvas Flush yet before the consuming view. Non-canvas copies keep the PeekNextViewId() fallback, preserving BabylonJS#1683's multi-canvas ordering fix. Drop the now-unnecessary renderCount from the two GUI unicode viz tests; with the fix they render correctly on the first frame. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bkaradzic-microsoft
approved these changes
Jul 13, 2026
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.
Context
The two GUI unicode viz tests were pinned to old playground revisions with
renderCount: 50settle frames. BabylonJS/Babylon.js#18506 re-saved them as awaiting#1revisions and dropped the settle frames on the Babylon.js side. Adopting the#1revisions on Native isn't enough to droprenderCount— the settle frames masked a Native rendering bug, independent of #18506.Root cause
updateDynamicTextureflushes a GUIAdvancedDynamicTexture'sNativeCanvas(nanovg), then copies the canvas render target into the ADT texture viaNativeEngine::CopyTexture(abgfx::blit). The fullscreen ADT layer samples that texture during the scene/backbuffer render.CopyTexturescheduled the blit onPeekNextViewId(), which — once the backbuffer view was already acquired — placed the blit on a view id after the view that samples the destination. bgfx runs blits in numeric view-id order, so the layer sampled the previous frame's canvas: a one-frame latency (blank first frame; forParse, red buttons + broken emoji).renderCount: 50just rendered past it.Trace of one ADT frame, before: canvas
view 0-7, backbuffer + layerview 8, blitview 9— blit runs after the layer.Fix
Context::Flushreserves the blit's view id right after the canvas draws (before the scene render is recorded) and hands it to the source texture;CopyTextureuses it. Non-canvas copies keep thePeekNextViewId()fallback (preserves #1683).After: canvas
view 0-7, blitview 8, backbuffer + layerview 9— same-frame. General to Native GUI, not just these two tests.Changes
NativeEngine.cpp,Context.cpp,Canvas.{h,cpp},Texture.h: reserve and thread the blit view id.config.json: adopt#YS93KY#1/#ERVGT5#1, droprenderCountfrom both.Both tests pass at the default
renderCount: 1on Win32 D3D11, including the ASAN sanitizer viz run.[Created by Copilot on behalf of @bghgary]