Skip to content

Announce the first HUD frame presented after a host-window retry - #189

Merged
Views2k merged 2 commits into
mainfrom
fix/hud-host-retry-acknowledgement
Nov 8, 2026
Merged

Views2k merged 2 commits into
mainfrom
fix/hud-host-retry-acknowledgement

Conversation

@Views2k

@Views2k Views2k commented Nov 8, 2026

Copy link
Copy Markdown
Owner

Failure. HudNativeHostTests (inside WpfStyleRuntimeTests.ApplicationStylesAndNativeControlsPassRuntimeChecks) failed in the nightly dispatched on the #188 branch (run 42505910128) and once in a full local run on 2026-11-07, both at the host-window retry step: after the injected ClientToScreen failure the status stayed on "host window retry after ClientToScreen (0x80070578)" with retries=1 for the whole 4 s window. It passed in the nightlies of 11-06, 11-07 and twice on 11-08.

Cause, from the code. The retry runs: RestartRendererAfterRelease clears _retryPending after 500 ms and the host captures and synchronizes its window again. The acknowledgement never comes for an unchanged scene: HudNativeHostRecovery.Presented() and the Ready status run only from OnPresented, and AnalogHudRenderWorker raises HudPresented only when a presented snapshot is not compatible with the last announced one (HudWindowSnapshot.CompatibleWith, keyed on car, unit, redline, layout, colors and so on, not on time). The test's seed changes only timestamps, so the retried capture presents a compatible scene and nothing fires. The stage passed whenever the previous stage's OnPresented callback was still queued on the dispatcher when the failure was injected, which depends on where that frame landed between two pumps. That is the intermittency.

Product consequence. This is a gap in #183, not only a test problem. In the application a single transient host-window failure leaves the status on the retry text and keeps Retries at 1 until the car or layout changes, so isolated failures hours apart accumulate in one episode, and the fourth releases the host and blanks the HUD until the next game attach or foreground return, contrary to the design note in HudNativeHostRecovery.cs ("a presented frame proves the host window works"). Wisp 2.7.4 shipped with this behavior.

Change. HudNativeHost sets _announceRetriedHost in the retry callback and passes it to AnalogHudRenderWorker.UpdateHud(..., announce: true) from the retried Capture; the worker clears its last announced scene when it dequeues that snapshot, so the first frame presented from it raises HudPresented as before for a changed scene. The request is made at the retry, not at the failure, so a frame presented before the window was synchronized again does not close the retry. If the retried Synchronize throws, Capture does not reach UpdateHud and the flag survives to the next retry. Flags are written and read under the worker's existing gate or on the dispatcher thread. No timing, interval or drawing path changes; the added work is one OnPresented round trip per retry.

Checked. Wisp.App.Tests built once; WpfStyleRuntimeTests run once on the maintainer PC with the change: the HUD host stage (retry and rebuild steps) passed, and the class failed only at the known 200 % display-scaling label-fit check that is unrelated and does not reproduce on the CI runner. The full nightly is dispatched on this branch; its result is recorded in a comment.

Not verified. The intermittent failure was not reproduced (forcing it needs an injected dispatcher delay). The diagnosis rests on reading the code and matches the recorded signature. No in-game check of a real host-window failure on the Store build; the live behavior is inferred from the same code path.

HudNativeHostTests failed once in the nightly suite and once in a full
local run at the host-window retry step: after the injected
ClientToScreen failure the status stayed "host window retry after
ClientToScreen (0x80070578)" with one retry counted for the whole 4 s
window.

The retry itself ran: RestartRendererAfterRelease cleared _retryPending
after 500 ms and the host captured and synchronized its window again.
What never came was the acknowledgement. HudNativeHostRecovery.Presented
and the Ready status run only from OnPresented, and the render worker
raises HudPresented only when a presented snapshot is not compatible
with the last announced one. The retried capture presents the same
scene, so the retry was closed only when a scene change happened to
follow. The test passed whenever the OnPresented callback of the
previous stage's frame was still queued on the dispatcher when the
failure was injected, which depends on where that frame landed between
two pumps. In the application the same gap left the status on the retry
text and kept counting isolated failures in one episode until the car or
layout changed.

The host now asks the worker to announce the first frame presented from
the snapshot captured by the retry, so OnPresented ends the retry and
reports Ready for an unchanged scene as well. The request is made at the
retry, not at the failure, so a frame presented before the window was
synchronized again does not count.
@Views2k

Views2k commented Nov 8, 2026

Copy link
Copy Markdown
Owner Author

Full nightly dispatched on this branch (run 42509178650, workflow_dispatch, windows-latest): Full behavioral and UI checks passed, 6130 of 6130 application tests including the HudNativeHostTests stage. One pass is weak evidence for a timing-dependent failure; the code reading in the description is the basis of the fix.

@Views2k
Views2k merged commit 8697d82 into main Nov 8, 2026
10 checks passed
@Views2k
Views2k deleted the fix/hud-host-retry-acknowledgement branch November 8, 2026 19:05
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.

1 participant