gfx-rs / gfx

[maintenance mode] A low-overhead Vulkan-like GPU API for Rust.
http://gfx-rs.github.io/
Apache License 2.0
5.35k stars 548 forks source link

Mystery framerate jumps on Metal #2710

Open kvark opened 5 years ago

kvark commented 5 years ago

Short info header:

I happen to benchmark gfx-portability a lot on macOS. This involves running the same scenario over and over many times under different conditions, like changing the command recording policy, or switching the game settings. For the most part, the runs are consistent to each other, however in some rare cases, I observed unusually high frame rates over considerable time spans.

This happened on different GPUs for different versions of gfx-portability and even for MoltenVK, so it is likely related to macOS itself.

For example, a game may show 75 fps regularly, but then something kicks in, and I see 100+ fps rock solid for 1-10 seconds. Eventually the performance goes back to normal. I'm very curious on what those spikes could be, and if we can make it so we spike 100% of the time :) My wild guesses:

  1. Our frames start aligning with some predefined timeouts in CAMetalLayer part responsible for display synchronization (or the window server):
    • Even when running without VSync (and that's how benchmarking is done), we see that sometimes window server GPU work is unnecessarily delayed, or the presentation itself happens later than expected.
    • I filed bug 48871262 to Apple about this, but we shouldn't keep our hopes up.
    • We might be staying in this "hyper-sync" phase until a frame spike is encountered (i.e. new shader is compiled)
  2. There is a bug at some level of the pipeline (from us to screen) that drops some work and pretends that it's done. So what we are seeing is just numbers that don't correspond to actually presented new frames.
  3. Some power management policy in the OS kicks in and allows GPU to run faster, temporarily.

cc @mstange @JohnColanduoni

JohnColanduoni commented 5 years ago

These all sounds pretty reasonable, and I can't think of anything else it would be off the top of my head. CAMetalLayer has always been tuned for mobile, "no wasted frames" situations (last time I looked at the internals it interacted with CVDisplayLink even when you turn vsync off), so it being responsible via 1/2 wouldn't surprise me at all.