4.4 KiB
4.4 KiB
NewEditor Live Resize Jitter Root Cleanup Plan
Date: 2026-04-22 Status: In Progress
1. Objective
Clean up the remaining new_editor live-resize jitter without weakening the already-restored anti-deformation contract.
The target contract remains:
- host-driven borderless resize must still be able to present target-size content before the native window visibly adopts that size
- Win32 lifecycle handling must not reintroduce stretched stale content
- resize-time rendering policy must stay centralized and structurally clean instead of being spread across message handlers and chrome code
2. Confirmed Root Cause
The current jitter is caused by two structural problems acting together:
- live borderless resize still drives a real swap-chain resize on each pointer step
- that resize path still performs a hard D3D12 synchronization before touching swap-chain buffers
- the same resize step can then be rendered again from
WM_SIZE,WM_PAINT, and the steady-state main loop
So the root issue is not the custom title bar design. The custom title bar is the mechanism that preserves anti-deformation. The remaining problem is the host-side resize / present execution strategy under it.
3. Red Lines
This cleanup must not:
- remove the custom title-bar-driven anti-deformation flow
- move resize / present ownership into the Editor UI content layer
- add scattered
if (interactiveResize)patches across unrelated code - create a second parallel frame executor beside the existing frame driver
- weaken D3D12 lifetime safety by blindly deleting resize synchronization without replacing it with a narrower correct rule
4. Target End State
After the cleanup:
- immediate resize-time frames still go through one shared frame-driving entry point
- predicted borderless resize transitions present at most one intentional immediate frame per interaction step
WM_SIZEonly acknowledges a predicted resize that was already presented and does not redundantly render it again- the next steady-state app-loop frame is skipped once after an already-presented immediate resize frame
- live resize waits only for tracked in-flight frame retirement instead of forcing a fresh queue-wide idle synchronization each step
5. Implementation Plan
Phase A. Re-centralize immediate resize-time frame execution
- add an explicit immediate-frame path on top of
EditorWindowFrameDriver - route borderless predicted transitions through that shared driver instead of calling
RenderFrame(...)directly - keep transfer-request handling ownership unchanged
Phase B. Add predicted-presentation acknowledgement state
- extend host runtime state so predicted client size can remember whether it has already been presented
- let borderless predicted transitions mark the prediction as presented only after the immediate frame path runs
- teach
WM_SIZEhandling to consume that acknowledgement and skip its redundant render when the incoming size is only the native echo of an already-presented prediction
Phase C. Eliminate the immediate-frame / steady-state double render
- add one-shot state that skips the next steady-state frame after an immediate synchronous frame already presented the same window
- consume that skip only inside
EditorWindowHostRuntime::RenderAllWindows(...) - keep normal steady-state rendering unchanged for all other cases
Phase D. Narrow D3D12 live-resize synchronization
- add a host-device helper that waits only for tracked submitted frame slots to retire
- use that narrower helper from live swap-chain resize
- keep full
WaitForGpuIdle()for shutdown / destruction paths where full teardown semantics are still required
6. Validation Requirements
Before completion:
XCUIEditorAppmust build successfully after the cleanup- borderless live resize must still avoid content deformation
- redundant
WM_SIZE+ steady-state resize-time frame duplication must be structurally removed from the new code path - no unrelated docking / detach / utility-window behavior may regress
7. Completion Criteria
This work is complete only when:
- live resize keeps the anti-deformation contract
- one resize interaction no longer fans out into multiple avoidable frame executions
- D3D12 live-resize synchronization is reduced from queue-wide idle to tracked frame retirement
- the resulting code remains a mainline host/render lifecycle cleanup instead of a symptom patch