|
|
Donner SVG 0.8.0-pre
SVG editor and embeddable C++20 engine.
|
Bounded CPU-side waits on GPU progress, and the shared device-lost flag. More...
#include <atomic>#include <chrono>#include <cstdint>#include <functional>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... | |
| struct | donner::geode::GeodeDeviceLostState |
| Shared device-lost flag. More... | |
Namespaces | |
| namespace | donner |
| Top-level Donner namespace, which is split into different sub-namespaces such as donner::svg and donner::css. | |
Enumerations | |
| enum class | donner::geode::GpuWaitResult { Complete , TimedOut , DeviceLost } |
| Outcome of a bounded GPU wait. More... | |
| enum class | donner::geode::GpuWaitSite : std::uint8_t { None , ReadbackMap , QueueIdle } |
| Which bounded wait exceeded its deadline and declared the device lost. More... | |
Functions | |
| bool | donner::geode::DeclareDeviceLost (GeodeDeviceLostState &state) |
Declare state lost with no wait to attribute it to. | |
| bool | donner::geode::DeclareDeviceLostAfterWaitTimeout (GeodeDeviceLostState &state, GpuWaitSite site, std::chrono::milliseconds elapsed) |
Declare state lost because a bounded wait at site exceeded its deadline after elapsed. | |
| 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. | |
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 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.
|
strong |
Which bounded wait exceeded its deadline and declared the device lost.
A hung device costs the full timeout wherever it is first waited on, and the two waits have very different budgets and callers, so "the device was declared lost" is not actionable on its own: a readback-map timeout points at buffer-map delivery, a queue-drain timeout points at submitted work never retiring. Recording which one tripped keeps that distinction in the diagnostics a failure report is assembled from.
| 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. | bool donner::geode::DeclareDeviceLost | ( | GeodeDeviceLostState & | state | ) |
Declare state lost with no wait to attribute it to.
For losses the driver reports: there is no deadline behind them, so timedOutSite stays None and says exactly that.
| bool donner::geode::DeclareDeviceLostAfterWaitTimeout | ( | GeodeDeviceLostState & | state, |
| GpuWaitSite | site, | ||
| std::chrono::milliseconds | elapsed ) |
Declare state lost because a bounded wait at site exceeded its deadline after elapsed.
The attribution is written only when this call is the one that declares the loss. Two other writers reach the same flag and neither may claim the site: a later bounded wait, which expires because the device is ALREADY hung (a consequence of the loss, never its cause), and the driver's device-lost callback, which has no wait to name. Deriving the claim from the flag's own transition covers both without a check-then-set window - reading the flag and then storing the site would let a driver-reported loss landing in between be relabelled as a wait timeout, which is the one misattribution an empty site exists to rule out.
| state | Shared device-lost record. |
| site | Which bounded wait expired. |
| elapsed | Wall time that wait spent before giving up. |