The problem:
LWJGL’s Display.update() (specifically nSwapBuffers) for simplest possible program periodically (every ~5sec) executes ~320 times slower than usual even with no rendering at all.
It creates visible gitter effect every 5 sec. while sprite/shape moving.
I also tried almost similar code with JOGL (through libgdx) and got the same results except FPS, which was almost twice lower (not sure why, I did not investigate)
And no matter which library I use on top of LWJGL/JOGL (slick 2d or libgdx) the same problem exists.
Test Environment:
Java6, Win 7 x64 Ultimate, ICore7-2600, NVidia 570 GTX, latest drivers (280.26 ).
Here is the sample simplified program that produces the effect:
(The render and update methods are left for visualization and could be removed- they do not have any effect on anything.)
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.input.Keyboard;
public class SimplifiedGameLoop
{
static float x;
static float velocity = 0.3f;
static long deltaPreviousJump = Sys.getTime();
static int deltaIterationsJump;
public static void main(String args[]) throws LWJGLException
{
SimplifiedGameLoop.run();
}
private static void init() throws LWJGLException
{
Display.setDisplayMode(new DisplayMode(800, 600));
// Display.setVSyncEnabled(true);
Display.create();
glOrtho(0.0, Display.getDisplayMode().getWidth(), 0.0, Display.getDisplayMode().getHeight(), -1.0, 1.0);
}
public static void run() throws LWJGLException
{
init();
long delta = 0;
while (true)
{
// measure start time
long start = Sys.getTime();
Display.processMessages();
// loop
if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
{
break;
}
update(delta);
render();
Display.update(false);
// measure end time and check for delta jump
delta = Sys.getTime() - start;
deltaIterationsJump++;
if (delta > 20)
{
long now = Sys.getTime();
System.out.println(Sys.getTime() +":"+
" Delta jumped! delta=" + delta +
//" LWJGLDelta=" + Display.getDelta() +
" interval=" + (now - deltaPreviousJump) +
" iterations=" +deltaIterationsJump);
deltaPreviousJump = now;
deltaIterationsJump = 0;
}
}
Display.destroy();
}
private static void update(float delta)
{
x += velocity * delta;
if (x > 700 || x < 0)
{
velocity = -velocity;
if (x > 700)
{
x = 700;
}
else
{
x = 0;
}
}
}
private static void render()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_QUADS);
glVertex2i((int) x, 10);
glVertex2i((int) x + 100, 10);
glVertex2i((int) x + 100, 100);
glVertex2i((int) x, 100);
glEnd();
}
}
Running the above program gives me a following log. (delta= appr. time in millis the last Display.update took (usually it takes ~0.09), interval= effect period, iterations= the number of “usual” quick time game loop iterations between effect takes place)
[quote]95603743: Delta jumped! delta=36 LWJGLDelta=0 interval=330 iterations=668
95604632: Delta jumped! delta=29 LWJGLDelta=0 interval=889 iterations=9341
95605426: Delta jumped! delta=32 LWJGLDelta=0 interval=794 iterations=8271
95610475: Delta jumped! delta=29 LWJGLDelta=0 interval=5049 iterations=55527
95615524: Delta jumped! delta=28 LWJGLDelta=0 interval=5049 iterations=55557
95620574: Delta jumped! delta=29 LWJGLDelta=0 interval=5050 iterations=55554
95625624: Delta jumped! delta=29 LWJGLDelta=0 interval=5050 iterations=55549
95630674: Delta jumped! delta=28 LWJGLDelta=0 interval=5050 iterations=55288
…
[/quote]
Background:
I searched several similar threads, but none of them seems to give me a reason or working solution
http://lwjgl.org/forum/index.php/topic,3956.0.html
http://lwjgl.org/forum/index.php/topic,3359.0.html
http://lwjgl.org/forum/index.php/topic,3563.0.html
What I have discovered so far:
- If I comment out Display.processMessages() (essentually nUpdate() call), the jitters dissapear.
- Shortly before a jitter, WinApi sends a message with type 13 (WM_GETTEXT - http://msdn.microsoft.com/en-us/library/ms632627(v=vs.85).aspx). And after some 22-24 iterations and apprx. 2 millis. the jitter occurs. I have added a log in WindowsDisplay to trace these calls and here is a log
95490352: WM_GETTEXT 13,wParam=520,lParam=37540896,millis=0 result=0
95490357: WM_GETTEXT 13,wParam=520,lParam=37540896,millis=0 result=0
95490357: WM_GETTEXT 13,wParam=520,lParam=37543344,millis=0 result=0
95494071: WM_GETTEXT 13,wParam=520,lParam=37542880,millis=95490676 result=4
95494101: Delta jumped! delta=27 LWJGLDelta=0 interval=3834 iterations=37939
95499123: WM_GETTEXT 13,wParam=520,lParam=37542880,millis=95490676 result=4
95499168: Delta jumped! delta=43 LWJGLDelta=0 interval=5067 iterations=54262
95504196: WM_GETTEXT 13,wParam=520,lParam=37542880,millis=95490676 result=4
95504232: Delta jumped! delta=34 LWJGLDelta=0 interval=5064 iterations=54291
95509255: WM_GETTEXT 13,wParam=520,lParam=37542880,millis=95490676 result=4
95509299: Delta jumped! delta=41 LWJGLDelta=0 interval=5067 iterations=54318
95514319: WM_GETTEXT 13,wParam=520,lParam=37542880,millis=95490676 result=4
95514349: Delta jumped! delta=28 LWJGLDelta=0 interval=5050 iterations=54316
- Interesting part about latter log, is that it seems the same message delivered over and over again (millis parameter (message creation time since last reboot) is the same). However if I move the mouse over the screen it creates another message and starts to deliver it again in the same manner (every 5 sec.)
I dont know maybe it’s some stupid question but I can not fugure out what the problem is…
Any guess would be greatly appreciated…