Detailed steps on how to reproduce the bug
I am changing the refresh rate setting of the same physical monitor in Windows display settings. The only variable I change is the monitor refresh rate: 144 Hz vs 60 Hz.
Repro steps:
-
Build and run a Windows standalone JUCE app that attaches juce::OpenGLContext to a visible component.
-
Keep the app in a light steady-state rendering scenario. In my case:
- component painting enabled
- JUCE continuous repaint disabled
- in standalone builds, the baseline UI timer is 60 Hz when the app is not in an interaction-boosted state
- interaction / playback-related paths in the app can raise the effective frame cadence above that baseline, up to about 120 Hz depending on state
-
In Windows display settings, on the same monitor, set the monitor refresh rate to 144 Hz.
- Windows Settings -> System -> Display -> Advanced display -> Choose a refresh rate
-
Run the app and observe CPU usage and UI smoothness.
-
Without changing the app or code, change the refresh rate of that same monitor to 60 Hz in Windows display settings.
-
Run the same standalone app again and observe CPU usage and UI smoothness.
Observed result:
- At 60 Hz, the standalone app uses noticeably more CPU in Task Manager and feels visibly more stuttery.
- At 144 Hz, the same app on the same monitor is smoother and uses less CPU.
- The workload is otherwise unchanged.
Local investigation note:
I instrumented JUCE's OpenGL path locally. The extra 60 Hz time does not appear to be mainly in renderOpenGL() or swapBuffers().
Instead, the frame-period wait appears around JUCE's Windows OpenGL context lifecycle / first GL setup call:
- initially around
OpenGLContext::deactivateCurrentContext()
- and, if per-frame deactivation is avoided, around the first GL setup call of the next frame
Adding an explicit DwmFlush() before entering the native GL scope moves that wait into an explicit compositor wait, which suggests the 60 Hz pacing cost is being hidden inside JUCE's Windows standalone OpenGL path.
What is the expected behaviour?
Changing the refresh rate of the same monitor from 144 Hz to 60 Hz should not make the same standalone JUCE OpenGL app significantly more CPU-heavy and visibly less smooth for the same workload.
Operating systems
Windows
What versions of the operating systems?
Windows 11
Architectures
x86_64
Stacktrace
Plug-in formats (if applicable)
No response
Plug-in host applications (DAWs) (if applicable)
No response
Testing on the develop branch
The bug is present on the develop branch
Code of Conduct
Detailed steps on how to reproduce the bug
I am changing the refresh rate setting of the same physical monitor in Windows display settings. The only variable I change is the monitor refresh rate: 144 Hz vs 60 Hz.
Repro steps:
Build and run a Windows standalone JUCE app that attaches
juce::OpenGLContextto a visible component.Keep the app in a light steady-state rendering scenario. In my case:
In Windows display settings, on the same monitor, set the monitor refresh rate to 144 Hz.
Run the app and observe CPU usage and UI smoothness.
Without changing the app or code, change the refresh rate of that same monitor to 60 Hz in Windows display settings.
Run the same standalone app again and observe CPU usage and UI smoothness.
Observed result:
Local investigation note:
I instrumented JUCE's OpenGL path locally. The extra 60 Hz time does not appear to be mainly in
renderOpenGL()orswapBuffers().Instead, the frame-period wait appears around JUCE's Windows OpenGL context lifecycle / first GL setup call:
OpenGLContext::deactivateCurrentContext()Adding an explicit
DwmFlush()before entering the native GL scope moves that wait into an explicit compositor wait, which suggests the 60 Hz pacing cost is being hidden inside JUCE's Windows standalone OpenGL path.What is the expected behaviour?
Changing the refresh rate of the same monitor from 144 Hz to 60 Hz should not make the same standalone JUCE OpenGL app significantly more CPU-heavy and visibly less smooth for the same workload.
Operating systems
Windows
What versions of the operating systems?
Windows 11
Architectures
x86_64
Stacktrace
Plug-in formats (if applicable)
No response
Plug-in host applications (DAWs) (if applicable)
No response
Testing on the
developbranchThe bug is present on the
developbranchCode of Conduct