Skip to content

Metal-first frame-specific presentation feedback for SurfaceTexture #9856

Description

@tuoxiansp

Focused follow-up to #2869. The broad API investigation already covers presentation statistics; this issue asks whether a small, feedback-only slice can land first. If maintainers prefer to keep all API discussion in #2869, please close this and I will move the concrete evidence there.

Is your feature request related to a problem? Please describe.

On wgpu 29.0.4, SurfaceTexture::present(self) returns () and the public SurfaceTexture exposes no token that can later be paired with actual presentation. GPU completion and return from present() are both earlier than display presentation, so applications cannot measure frame-specific input-to-display latency or distinguish a displayed frame from a dropped one.

The Metal backend already owns the necessary object: wgpu-hal's private Metal SurfaceTexture retains an MTLDrawable, and Queue::present consumes it through presentDrawable. Metal provides addPresentedHandler, presentedTime, and drawableID, but the current public wgpu boundary cannot reach them.

In a real-window 120 Hz calibration using the current wgpu/Vello surface, the time from SurfaceTexture::present() return to the same CADisplayLink.targetTimestamp was p50 7.613 ms / p95 7.858 ms over 28 valid samples. That fallback only estimates the next display tick; it cannot prove that the particular drawable was shown. The almost-one-tick ambiguity is precisely the information an actual feedback API would remove.

Describe the solution you'd like

A capability-gated, frame-specific feedback API that lets an application associate one presented surface texture with an eventual result such as:

  • a stable present ID/token;
  • Presented { timestamp } or NotPresented/dropped status;
  • a timestamp in a documented presentation clock plus a supported way to correlate it with the application's monotonic clock.

The exact Rust shape is open. A future/receiver returned from present, a callback, or a Surface::poll_presentation_feedback() queue could all work as long as feedback stays paired to the submitted SurfaceTexture. For a Metal-first implementation, wgpu-hal could register MTLDrawable.addPresentedHandler before presentDrawable, retain only the minimal ID/result state, and report presentedTime == 0 as not presented.

This request intentionally does not require exposing raw MTLDrawable, predicting or scheduling future presentation, damage rectangles, monitor statistics, or changing surface ownership. Other backends can report the capability as unavailable until they have a reliable implementation.

Describe alternatives you've considered

  • GPU completion callbacks: prove GPU work completed, not display presentation.
  • Timing SurfaceTexture::present() return: proves only that the present request returned.
  • CADisplayLink.targetTimestamp: estimates a display tick but cannot identify which drawable was displayed or whether it was dropped.
  • Owning a separate CAMetalLayer/drawable path: provides feedback but replaces wgpu's single surface owner and is not an acceptable integration for applications that need to keep the standard wgpu surface path.
  • Reading private wgpu-hal fields or relying on layout: unsafe and not maintainable.

Additional context

I am happy to adapt the use-case/reporting details to an API direction preferred by maintainers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions