Repository navigation
Wake a laptop's discrete card when an iPad looks for PCs - #256
Merged
Merged
Conversation
A laptop powers its discrete card off entirely (D3cold) about 20 s after its last use: on an AMD hybrid laptop the card and every PCIe port above it, up to the root port, went to D3. The next D3D11 device or AMF open on it then took about 800 ms instead of 160, and an AMF session's first picture after 40 s idle took about 870 ms instead of 130. An iPad looks for PCs over mDNS on its connect screen, seconds before it sends HELLO. The host now reads mDNS queries alongside its daemon, and a PTR or ANY question for the service from another device (not the PC's own daemon, which probes at each registration and re-advertisement) creates a D3D11 device on the encoder's adapter on a thread of its own and drops it. Nothing is kept open, and nothing wakes the card on a timer: a wake comes at most every 15 s, never while a viewer is connected, and each one no session followed doubles the wait for the next, up to 10 min.
- The browse watch read into a 1500-byte buffer and stopped at its first receive error: one oversized mDNS datagram (WSAEMSGSIZE) ended warming until the app restarted. It now reads up to mDNS's 9000 bytes, goes on at once after errors that pass, and waits longer after repeated or other errors, up to a minute, without stopping. - A HELLO could start a session between the browse's check and the wake's device. The wake thread now checks again, just before it creates the device, that no session has started since (the session count), and drops the wake if one has. - After a long backoff a session didn't restore the short wait until the old ten-minute one had passed: the gate checked the wait before noticing the session. It now resets the wait first, keeping the 15 s minimum. - Whether to wake now follows the encoder that will stream: the override in Settings, and no wake after a fallback to the CPU, nor for an encoder on another card.
…d it The browse callback judged a snapshot of startup: the detected encoder, the Settings override and the CPU-fallback flag. A hardware fallback (NVENC or AMF failing over to Quick Sync, which clears that flag) still woke the card no one used, and a late GPU detection the supervisor adopted never became wakeable: startup's libx264 stayed in the callback. SharedControl::wake_adapter now holds the card to wake. Each encoder open, fallbacks included, sets it from the encoder that opened and the pipeline's GPU: that GPU's adapter for a hardware encoder of its family, None for the CPU or another card's encoder. Adopting a late detection sets it too, until the new pipeline's encoder opens. The callback reads only that.
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.
Why
On a hybrid AMD laptop, the first session after about 20-40 s idle had its first picture about 700 ms late. The discrete card had powered off entirely (D3cold):
Whatever touches the card first pays for the wake. With a D3D11 device created first, the AMF open that follows took 74-145 ms; without one, the AMF open itself took about 830 ms.
The iPad looks for PCs over mDNS on its connect screen, seconds before it sends HELLO. That is early enough to start the wake.
What
discovery::watch_browsers: reads mDNS on the shared port alongside the daemon, and sends nothing. A PTR or ANY question for_eternaldisplay._udp.localfrom another device callson_browse.Respondevents can't be used: it answers its own probes at each registration and at the 60 s re-advertisement.gpu_wake: on a browse, creates a D3D11 device on the encoder's DXGI adapter on a thread of its own and drops it at once.SharedControl::wake_adapter: the pipeline GPU's adapter for a hardware encoder of its family, None for the CPU or another card's encoder (NVENC or AMF failing over to Quick Sync). Adopting a late GPU detection publishes it too, until the new pipeline's encoder opens. The browse callback reads only that.WakeGate: at most one wake every 15 s. Each wake that no session followed doubles the wait for the next, up to 10 min, so a device that browses and never connects causes a few wakes an hour. A session since the last wake restores the 15 s wait before the elapsed-time check, so a viewer after a long backoff doesn't wait it out (Session::sessions_started).Tests
discovery: a browse for the service is told from other mDNS traffic (other service types, A questions, responses, case, a second question through a compression pointer). Malformed, truncated and self-pointing packets are not browses.discovery, receive errors: an oversized datagram, a reset and an interruption go on at once, then back off if they keep coming. Other errors back off from the first, up to a minute, and the watch never stops.gpu_wake:encoder: an open publishes the card to wake, and a Quick Sync fallback from NVENC clears it.supervisor: an adopted late detection becomes the card to wake, after startup encoded on the CPU.cargo test -p eternal-host --libpasses (1231).cargo clippy --all-targets -D warningsandcargo fmt --checkare clean.cargo clippy -p eternal-host --all-targets -D warningsis clean.Behaviour before and after
Measured at f271721. RX 7600S hybrid laptop, h264_amf, headless synthetic still desktop. The first session after 45 s idle, 6 trials each, client time from HELLO_ACK to the first decoded frame. The client browsed for the service over mDNS (loopback only, in a local test copy) the given time before HELLO.