Skip to content

Bound the retry loop while acquiring the surface texture - #462

Merged
parasyte merged 1 commit into
mainfrom
fix/460
Aug 12, 2026
Merged

parasyte merged 1 commit into
mainfrom
fix/460

Conversation

@parasyte

@parasyte parasyte commented Aug 4, 2026

Copy link
Copy Markdown
Owner

This will turn the infinite loop into an error. It does not address the cause of the infinite loop. Users who experience the hang will instead need to handle the error appropriately instead of terminating the application.

The root cause was identified in #460 as a permenant desynchonization between the window manager's understanding of the window size and pixels' understanding of the surface size. Making pixels robust to this desync is currently out of scope, as it will require a major refactor.

Closes #460
Closes #461

This will turn the infinite loop into an error. It does not address
the cause of the infinite loop. Users who experience the hang will
instead need to handle the error appropriately instead of
terminating the application.

The root cause was identified in #460 as a permenant
desynchonization between the window manager's understanding of the
window size and `pixels`' understanding of the surface size. Making
`pixels` robust to this desync is currently out of scope, as it
will require a major refactor.

Closes #460
Closes #461
@parasyte
parasyte merged commit d0fa7bb into main Aug 12, 2026
20 checks passed
@parasyte
parasyte deleted the fix/460 branch August 12, 2026 04:19
sidick pushed a commit to sidick/Copperline that referenced this pull request Oct 21, 2026
Resizing the main window on Windows could hang Copperline and slow the
whole host until the process was killed (reported on Win11 with an AMD
GPU).

The present worker plans each frame on the main thread and presents it
later. On Windows the main thread pumps the modal size-move loop while
the user drags an edge, so the window changes size under frames still
queued for the worker. wgpu picks Vulkan first there, and the driver
answers VK_ERROR_OUT_OF_DATE_KHR for a swapchain whose extent no longer
matches the window. pixels 0.17.2 retries that acquire in a loop with no
bound, reconfiguring from its cached surface size, which only the main
thread can update, and only after reclaiming the GPU side. The worker
rebuilt the swapchain at the stale size forever while the main thread
waited in PresentWorker::reclaim to apply the Resized event: the window
stopped responding, and the swapchain churn starved the GPU driver. This
is issue CopperlineHQ#362's loop again, now on a thread the corrective event cannot
reach. Single-threaded present never hit it on Windows, since the window
can only change size while that same thread pumps messages.

Each PresentJob now carries the surface size it was planned for, and the
worker compares it with the window's live size before acquiring. A job
whose window has moved on is dropped: it was drawn for the old geometry
anyway, and the Resized behind the change reconfigures the surface on the
main thread for the next frame. On macOS the worker must not call winit,
and the Metal layer never reports a resized surface out of date, so it
presents as before.

The race between that check and the acquire is closed by patching in
upstream's bounded retry (parasyte/pixels#462, unreleased): pixels gives
up after one reconfigure and returns GetSurface(Outdated). That error is
logged at debug as a dropped frame on both present paths; other present
failures stay errors. The patch is a revision-pinned [patch.crates-io] in
the root, player and fuzz workspaces, allowed in deny.toml, to be removed
once a pixels release includes CopperlineHQ#462.

COPPERLINE_THREADED_PRESENT=0 or WGPU_BACKEND=dx12 avoid the hang on
builds without this fix.
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.

render() can loop forever reconfiguring the surface when the cached surface size is stale

1 participant