`read_output` waited on the copy with `Maintain::Wait`, which parks the
calling thread until the GPU is done. That call is made from the UI
thread, so the interface was frozen for the length of the copy — the
note on this function measures it at ~7 ms at 4K against a 0.28 ms
compute pass, so nearly all of it was the wait.
`Maintain::Poll` drives the same callbacks without sleeping. The mapping
still completes and the pixels are identical; the thread simply is not
parked while it happens.
The poll loop is bounded. A lost device never delivers the map callback,
and spinning forever on that would hang the app rather than report the
error the caller already handles.
This does not remove the round-trip itself, which ARCH §6.1 forbids and
spike S1 replaces by importing the texture into Slint directly. It stops
the round-trip from blocking input until then.
dr-gpu tests pass, including those comparing readback pixels.