Bounded CPU-side waits on GPU progress, and the shared device-lost flag. More...
Classes | |
| struct | donner::geode::GpuWaitTestHooks |
| Test seams for BoundedGpuWait. Production callers pass none; tests inject a fake clock and a sleep recorder so timeout behavior is verified deterministically and without real sleeping. More... | |
Namespaces | |
| namespace | donner |
| Top-level Donner namespace, which is split into different sub-namespaces such as donner::svg and donner::css. | |
Typedefs | |
| using | donner::geode::GpuWaitSite = gpu::DeviceLostWaitSite |
| Which bounded wait exceeded its deadline and declared the device lost. The runtime owns the enumeration because the condition belongs to the backend root, not to the Geode wrappers over it; see gpu::DeviceLostWaitSite. | |
| using | donner::geode::GeodeDeviceLostState = gpu::DeviceLostState |
| Shared device-lost flag of one backend root, observed and published by every Geode context over it and by a host embedder's own device-lost callback. Owned by the runtime; see gpu::DeviceLostState. | |
Enumerations | |
| enum class | donner::geode::GpuWaitResult { Complete , TimedOut , DeviceLost } |
| Outcome of a bounded GPU wait. More... | |
Functions | |
| std::ostream & | donner::geode::operator<< (std::ostream &os, GpuWaitResult value) |
| Ostream output operator, e.g. TimedOut. | |
| GpuWaitResult | donner::geode::BoundedGpuWait (const std::function< bool()> &pollOnce, std::chrono::microseconds timeout, std::chrono::microseconds pollInterval=kGpuWaitPollInterval, const GpuWaitTestHooks &testHooks={}) |
Repeatedly invoke pollOnce until it returns true or timeout expires. | |
| bool | donner::geode::DeclareDeviceLost (DeviceLostState &state) |
| Declares a state lost with no wait to attribute it to; see gpu::DeclareDeviceLost. | |
| bool | donner::geode::DeclareDeviceLostAfterWaitTimeout (DeviceLostState &state, DeviceLostWaitSite site, std::chrono::milliseconds elapsed) |
| Declares a state lost because a bounded wait gave up; see gpu::DeclareDeviceLostAfterWaitTimeout. | |
Variables | |
| constexpr std::chrono::milliseconds | donner::geode::kDefaultGpuWaitTimeout {5000} |
| Default bound for waits that previously blocked without limit (teardown drains, inter-submit serialization, editor readback maps). | |
| constexpr std::chrono::milliseconds | donner::geode::kReadbackMapTimeout {10000} |
| Bound for snapshot readback map waits. Matches the long-standing readback deadline: snapshot consumers tolerate up to 10 seconds under heavily loaded parallel test runs before declaring the device unresponsive. | |
| constexpr std::chrono::microseconds | donner::geode::kGpuWaitPollInterval {100} |
| Poll cadence for non-blocking wait loops. The 100 us cadence bounds completion-detection latency without measurable CPU cost; the snapshot readback path was tuned to this cadence and the perf ceilings assume it. | |
Bounded CPU-side waits on GPU progress, and the shared device-lost flag.
A hung GPU driver can leave a fence or buffer-map wait blocked forever, in the worst case in uninterruptible kernel sleep. Donner cannot fix drivers, but no thread the application relies on may block unboundedly on the GPU: a hung device must surface as a detectable device-lost condition instead of a hung process. Every native CPU-blocks-on-GPU wait in the Geode stack routes through this header so the timeout policy lives in exactly one place.
This header is deliberately WebGPU-free (chrono, functional and ostream only) so the wait loop can be unit tested without a GPU via the injectable clock and sleep hooks.
|
strong |
Outcome of a bounded GPU wait.
| GpuWaitResult donner::geode::BoundedGpuWait | ( | const std::function< bool()> & | pollOnce, |
| std::chrono::microseconds | timeout, | ||
| std::chrono::microseconds | pollInterval = kGpuWaitPollInterval, | ||
| const GpuWaitTestHooks & | testHooks = {} ) |
Repeatedly invoke pollOnce until it returns true or timeout expires.
pollOnce must be non-blocking: one device poll (or callback-flag check) that returns true when the awaited condition has been observed. The loop never blocks inside the driver, so a hung device costs at most timeout plus one pollInterval instead of hanging the calling thread forever.
The happy path costs one pollOnce call and one clock read, so wrapping an already-complete wait adds no measurable overhead.
| pollOnce | Non-blocking poll; returns true when the wait is over. |
| timeout | Total time budget for the wait. Taken in microseconds because the readback wait slices below a millisecond, and a budget rounded up to a whole millisecond would coarsen the poll cadence the readback path is tuned to. |
| pollInterval | Sleep between polls while the condition is pending. |
| testHooks | Optional clock/sleep overrides for deterministic tests. |
pollOnce returned true, TimedOut otherwise. | std::ostream & donner::geode::operator<< | ( | std::ostream & | os, |
| GpuWaitResult | value ) |
Ostream output operator, e.g. TimedOut.
| os | Output stream. |
| value | Value to output. |
|
inlineconstexpr |
Default bound for waits that previously blocked without limit (teardown drains, inter-submit serialization, editor readback maps).
A wait for submitted work measures it as time without progress, not as a budget for the whole wait: the awaited work completes only after everything queued ahead of it, and a slow device can take far longer than this to get through a long backlog while still finishing command buffers. A healthy device finishes some command buffer well within the bound, so it only trips when the device has effectively hung.