Repository navigation
Integrate native canvas texture updates and font metrics - #19041
Conversation
Babylon Native GUI text rendered differently from the browser in two ways: - ThinNativeEngine.getFontOffset returned all zeros (a TODO), so GUI controls computed zero line heights and mis-positioned or clipped text. It now measures the font with the native Canvas, using font bounding-box metrics as browsers do for line layout, and falls back to glyph bounds on older runtimes, then to an estimate from the CSS px size. The measuring canvas is created once, reused, and disposed with the engine. - createDynamicTexture ignored generateMipMaps, and updateDynamicTexture ignored premulAlpha. Minified GUI and text textures therefore aliased, and alpha blending differed from the browser. The flags are now passed to Canvas.getCanvasTexture, gated on the runtime advertising supportsDynamicTextureMipMaps, so older runtimes keep the previous behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
|
Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s). |
There was a problem hiding this comment.
🟡 Changes recommended
Texture updates bypass the promised compatibility gate, and failed context initialization can replace canvases without disposing them.
2 open issues
What changed in this PR
This PR improves Babylon Native GUI text layout and dynamic texture rendering through ThinNativeEngine.
Changes:
- Adds native font measurement with fallback estimates and a reusable measuring canvas.
- Forwards dynamic texture alpha and mipmap options, with capability-gated mipmap creation.
- Adds unit tests for font bounds, canvas reuse, and texture options.
| File | Description |
|---|---|
packages/dev/core/test/unit/Engines/nativeEngine.fontMetrics.test.ts |
Tests font metrics and dynamic texture behavior. |
packages/dev/core/src/Engines/thinNativeEngine.pure.ts |
Implements font measurement, canvas cleanup, and texture option handling. |
packages/dev/core/src/Engines/Native/nativeInterfaces.ts |
Declares the optional native runtime capability. |
Review effort: Balanced
Address review feedback: - updateDynamicTexture now passes the premultiplied-alpha and mip options to Canvas.getCanvasTexture, and records _premulAlpha, only when the runtime advertises supportsDynamicTextureMipMaps. Older runtimes keep the argument-less legacy call. - getFontOffset reuses the existing measuring canvas when its 2D context was unavailable, so a retry never orphans a canvas that engine disposal would not release. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
|
Please make sure to label your PR with "bug", "new feature" or "breaking change" label(s). |
|
Snapshot stored with reference name: Test environment: To test a playground add it to the URL, for example: https://snapshots-cvgtc2eugrd3cgfd.z01.azurefd.net/refs/pull/19041/merge/index.html#WGZLGJ#4600 Links to test your changes to core in the published versions of the Babylon tools (does not contain changes you made to the tools themselves): https://playground.babylonjs.com/?snapshot=refs/pull/19041/merge To test the snapshot in the playground with a playground ID add it after the snapshot query string: https://playground.babylonjs.com/?snapshot=refs/pull/19041/merge#BCU1XR#0 If you made changes to the sandbox or playground in this PR, additional comments will be generated soon containing links to the dev versions of those tools. |
Add INativeCanvas (ICanvas plus a required dispose()) for native-only disposal, and use it for INativeCanvasConstructor, createCanvas and _fontMeasureCanvas. This removes the cast and the optional call. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
|
WebGL2 visualization test reporter: |
Popov72
left a comment
There was a problem hiding this comment.
Approve. The complete current-head review found no actionable issues in native font measurement, canvas lifetime, or capability-gated dynamic texture updates.
🟢 Memory Leak Test Results4 passed, 0 leaked out of 4 scenarios 🟢 All memory leak tests passed — no leaks detected. Passed Scenarios (4)
|
⚡ Performance Test Results🟢 All performance tests passed — no regressions detected. |
|
WebGL2 visualization test reporter: |
|
Visualization tests for WebGPU |
|
CI note: the only failure in Native tests (experimental) is GUI Gradient Linear with transparency (641/642 passed; it fails all 3 retries with a 60% diff). The KHR_interactivity failure is a browser crash or timeout on The cause is a cross-repo pairing. Chrome interpolates canvas gradient stops in straight RGBA, and the reference expects (191, 8, 11) at (50,50). BN master interpolates premultiplied, then hands out the raw premultiplied texture, so legacy
I reproduced this locally with this PR's CDN snapshot in a BN Playground. With BabylonJS/BabylonNative#1889 it shows no pixel difference. Plan: BabylonJS/BabylonNative#1889 now temporarily excludes this test, so it can land first. Once the BN nightly includes it, re-running this PR's Native tests should pass. The test is re-enabled in BN after the Babylon.js npm update. |
## Problem The BabylonNative Nightly CI pipeline hasn't published a build since #1889 landed: | Run | BN commit | Nightly job | Packaged VisualizationTests | |---|---|---|---| | 61289 (last success) | bac047b | 59 min (just under the limit) | 34 min | | 61325 (manual) | c181462 | cancelled at 60 min, during UnitTests | 39 min | | 61329 (scheduled) | c181462 | cancelled at 60 min, during Upload Playground | 38 min | The `Nightly` job has no `timeoutInMinutes`, so Azure applies its 60-minute default. As more validation tests are enabled, the packaged visualization run has grown, and the job now overruns before publishing `BabylonNativeNightlyPlayground`. Babylon.js CI only uses fully succeeded nightly runs, so it is still testing against bac047b. That is why BabylonJS/Babylon.js#19041 keeps failing on "GUI Gradient Linear with transparency", which #1889 addresses. Each failure re-runs the whole native suite 3 times, which then hits B.js's own 90-minute limit. ## Fix Set `timeoutInMinutes: 180` on the `Nightly` job. Run 61329 also had an unrelated agent-lost failure on Android macOS JavaScriptCore during the ccache restore. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
deltakosh
left a comment
There was a problem hiding this comment.
Hello @bkaradzic-microsoft,
Approved from my side; merging still depends on the required CI gate passing.
Thanks!
Bumps all `babylonjs*` packages from 9.31.3 to 9.32.1. 9.32.1 includes BabylonJS/Babylon.js#19041 and #19043. It also enables 14 tests that now pass: - Gaussian Splatting modify - Gaussian Splatting Bake Transforms - GUI Transform StackPanel - GLTF Box with bad Draco normalized flag - GLTF Buggy with Meshopt Compression - Order independent transparency - GUI Force Resize Width - GUI Gradient Linear with transparency - Vertex buffers with non aligned strides - Font size inheritance - skybox-with-boombox - OpenPBR Thin Walled Subsurface Transmission Blending - IBL - FrameGraph nrge clustered lights - Clustered lights - debug markers **Depends on #1975 (Draco full bitstream).** Without it, the GLTF Draco tests (202–206) fail with Babylon.js 9.32.1. Verification: I ran Win32 D3D11 V8 locally with this change plus #1975, #1976 and #1977, as a single process like CI. Result: `ran=689 passed=689 failed=0`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae

Babylon Native GUI text renders differently from the browser in two ways. This PR fixes both in
ThinNativeEngine.Font metrics
getFontOffsetreturned all zeros (it was a TODO). As a result, GUI controls computed zero line heights, and text was mis-positioned or clipped.It now measures the font with the native Canvas, using font bounding-box metrics for line layout as browsers do. On older runtimes it falls back to glyph bounds, and then to an estimate from the CSS px size. The measuring canvas is created once, reused, and disposed with the engine.
Dynamic texture flags
createDynamicTextureignoredgenerateMipMaps, andupdateDynamicTextureignoredpremulAlpha. Minified GUI and text textures therefore aliased, and alpha blending differed from the browser.Both flags are now passed to
Canvas.getCanvasTexture. This is gated on the runtime advertisingsupportsDynamicTextureMipMaps, so older Babylon Native runtimes keep the previous behavior.Tests
nativeEngine.fontMetrics.test.ts.packages/dev/core/test/unit/Engines/: 30 files, 261 passed, 1 expected fail.tscandeslintare clean.