Skip to content

Improve SDL frame pacing with presentation-aware timing and conservative backend fallbacks - #188

Closed
kunitoki with Copilot wants to merge 9 commits into
mainfrom
copilot/add-rendering-timing-frame-pacing
Closed

kunitoki with Copilot wants to merge 9 commits into
mainfrom
copilot/add-rendering-timing-frame-pacing

Conversation

Copilot AI commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

SDLComponentNative was deriving animation/update deltas from CPU render-start time, which can diverge from the cadence at which frames become visible. This change adds presentation-aware timing and optional frame pacing, while keeping defaults conservative and falling back cleanly when a backend cannot provide reliable display-synchronized feedback.

  • Public pacing configuration

    • Added ComponentNative::FramePacingMode with:
      • automatic
      • off
      • software
      • presentationDriven
    • Added orthogonal ComponentNative::Options controls:
      • withFramePacingMode(...)
      • withMaximumFramesInFlight(...)
    • Kept default behavior conservative: no forced low queue depth, and automatic mode only uses presentation-driven pacing when the backend can support it safely.
  • Backend-neutral pacing policy

    • Introduced an internal FramePacer to centralize:
      • effective mode selection
      • software wake deadlines
      • adaptive lead-time estimation
      • presentation-vs-CPU delta selection
      • reset behavior across minimize/focus/resize/resume/surface-loss paths
    • The pacer distinguishes:
      • CPU update/render duration
      • submission duration
      • GPU completion telemetry
      • validated presentation timing
    • Missed deadlines advance to the next future slot instead of generating catch-up bursts.
  • SDL window/render-loop integration

    • Refactored SDLComponentNative render scheduling to use FramePacer.
    • internalRefreshDisplay() now consumes presentation-derived deltas when validated timing exists, otherwise falls back to monotonic CPU time.
    • Added lifecycle resets so stale timing does not leak across:
      • minimize / restore
      • focus transitions
      • resize / display change
      • device-reset / surface-loss scenarios
    • Preserved repaint-on-demand semantics: no idle frames are generated just to harvest timing samples.
  • GraphicsContext timing/capability hooks

    • Extended GraphicsContext with minimal backend-neutral timing support:
      • timing capability query
      • latest timing sample query
      • optional frame-latency wait
      • optional max-frames-in-flight control
    • Capability reporting is separate from sample validity, so callers can see whether a path is supported without conflating it with the latest usable timestamp.
  • Backend support

    • Direct3D 11
      • Added DXGI frame-latency wait support where available.
      • Added DXGI frame statistics sampling for validated presentation timestamps.
      • Added max-frames-in-flight propagation with conservative clamping/reset behavior.
      • Cleans up disjoint/invalid samples instead of reusing stale presentation data.
    • Metal
      • Added max drawable count control when supported by platform availability.
      • Added asynchronous GPU completion telemetry.
      • Added presented-time sampling via drawable presentation callbacks where available, without treating GPU completion as display time.
    • OpenGL / SDL
      • Keeps conservative fallback behavior.
      • Uses software pacing / present-block telemetry only; does not treat swap return or GL fences as presentation timestamps.
  • Bindings and tests

    • Exposed the new pacing options in Python bindings.
    • Exposed timing capability/info structs and accessors in graphics bindings.
    • Added deterministic pacing tests covering:
      • automatic/fallback mode selection
      • presentation-derived stable deltas
      • adaptive lead time
      • no catch-up burst after overruns
      • non-integral target cadence behavior
      • invalid/missing feedback fallback
      • reset semantics
      • stale/out-of-order presentation sample handling

Example:

auto options = ComponentNative::Options()
    .withVSync (true)
    .withFramePacingMode (ComponentNative::FramePacingMode::presentationDriven)
    .withMaximumFramesInFlight (2);

Copilot AI and others added 8 commits September 17, 2026 02:04
Co-authored-by: kunitoki <707032+kunitoki@users.noreply.github.com>
Co-authored-by: kunitoki <707032+kunitoki@users.noreply.github.com>
Co-authored-by: kunitoki <707032+kunitoki@users.noreply.github.com>
Co-authored-by: kunitoki <707032+kunitoki@users.noreply.github.com>
Co-authored-by: kunitoki <707032+kunitoki@users.noreply.github.com>
Co-authored-by: kunitoki <707032+kunitoki@users.noreply.github.com>
Co-authored-by: kunitoki <707032+kunitoki@users.noreply.github.com>
Co-authored-by: kunitoki <707032+kunitoki@users.noreply.github.com>
Copilot AI changed the title [WIP] Add rendering timing and frame pacing for SDLComponentNative Improve SDL frame pacing with presentation-aware timing and conservative backend fallbacks Sep 17, 2026
Copilot AI requested a review from kunitoki September 17, 2026 02:13
@kunitoki kunitoki closed this Sep 17, 2026
@kunitoki
kunitoki deleted the copilot/add-rendering-timing-frame-pacing branch September 17, 2026 15:26
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.

2 participants