Skip to content

Higher present wall time after upgrading from wgpu 29 to 30 #9937

Description

@panxinmiao

Description

While upgrading Myth Engine from wgpu 29.0.4 to wgpu 30.0.0, our release performance tests showed a repeatable frame-time regression.

Phase measurements localized most of the difference around presentation, so I extracted the relevant path into a small standalone Rust reproducer containing no Myth Engine code.

The attached reproducer performs only:

  1. Surface::get_current_texture
  2. one render pass that clears the acquired texture
  3. Queue::submit
  4. presentation

The wgpu 29 build uses SurfaceTexture::present(), while the wgpu 30 build uses Queue::present(surface_texture). Every acquired texture is rendered to and submitted before presentation.

Reproduction

The attachment contains two projects sharing the same benchmark source, with wgpu fixed to 29.0.4 and 30.0.0 respectively.

wgpu-present-repro.zip

Build both versions:

cargo build --release --workspace --locked

Then run them as separate processes in A29/B30/B30/A29 order:

cargo run --release --locked -p wgpu-present-bench29
cargo run --release --locked -p wgpu-present-bench30
cargo run --release --locked -p wgpu-present-bench30
cargo run --release --locked -p wgpu-present-bench29

Each run uses 10,000 warm-up frames followed by 100,000 measured frames.

Results

Two-run means from the A29/B30/B30/A29 block:

Wall-time segment wgpu 29.0.4 wgpu 30.0.0 Difference
Acquire 13.79 µs 14.05 µs +0.26 µs
Encode + submit 51.15 µs 53.63 µs +2.48 µs
Present 83.29 µs 108.44 µs +25.15 µs (+30.2%)
Total loop 148.23 µs 176.12 µs +27.88 µs (+18.8%)

The final wgpu 29 run returned to the original range, so the result does not appear to be explained by one-way warm-up drift.
These measurements are host-observed wall-clock intervals around the API calls. In particular, the present interval may include driver, WSI, compositor, or frame-pacing waits; it should not be interpreted as pure CPU execution time.

Expected behavior / question

I expected the common acquire-render-submit-present path to remain close to wgpu 29 while retaining the correctness behavior added for unrendered or otherwise unprepared surface textures.

I am not suggesting that #9361 should be reverted. Could maintainers confirm whether this cost is expected, and whether the normal successfully-rendered path could safely avoid part of the presentation preparation work?

I have not completed a commit-level bisect or profiler trace. The benchmark compares the released 29.0.4 and 30.0.0 crates.

Platform

OS: Windows 11, build 10.0.26200.8875 (25H2)
CPU: Intel Core i9-9900K
GPU: NVIDIA GeForce GTX 1080 Ti
Driver: 581.57
Backend: Vulkan
Present mode: AutoNoVsync
desired_maximum_frame_latency: 2
winit: 0.30.13
Rust: 1.95.0, x86_64-pc-windows-msvc

The complete reproducer and lockfile are attached. I have not yet tested DX12, another GPU/vendor, another present mode, or the current development branch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions