If you want to run at a fixed 60FPS and don’t have access to VSync doing a constant Thread.yield() checking System.nanoTime() appears to be the only way to get decent timing. Thread.sleep() is usually +/- 10ms which is unacceptable for trying to get a consistent 16.7ms per frame.
I’m a little worried that Thread.yield() will be too CPU intensive and have platform dependent issues and was wondering if anyone has any insight into how Thread.yield() works or a better way to avoid high CPU usage but also achieve reliably timing.
I’ve tried using Java Audio but the SourceDataLine blocking behavior is just as bad as Thread.sleep().
I’m going to shamelessly plug my own implementation, that is now in the nightly build of LWJGL:
Looks interesting, how well does it work? What is the typical number of sleep(1) calls per frame? How often does it over-sleep and by how much?
Every few minutes it misses its scheduled frame time by slightly over 1ms.
In other words: it’s extremely accurate.
The number of sleeps is irrelevant, you can easily calculate it. It’s all about reducing the number of yields. On my CPU there are about 50-100 yields per frame, which I think is quite low.
This article is quite interesting:
http://www.javamex.com/tutorials/threads/yield.shtml
And it’s probably worth testing your sync code on a few platforms to see if the behavior is consistent.
I’ve done quite a bit of cross platform testing on that method and IMO its probably as accurate as its going to get with those methods (while also not totally killing the CPU) but more testing is always good
How about I run a Java2D game with this at 40FPS on a normal flatscreen, will this prevent tearing then?
Or should it run at 60?
As long as your FPS is less than the refresh rate, you don’t get tearing. If it’s not an integer divisor of your framerate, you may get noticeable stutter however. Isn’t Java2D supposed to respect your desktop’s compositor anyway? That means on windows it should never tear, and on linux it always will.
So, in the new nightly build Display.sync() does exactly this ? Or should one copy that class and use it instead ?
Display.sync(fps) calls Sync.sync(fps)
k, and initialise() is called internally by lwjgl, I presume.
Yes, if only because it’s a private method.
If you want to have a jolly good time, try these:
As long as your FPS is less than the refresh rate, you don’t get tearing. If it’s not an integer divisor of your framerate, you may get noticeable stutter however. Isn’t Java2D supposed to respect your desktop’s compositor anyway? That means on windows it should never tear, and on linux it always will.
False. You can get tearing at any FPS, but it’s most noticeable at higher frame rates. Picture a road intersection. You just stated that we don’t need traffic lights or stop signs as long as the road isn’t completely full of cars.
Right, I was way off by saying you never get tearing, you still need to enable vsync to avoid it entirely. It’s just less apparent on many LCD monitors largely because the refresh itself usually completes long before the mandatory vertical blank interval comes around.