Skip to content

Add wrapped-native-texture device-loss restore unit test#1716

Open
bghgary wants to merge 6 commits into
BabylonJS:masterfrom
bghgary:wrapped-native-texture-restore
Open

Add wrapped-native-texture device-loss restore unit test#1716
bghgary wants to merge 6 commits into
BabylonJS:masterfrom
bghgary:wrapped-native-texture-restore

Conversation

@bghgary
Copy link
Copy Markdown
Contributor

@bghgary bghgary commented May 22, 2026

End-to-end test for BJS #18469 — the device-loss / device-restore flow for wrapped native textures.

Test (WrappedNativeTexture.RestoreAfterDeviceLoss)

  1. Create an external GPU texture, wrap via wrapNativeTexture, render a red plane, readback, verify red pixels.
  2. Create a second GPU texture (simulates device restore), call updateWrappedNativeTexture to repoint the wrapper at the new handle, render a blue plane, readback, verify blue pixels.

Confirms the InternalTexture identity survives the handle swap and the framebuffer is rebuilt correctly against the new resource.

Test infrastructure improvements

  • GUI snippet flake fix: The Load GUI snippet with unicode and Parse GUI json with unicode tests called parseFromSnippetAsync/parseFromURLAsync fire-and-forget. On slow CI runners the async fetch hadn't completed by the capture frame, causing intermittent failures. Fixed via config replace to transform the fire-and-forget into a proper return ...then(() => { return scene; }), making createScene return a promise that the runner already handles.
  • guiIsReady() gate: Ported from the BJS Playwright viz-test runner. Defers frame counting until all AdvancedDynamicTexture instances report guiIsReady() (handles image loading within already-parsed GUI controls).
  • const -> let bug fix: The scriptToRun code path in validation_native.js declared const scriptToRun then reassigned it (latent strict-mode bug).
  • Safe PG version syncs from BJS: #WCDZS#92->#531, #5E318S#5->#7, #8RU8Q3#157->#193 (same code, no visual change).

Dependency

Requires @babylonjs/core >= 9.9.1 (which includes updateWrappedNativeTexture). The fail-fast JS guard throws a clear error when the API is missing, so the test fails immediately instead of hanging until CI timeout.

Local verification

Win32 D3D11 Debug: before=13456 red / 0 blue, after=0 red / 13456 blue. PASSED in 1293ms.

[Created by Copilot on behalf of @bghgary]

End-to-end test for BJS #18469 `updateWrappedNativeTexture` on Native:

1. Create an external GPU texture, wrap it via `wrapNativeTexture`, render a red plane into it, readback → verify red pixels.
2. Create a SECOND GPU texture (simulating device restore), call `updateWrappedNativeTexture` to repoint the wrapper at the new handle without losing the InternalTexture identity.
3. Render a blue plane into the restored RTT, readback → verify blue pixels (confirms the new handle is wired up correctly and the framebuffer was rebuilt).

Verified locally on Win32 D3D11 Debug: before=13456 red/0 blue, after=0 red/13456 blue.

Requires a `babylon.max.js` build that includes BJS #18469 (merged 2026-05-21). The test will fail on the published npm 9.9.0 UMD because `updateWrappedNativeTexture` doesn't exist there yet — it will pass once the next patch version ships.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 22, 2026 00:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new end-to-end UnitTests scenario validating Babylon.js Native wrapped-native-texture “device loss / restore” behavior by swapping the underlying native texture handle and verifying rendering output changes accordingly.

Changes:

  • Introduces a new C++ GTest that wraps an external GPU texture, renders/readbacks pre- and post-handle swap, and validates pixel colors.
  • Adds a paired TypeScript test harness that creates the RTT over a wrapped native texture and calls updateWrappedNativeTexture to repoint it.
  • Wires the new JS bundle into the UnitTests webpack build and UnitTests CMake asset/source lists.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
Apps/UnitTests/Source/Tests.WrappedNativeTexture.Restore.cpp New GTest driving the two-phase render/readback workflow around a wrapped native texture handle swap.
Apps/UnitTests/JavaScript/webpack.config.js Adds a new webpack entry for the wrapped-native-texture restore test bundle.
Apps/UnitTests/JavaScript/src/tests.wrappedNativeTexture.restore.ts JS-side setup/render/restore functions that exercise wrapNativeTexture + updateWrappedNativeTexture.
Apps/UnitTests/JavaScript/dist/tests.wrappedNativeTexture.restore.js Generated bundle for the new TypeScript test entry.
Apps/UnitTests/CMakeLists.txt Registers the new C++ test source and JS asset so it’s built and packaged into UnitTests.

Comment on lines +61 to +63
engine.updateWrappedNativeTexture(wrappedInternalTexture, newNativeTexture);

// Switch to blue so the C++ side can distinguish "before" (red) from "after" (blue).
bghgary and others added 5 commits May 21, 2026 17:18
…-> 200)

The test's playground uses fire-and-forget parseFromSnippetAsync to fetch a GUI layout over the network. With renderCount=50, the async fetch may not complete before the screenshot is captured on slow CI runners (Ubuntu_Clang_JSC). The rendered image shows the dark 3D background instead of the GUI text panel, producing ~10K pixel diff. This is the flake that has hit Ubuntu_Clang_JSC on multiple PRs (ran=107 passed=106 failed=1, always this test).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The nightly BN pipeline artifact may lag behind npm. When the bundled UMD doesn't include updateWrappedNativeTexture (requires @babylonjs/core >= 9.9.1), throw immediately so the C++ promise rejects and the test fails fast instead of hanging until CI timeout.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
GUI snippet tests (Load GUI snippet with unicode, Parse GUI json with
unicode) called parseFromSnippetAsync / parseFromURLAsync fire-and-forget.
On slow CI runners the async fetch hadn't completed by the capture frame,
causing intermittent failures.

Fix: use config.json `replace` to transform the fire-and-forget pattern
into `return adv.parseFromSnippetAsync(...).then(() => { return scene; })`,
making createScene return a promise. The BN runner already handles async
createScene (`currentScene.then`), so no renderCount hack needed.

Also:
- Port BJS's `guiIsReady()` gate: defer frame counting until all
  AdvancedDynamicTextures report ready (handles image loading after
  GUI parse completes).
- Fix `const` -> `let` for scriptToRun reassignment in the
  scriptToRun code path (latent strict-mode bug).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update playground snippet versions to match BJS config where the code is unchanged (no visual diff, no new reference images needed):
- Solid particle system: #WCDZS#92 -> BabylonJS#531 (v2 snippet format, same code)
- Volumetric Light Scattering + Morph Targets: #5E318S#5 -> BabylonJS#7 (same code)
- wgsl-in-shadermaterial: #8RU8Q3#157 -> BabylonJS#193 (same code)

The latter two are excludeFromAutomaticTesting so no CI impact.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants