Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (107)
games submitted by our members
Games in WIP (536)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  A simpler FPSAnimator  (Read 1503 times)
0 Members and 1 Guest are viewing this topic.
Offline zeyous

Junior Member


Projects: 1



« Posted 2009-03-11 18:23:56 »

Hi all, I know this subject has already been discussed often. However I didn't find a clear argued answer. This post is specially oriented for performance guru like me and people who are looking for an FPSAnimator set in mode ‘schedule at fixed rate’ with a setable FPS value.

What I collected on other forum thread :
* FPSAnimator is good for almost everybody. I agree.
* It is not cross-platform and seems to be unstable.
* Active rendering technique may not be as secure as the listener one.
* Using nano time may waste CPU cycle and we don’t really need this kind of resolution.
* Using Thread.sleep() is wasting a lof of CPU cycles.

When looking into FPSAnimator code I’ve seen it is synchronized and based on a java.util.Timer. It actually doesn’t measure the time needed for executing the display and use the timer queue mechanism. I’ve though damn this is pretty complicated for what I want to achieve. Basically I need a timer which doesn’t mind if the task is taking longer than the period. I think we can do this with a simple wait(period).

What do you think about this draft class ?
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
public class SimpleFPSAnimator extends Thread {

    private GraphDrawable drawable;
    private long delay;
    private AtomicBoolean animating;
    private final Object lock = new Object();

    public SimpleFPSAnimator(GraphDrawable drawble, int fps) {
        super("SimpleFPSAnimator");
        this.drawable = drawble;
        this.animating = new AtomicBoolean();

        setFps(fps);
    }

    @Override
    public void run() {
        animating.set(true);

        try {
            while (animating.get()) {
                long startTime = System.currentTimeMillis();
                drawable.display();
                long timeout;
                while ((timeout = delay - System.currentTimeMillis() + startTime) > 0) {
                    //Wait only if the time spent in display is inferior than delay
                   //Otherwise the render loop acts as a 'as fast as you can' loop
                   synchronized (this.lock) {
                        this.lock.wait(timeout);
                    }
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void shutdown() {
        animating.set(false);
    }

    public boolean isAnimating() {
        return animating.get();
    }

    private void setFps(int fps) {
        delay = (long) (1000.0f / (float) fps);
    }
}


I precise I don’t care about thread-safety, I only have one GLAutoDrawable to display and a unique controller manages the Animator. It is better to use this class with a GLCanvas because it doesn't use special mechanism of Animator to paint GLJPanel (see Animator source).
Offline bienator

Senior Member




OutOfCoffeeException


« Reply #1 - Posted 2009-03-11 20:39:05 »

wait(timeout) and sleep(timeout) should both have similar timing accuracy (and performance). Wait waits on the objects monitor till notify() or timeout, sleep 'waits' till timeout.

Offline bienator

Senior Member




OutOfCoffeeException


« Reply #2 - Posted 2009-03-11 21:09:43 »

the best way to render in opengl is still relying on vsync. If you want to render in a lower framerate than your refresh rate and it is not that important for you to to renter in a custom framerate you could use this trick:
Quote
        drawable.setAutoSwapBufferMode(false);
        drawable.getGL() .setSwapInterval(1); // enable vsync
        final int skip = 1;
        new Thread("Bienator's Animator") {
            @Override
            public void run() {
                System.out.println("start");
                while(true) {
                   
                    drawable.display();
                    drawable.swapBuffers();

                    for(int i = 0; i < skip; i++) {
                        drawable.swapBuffers();
                    }
                }
            }
        }.start();

What does it do?
1. it enables sync
2. renders fast as possible in a while loop
3. but it calls swapBuffers() more as needed (thats the trick, since this will block when vsync is on)

this is the most accurate way (from a timing point of view) to render with targetFPS = refreshRate/skip. Swapping buffers should be relative inexpensive. In worst case the driver would do active waiting on the CPU - but i don't believe that someone would implement vsync in this way. (works perfectly on a geforce, haven't tested it yet on amd hw)

for example with a refresh rate of 60Hz the animator above can easily fix the framerate to 60,30,20,15,12...

possible issues:
-arcane intel chips do not support vsync
-tripple buffers are enabled
-vsynch disabled in driver configuration

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline zeyous

Junior Member


Projects: 1



« Reply #3 - Posted 2009-03-12 10:09:39 »

This is a nice hack, it works on my hardware but it also have some drawbacks. Because it runs as fast as possible the CPU consuming is high. I'm not sure it really blocks on swapBuffers(), since CPU is almost at 100% (rather than ~40%) with my or FPSAnimator.
Offline bienator

Senior Member




OutOfCoffeeException


« Reply #4 - Posted 2009-03-12 18:00:00 »

the trick won't work if your hardware does not support vsync in general.

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Riven (12 views)
2014-07-29 18:09:19

Riven (8 views)
2014-07-29 18:08:52

Dwinin (9 views)
2014-07-29 10:59:34

E.R. Fleming (25 views)
2014-07-29 03:07:13

E.R. Fleming (10 views)
2014-07-29 03:06:25

pw (39 views)
2014-07-24 01:59:36

Riven (39 views)
2014-07-23 21:16:32

Riven (27 views)
2014-07-23 21:07:15

Riven (28 views)
2014-07-23 20:56:16

ctomni231 (59 views)
2014-07-18 06:55:21
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!