Conversation
Contributor
|
Thanks! The issue here is valid, but this fix doesn't seem to be the right one. I've labelled the relevant issue as zed-team-only as I believe we need to take this on |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Objective
Addresses the
WM_PAINTstarvation described in #61469.On Windows, frames stop reaching the display while input is arriving continuously. The vsync thread invalidates each window once per tick with
RedrawWindow(hwnd, None, None, RDW_INVALIDATE), and the frame is then only drawn when the run loop receivesWM_PAINT. ButWM_PAINTis synthesized rather than queued, so a thread only receives one once its message queue holds nothing else. Any sustained input source keeps the queue non-empty and starves it, so the invalidations never become dispatched paints.I encountered this issue when dragging a scrollbar with a high-polling mouse in my own GPUI application. #61469 describes the same mechanism at the same line. However I have not verified that this resolves the keyboard case as I have not been able to reproduce it, so I'm not including a closing keyworkd.
Solution
Keep the existing invalidation and additionally post a real message,
WM_GPUI_VSYNC_FRAME, from the vsync thread. A posted message queues behind the input rather than losing to it. Its handler callsUpdateWindow, which delivers the pending paint directly and is a no-op when the update region is empty.Testing
I added a counter to check the number of messages that arrive, and another one to check how many times the window actually paints. Windows 11, 240Hz display.
The window should paint 240 times a second. Before the fix it manages 147 with a real hand on the mouse, and as few as 13 when the input never pauses (tested via PowerShell script). After the fix it holds a steady 240 no matter how much input arrives.
Nothing here is actually slow. A complete paint (building the element tree, layout, GPU submit and present)
takes about 120us out of the 4170us available per frame. The frames were not late, they were just never dispatched.
Self-Review Checklist:
Release Notes: