Open Intrets opened 2 years ago
OK so this has to do with the graphics driver (I have read only nvidia does it this way?) spinlocking for synchronization.
Taking a look at how GLFW handles this: https://github.com/glfw/glfw/blob/63da04e5ced93fcb87a20513acdff5d78b1166ff/src/wgl_context.c#L321-L342, seems to be a good solution (stood the test of time) even though it is called a hack.
Bare minimum to get it working: https://github.com/Intrets/JUCE/commit/c942217c39299f0011d8a8c6c73f705ce84103df
@Intrets
Try switching off continuous repainting with OpenGLContext::setContinuousRepainting(bool)
.
Continuous repainting will always saturate the rendering thread, either by doing actual work or just by sleeping (so that it doesn't hog the Message Manager by constantly locking it).
See the body of juce::OpenGLContext::CachedImage::renderFrame()
// ...
// This avoids hogging the message thread when doing intensive rendering.
if (lastMMLockReleaseTime + 1 >= Time::getMillisecondCounter())
Thread::sleep (2);
// ...
OpenGLContext::deactivateCurrentContext();
Is there any reason why there are the context activations inside renderFrame? As far as I can see that's already handled directly in the render thread job loop.
Apart from that, the dwmapi hint works wonders - also for timed repaints.
BTW: continuous repainting should never saturate the thread because there is swap interval of 1 by default, ie. VSYNC, so it's throttled by the frame rate of the monitor.
When playing around with JUCE and OpenGL I noticed my program was doing essentially nothing but showed high CPU usage. Trying from a fresh and latest version of JUCE, an empty project created from projucer or the demo apps showed the same high CPU usage.
System: OS: Windows 10 home build 19043 CPU: Ryzen 3700x GPU: GTX 1660 super, driver 471.68 Visual Studio: 16.11.2
Reproducing steps:
$Foo
, run Projucer, File -> Global Paths -> set Path to JUCE to$Foo/JUCE
, set JUCE modules to$Foo/JUCE/modules
Expected result: Very minimal CPU usage by the application.
Actual result: The application completely saturates one core and then some. This shows in task manager, the Visual Studio profiler, and while breaking the program with the debugger at an arbitrary time the execution of the program is guaranteed to be in the same function.