Understanding X Present extension events from the NVIDIA driver

There is work in progress adding frame pacing to the picom compositor for latency reduction. The approach we took is using the PresentCompleteNotify event from the X present extension. Basically we deduce when vblank starts and ends from those events, and only render once per vblank interval.

The interesting thing we noticed is that, when a NVIDIA GPU is connected to a VRR capable display, doesn’t matter if VRR is disabled in the settings, the vblank interval becomes uneven. And how often vblanks occur seems to correlate with how often we render. With a 175hz display, if we use the strategy of render once per vblank, the vblank interval lengthens, to ~16ms; if we render as often as possible, the vblank interval is ~5ms, which is close to the expected value.

My hypothesis is that even with VRR disabled, the driver is just emulating a fixed refresh rate in software, in the graphics API. (i.e. a timer in glXSwapBuffers, throttling the rate frames are submitted). And therefore the PresentCompleteNotify events only represent the longest possible vblank interval.

Is that correct? Can someone shed more light on this? And any advice on how to do this properly? I think the right thing to do is query the driver for the minimal vblank interval and render at that rate, but I don’t know how to get that information from the driver.

Actually, I don’t think this is related to VRR. Even with a non-VRR monitor, the vblank interval is irregular. Why is the vblank interval different from the actual refresh rate? Is this a bug in the driver?