Skip to content

Remove DeviceUpdate usage and mark the shim deprecated#1653

Merged
bkaradzic-microsoft merged 1 commit into
masterfrom
remove-device-update
Jun 11, 2026
Merged

Remove DeviceUpdate usage and mark the shim deprecated#1653
bkaradzic-microsoft merged 1 commit into
masterfrom
remove-device-update

Conversation

@bkaradzic-microsoft

@bkaradzic-microsoft bkaradzic-microsoft commented Apr 7, 2026

Copy link
Copy Markdown
Member

DeviceUpdate became a no-op compatibility shim when the threading model was reworked (#1652) — frame synchronization is now handled by FrameCompletionScope inside StartRenderingCurrentFrame/FinishRenderingCurrentFrame.

This PR:

  • Removes all of its now-redundant callers across the apps, platform shells (Win32/UWP/X11/Android/iOS/macOS/visionOS), and unit tests.
  • Marks DeviceUpdate::Start/Finish/RequestFinish and Device::GetUpdate [[deprecated]] so any remaining external callers get a warning. The type itself is left un-deprecated so GetUpdate can keep returning it without a self-warning (no compiler-specific pragmas needed). The shim implementation is kept for source compatibility and will be removed in a future PR.

Rebuilt fresh on top of current master (the original branch predated the squash-merge of #1652). Verified locally on Win32: Playground and UnitTests build clean with no deprecation-warning leakage, and all UnitTests pass.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Removes the deprecated Babylon::Graphics::DeviceUpdate compatibility shim and updates samples/apps/tests to rely solely on Device::StartRenderingCurrentFrame() / Device::FinishRenderingCurrentFrame() for frame synchronization.

Changes:

  • Deleted DeviceUpdate and Device::GetUpdate() from the public graphics device header.
  • Removed DeviceUpdate usage across unit tests and sample applications.
  • Updated ExternalTexture documentation examples to no longer reference DeviceUpdate.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
Plugins/ExternalTexture/Readme.md Removes DeviceUpdate calls from the D3D12 example snippet.
Core/Graphics/Include/Shared/Babylon/Graphics/Device.h Removes deprecated DeviceUpdate type and GetUpdate() API.
Apps/UnitTests/Source/Tests.UniformPadding.cpp Drops DeviceUpdate usage around frame start/finish.
Apps/UnitTests/Source/Tests.ShaderCache.cpp Drops DeviceUpdate usage in frame-pumping loop.
Apps/UnitTests/Source/Tests.ExternalTexture.D3D11.cpp Drops DeviceUpdate usage (minor formatting/spelling nits remain).
Apps/UnitTests/Source/Tests.ExternalTexture.cpp Drops DeviceUpdate usage around frame boundaries.
Apps/UnitTests/Source/Tests.Device.D3D11.cpp Drops DeviceUpdate usage inside back-buffer iteration.
Apps/StyleTransferApp/Win32/App.cpp Removes g_update lifecycle and frame sync calls.
Apps/PrecompiledShaderTest/Source/App.cpp Removes deviceUpdate from render/unblock sequencing.
Apps/Playground/X11/App.cpp Removes DeviceUpdate() calls from the main loop tick.
Apps/Playground/Win32/App.cpp Removes DeviceUpdate() calls from loop and suspend/resume paths.
Apps/Playground/visionOS/LibNativeBridge.mm Removes DeviceUpdate() calls from resize/render callbacks.
Apps/Playground/UWP/App.cpp Removes DeviceUpdate() calls from run loop and suspend/resume.
Apps/Playground/Shared/AppContext.h Removes DeviceUpdate() accessor and stored optional.
Apps/Playground/Shared/AppContext.cpp Removes m_deviceUpdate initialization/teardown and usage.
Apps/Playground/macOS/ViewController.mm Removes DeviceUpdate() calls from Metal view callbacks.
Apps/Playground/iOS/LibNativeBridge.mm Removes DeviceUpdate() calls from resize/render entrypoints.
Apps/Playground/Android/BabylonNative/src/main/cpp/BabylonNativeJNI.cpp Removes DeviceUpdate() calls from JNI render tick.
Apps/HeadlessScreenshotApp/Win32/App.cpp Removes deviceUpdate usage from headless render flow.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Apps/UnitTests/Source/Tests.ExternalTexture.D3D11.cpp Outdated
Comment thread Apps/UnitTests/Source/Tests.ExternalTexture.D3D11.cpp Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@bkaradzic-microsoft bkaradzic-microsoft force-pushed the remove-device-update branch 2 times, most recently from 98212e9 to 758fcdc Compare April 9, 2026 16:02
bghgary added a commit that referenced this pull request Jun 9, 2026
[Updated by Copilot on behalf of @bghgary]

## Context

Replaces the old per-thread encoder model
(`GetEncoderForThread`/`EndEncoders` + `UpdateToken` wrapping
`SafeTimespanGuarantor`) with a **single frame encoder** owned by
`DeviceImpl`, synchronized by a `FrameCompletionScope` RAII gate.
`SafeTimespanGuarantor`, `UpdateToken`, and the `Update` classes are
removed. `DeviceUpdate` remains as a no-op shim — removing it is an API
break and a separate PR (#1653).

## Model

`StartRenderingCurrentFrame` acquires the encoder (`bgfx::begin`) and
opens the gate; `FinishRenderingCurrentFrame` waits for all
`FrameCompletionScope`s to release, closes the gate, ends the encoder,
and submits the frame. All consumers (NativeEngine, Canvas, NativeXr)
read the shared encoder via `GetActiveEncoder()`. `SubmitCommands` and
`ReadTexture` each hold a stack-scoped `FrameCompletionScope`, so the
encoder can't be ended mid-work; when invoked outside a frame (e.g. an
XHR callback) the scope blocks until the next frame opens.

```
Main Thread                       JS Thread                 bgfx render thread
  StartRenderingCurrentFrame()
    m_frameEncoder = bgfx::begin(true)
    m_frameBlocked = false; CV notify
    tick frameStartDispatcher  -----> RAF callbacks
                                        submitCommands()
                                        AcquireFrameCompletionScope (immediate; frame open)
                                        GetEncoder() -> m_frameEncoder; draw...
                                        scope released; pendingScopes-- -> CV notify
  FinishRenderingCurrentFrame()
    wait scopes == 0; m_frameBlocked = true
    tick beforeRenderDispatcher
    bgfx::end(m_frameEncoder)
    Frame() -> bgfx::frame()  ------------------------------> GPU submit & render
    tick afterRenderDispatcher
```

## Synchronization rules

1. Single encoder, acquired before the gate opens (mutex gives memory
ordering) and ended only after all scopes release.
2. `SubmitCommands`/`ReadTexture` always hold a scope — the encoder
can't be ended mid-command, regardless of microtask draining or
reentrancy.
3. Apps must bracket any main-thread wait for JS work with
`Start`/`Finish`, or `SubmitCommands` blocks forever waiting for the
gate (HeadlessScreenshotApp, StyleTransferApp, UnitTests do this).
4. `Canvas::Flush` acquires a scope when called outside a frame, then
discards residual encoder state before nanovg rendering (the shared
encoder carries NativeEngine state).

## Notes

- `Tests.ExternalTexture.Msaa.cpp` opens the next frame before waiting
on `startup()` — a workaround for the legacy async `AddToContextAsync`
pattern, obsoleted once #1646's sync `CreateForJavaScript` lands.
- `Tests.ExternalTexture.RestoreAfterDeviceLoss` (added on master after
this branch) uses the same async pattern; the same frame-pump workaround
is applied here. Obsoleted once #1646's sync `CreateForJavaScript`
lands.
- bgfx: added `m_encoderBeginLock` in `bgfx::frame()` to prevent a
deadlock with `bgfx::destroy()`.
- Follow-up: removing the `DeviceUpdate` no-op shim is an API-breaking
change handled in #1653.

---------

Co-authored-by: Branimir Karadzic <branimirkaradzic@gmail.com>
Co-authored-by: Gary Hsu <bghgary@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft changed the base branch from rework-thread-model to master June 10, 2026 22:58
@bkaradzic-microsoft bkaradzic-microsoft marked this pull request as ready for review June 10, 2026 22:58
@bkaradzic-microsoft bkaradzic-microsoft force-pushed the remove-device-update branch 2 times, most recently from 6ddbf11 to fa082bd Compare June 10, 2026 23:17
@bkaradzic-microsoft bkaradzic-microsoft changed the title Removed DeviceUpdate. Remove DeviceUpdate usage and mark the shim deprecated Jun 10, 2026
DeviceUpdate became a no-op compatibility shim when the threading model was
reworked (#1652) -- frame synchronization is now handled by
FrameCompletionScope inside StartRenderingCurrentFrame/
FinishRenderingCurrentFrame.

This removes all of its now-redundant callers across the apps, platform shells
(Win32/UWP/X11/Android/iOS/macOS/visionOS), and unit tests, and marks
DeviceUpdate::Start/Finish/RequestFinish and Device::GetUpdate [[deprecated]]
so any remaining external callers get a warning. The shim itself is kept for
source compatibility and will be removed in a future PR. The type is left
un-deprecated so GetUpdate can keep returning it without a self-warning.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bkaradzic-microsoft bkaradzic-microsoft merged commit 50888fa into master Jun 11, 2026
28 checks passed
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.

3 participants