I have noticed curious thing - my application, with almost nothing inside and vsync turned out is consuming full cpu. Strange… so I started investigating.
I have a skybox, few static meshes with shadows and glow - nothing fancy. 1600x1200 windowed mode, good GPU, 4 cores.
Vsync on: 60fps, 25% cpu utilization
Vsync off: >400fps, 48% cpu utilization
Hmm - first strange thing, how can it utilize more than one cpu? Maybe some driver magic, let’s profile. ALL traces are stopping at LwjglRenderer.checkFrameBufferError, at glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT). It takes 15ms to execute this call in vsync case. Ok, so maybe it IS the vsync (I have no idea what this method does). But why it does it by busy-looping cpu?
Just for kicks, I have removed the call (as it is always returning GL_FRAMEBUFFER_COMPLETE_EXT in my case). And suddenly
Vsync on: 60fps, 3% cpu utilization
Vsync off: >400fps, 30% cpu utilization.
And displays till looks good.
I don’t know what is happening here - I suppose that this call is needed - but why it turns vsync on case into cpu-hog?
When I disable SLI it behaves exactly the same way - to be honest, not sure if it is even used when running jme3 by default. Anyway, it doesn’t look to be SLI related.
I have a strange feeling it has to be related to vsync somehow. Many many calls are taking zero time and exactly one call per frame is taking around 15ms (which is almost vsync time of 16ms - 1ms is probably spent doing ‘real’ things). But I was always under impression that vsync waits somewhere else (on swap frame?) and it is doing non-busy wait.
I have tried disabling vsync and setting framerate to 60 - in such case, I’m getting 60fps and around 10% cpu utilization, but display is getting choppy at some points. Additionally, I suppose it won’t help with tearing if screen update happens in the middle of rendering?
Ok, done same tests in fullscreen mode. Same results - vsync on, huge cpu utilization, vsync off and framerate set to 60 - small cpu utilization. But this time, with vsyn being off, I was noticing really bad tearing (in windowed mode with vsync off and framerate set to 60, it was occasional hiccup in input processing - here, a proper across the screen display tear).
So yes, it seems that in windowed mode there is no tearing even with vsync off. Still, setting it to on limits the framerate to 60, so it has some effect. In any case, setting vsync to on, regardless of windowed/full screen mode is causing full or even 2x cpu busy spin in glCheckFramebufferStatusEXT.
mhh…I have the same behavior. Not as much though.
but i have 17% cpu with vsync off on the testDirectionalLightShadows, and 25% with vsync on.
if I remove the checkFrameBufferError in the renderer I have 17 with vsync off and 13 with vsync on.
I have an Nvidia GTX 670
That’s strange…this check error thing is only there in case of error, but removing it would make it difficult to debug in case of bad FrameBuffer.
I’m gonna investigate a bit on this.
I thought glCheckFramebufferStatusEXT would check to make sure the frame is complete. If so then it’s what is implementing the vsync behavior, right?
The issue (to me) is that in the examples mentioned it seems to be busy-waiting.
Abies, in your test scene you mention shadows and glow… both of which require off-screen rendering. Do you have the same issue when you are only rendering directly to the frame buffer? ie: no shadows, no post-processing at all, etc.
vsync on - high cpu
vsync on, shadows on, no glow - high cpu
vsync on, no shadows, glow on - high cpu
vsync on, no shadows, no glow - 5%
Now, high cpu is very interesting thing. It is either 25% or 50% (1 or 2 full cores). It often starts with 2, but when I minimize the window and maximize it back, it drop to 1 core. Another interesting thing - I have pause on focus lost disabled, so when I minimize application window, it is still rendering - but with around 500-600 fps (which makes my monitor hum).
@pspeed - yes, for me it doesn’t matter at which point in app it is doing the wait, as long as it is not doing busy wait.
I looked a bit into it, I wonder if glCheckFramebufferStatusEXT must not "wait " for the buffer to be available to check errors. Maybe there is some kind of lock mechanism when the buffer is rendered.
Vsync would make this lock last longer and glCheckFramebufferStatusEXT would stall the cpu until it’s available.
That’s just a blind shot, but that would explain the difference with vsync.
Anyway, not sure how to fix this…Only idea I see is to have some debug mode for the renderer that would toggle on the errors check, and one would have to make sure it’s off when releasing…
@nehon said:
I looked a bit into it, I wonder if glCheckFramebufferStatusEXT must not "wait " for the buffer to be available to check errors. Maybe there is some kind of lock mechanism when the buffer is rendered.
Vsync would make this lock last longer and glCheckFramebufferStatusEXT would stall the cpu until it's available.
That’s just a blind shot, but that would explain the difference with vsync.
Anyway, not sure how to fix this…Only idea I see is to have some debug mode for the renderer that would toggle on the errors check, and one would have to make sure it’s off when releasing…
Sounds about right, but why using a own debugmode, we could just use the java provided assert for that. -ea in command line to enable else its disabled. (And let the sdk pass -ea by default)