www.jpct.net

jPCT - a 3d engine for Java => Support => Topic started by: Mr.Marbles on April 04, 2007, 01:44:00 am

Title: FrameBuffer.enableGLCanvasRenderer() performance
Post by: Mr.Marbles on April 04, 2007, 01:44:00 am
Just a quick question about the performance of renderers. In general, should
Code: [Select]
FrameBuffer.enableGLCanvasRenderer(IRenderer.MODE_OPENGL)
have better performance (lower CPU usage) than
Code: [Select]
FrameBuffer.enableRenderer(IRenderer.RENDERER_SOFTWARE, IRenderer.MODE_OPENGL)
Although the first one is hardware rendering, I'm getting poorer performance out of it. I'm not quite sure why. ???
Title: Re: FrameBuffer.enableGLCanvasRenderer() performance
Post by: EgonOlsen on April 04, 2007, 08:19:19 am
Have you disabled the software renderer in addition to enable the canvas one?
Title: Re: FrameBuffer.enableGLCanvasRenderer() performance
Post by: Mr.Marbles on April 04, 2007, 03:55:41 pm
Quote
Have you disabled the software renderer in addition to enable the canvas one?

Yes, I have. I'm using a modified version of your "CarTest" program. Here is the "switchOtions()" method:

Code: [Select]
    private void switchOptions()
    {
        switch (switchMode)
        {
            case (SWITCH_RENDERER):
            {
                isIdle = true;
                if (buffer.usesRenderer(IRenderer.RENDERER_OPENGL))
                {
                    keyMapper.destroy();
                    mouseMapper.destroy();
                    keyMapper = new KeyMapper(awtCanvas);
                    mouseMapper = new MouseMapper(awtCanvas);
                    frame.setVisible(false);
                    frame.setTitle(FRAME_TITLE + SOFTWARE_MODE);
                    frame.removeAll();
                    frame.add(awtCanvas);
                    frame.validate();
                    buffer.disableRenderer(IRenderer.RENDERER_OPENGL);
                    buffer.enableRenderer(IRenderer.RENDERER_SOFTWARE,
                            IRenderer.MODE_OPENGL);
                    openGL = false;
                    frame.setVisible(true);
                    gFrame = awtCanvas.getGraphics();
                }
                else
                {
                    keyMapper.destroy();
                    mouseMapper.destroy();
                    frame.setVisible(false);
                    frame.setTitle(FRAME_TITLE + HARDWARE_MODE);
                    frame.removeAll();
                    buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
                    Canvas canvas = buffer.enableGLCanvasRenderer(IRenderer.MODE_OPENGL);
                    keyMapper = new KeyMapper(canvas);
                    mouseMapper = new MouseMapper(canvas);
                    frame.add(canvas);
                    frame.validate();
                    frame.setVisible(true);
                    openGL = true;
                }
                isIdle = false;
                break;
            }
        }
        switchMode = 0;
    }
Title: Re: FrameBuffer.enableGLCanvasRenderer() performance
Post by: EgonOlsen on April 04, 2007, 04:02:36 pm
Hard to tell what's the problem here without more information. What's your hardware? And could you please try this little benchmark: http://www.jpct.net/download/carbench.zip (http://www.jpct.net/download/carbench.zip) and tell me the frame rates for all three batch-files? (the mt_opengl.bat uses the AWTGLRenderer while the others use software and "normal" OpenGL renderer).
Title: Re: FrameBuffer.enableGLCanvasRenderer() performance
Post by: Mr.Marbles on April 04, 2007, 04:31:24 pm
Here are the results from the benchmark tests:

mt_opengl.bat
Frames rendered: 13171
FPS: 177.30
CPU (usage) : 80%-90%

st_software.bat
Frames rendered: 2100
FPS: 28.25
CPU (usage) : 50%

st_opengl.bat
Frames rendered: 11336
FPS: 152.60
CPU (usage) : 50%

It seems that these results are perfectly matched to the results I'm getting with my test bed as well. In all cases, the hardware renderer produces a better framerate, but it seems that the AWTGLRenderer is more CPU intensive than the software renderer  :-\
Title: Re: FrameBuffer.enableGLCanvasRenderer() performance
Post by: Mr.Marbles on April 04, 2007, 05:02:58 pm
UPDATE

I've applied a 20 milli-sec sleep to my game loop, and the results are very interesting!

In both software and hardware rendering the FPS dropped (obviously), but the CPU usage results were a little unexpected; the software rendering dropped from 50% CPU to ~20% and the AWTGLRenderer dropped from ~85% to <1% !!! I'd be very interested in knowing why since this doesn't make sense to me anymore ???

Title: Re: FrameBuffer.enableGLCanvasRenderer() performance
Post by: EgonOlsen on April 04, 2007, 05:17:02 pm
Funny, isn't it... ;D The main difference between GLRenderer and SoftwareRenderer on the one and the AWTGLRenderer on the other hand is, that the latter one is multi-threaded...it has to be, because drawing has to happen in the AWT-Event-Thread but normal jPCT operations do not.
That's the reason why it consumes more cpu power than the other two on your machine (because it seems to be a dual core/cpu setup or otherwise all renderers would use close to 100% cpu). With AWTGLRenderer, there are two threads running: One does all the calculations (that's your application's thread), the other one (the event thread) all the drawing. If you want to throttle cpu usage, use a sleep (as you've already done). The engine itself will try to pump out data as fast as it can, which will always lead to 100% cpu usage.
However, the results after adding the sleep(20) are i but strange indeed. I don't know the complexity of your test scene, but keep in mind that software renderer needs some cpu cycles to clear the buffers and blit the result. Especially the latter is not cheap in Java, so this may be a reason for the large difference. But as long as adding the sleep helps, i wouldn't worry too much about it... ;)
Title: Re: FrameBuffer.enableGLCanvasRenderer() performance
Post by: Mr.Marbles on April 04, 2007, 07:09:44 pm
Quote
The main difference between GLRenderer and SoftwareRenderer on the one and the AWTGLRenderer on the other hand is, that the latter one is multi-threaded...it has to be, because drawing has to happen in the AWT-Event-Thread but normal jPCT operations do not

Isn't the AWT thread also needed for software rendering? If so, this would also be multi-threaded since both AWT and jPCT threads need to run.

Quote
it seems to be a dual core/cpu setup or otherwise all renderers would use close to 100% cpu

I actually have an Intel P4 with HT (hyperthreading) so I guess it gives similar results to the dual-core.

Quote
If you want to throttle cpu usage, use a sleep (as you've already done). The engine itself will try to pump out data as fast as it can, which will always lead to 100% cpu usage

So that means I've "throttled" the jPCT thread which was the most CPU intensive thread of all, correct? If so, how could the overall CPU usage drop to <1% in AWTGLRenderer mode if the AWT thread is still doing all the painting (hasn't been "throttled")? I'm just not understanding such a low CPU usage with that very short (20 milli) sleep...

Title: Re: FrameBuffer.enableGLCanvasRenderer() performance
Post by: manumoi on April 04, 2007, 07:20:04 pm
I had similar results with awtGLRenderer long time ago when i used a sleep in the game loop... My idea was that the sleep released the control on the currentThread and other threads can be processed in an easier manner... From my experience, the fact is that when you want to use awtglrenderer and listeners (such as mouseListener), it seems you have to had a sleep elsewhere the event management will not be efficient, possibly because the game loop is a no ending loop so the associated thread try to speed up the frequency of the loop as much as possible until reaching the hardware limit... not sure...
Title: Re: FrameBuffer.enableGLCanvasRenderer() performance
Post by: EgonOlsen on April 05, 2007, 01:27:12 am
Isn't the AWT thread also needed for software rendering? If so, this would also be multi-threaded since both AWT and jPCT threads need to run.
No. In software rendering, everything is done in one thread...on jPCT's side. Of course some awt stuff will still run in the event thread as usual but that's not related to drawing the polygons.
About the sleep: A sleep of 20 isn't very short at all plus sleep is not very granular on windows...a sleep of 20 can very well lead to an actual sleep time of 30ms on multi-core/ht machines (because windows defaults to 15ms minimum thread sleep time when detecting multiple cpus).
Title: Re: FrameBuffer.enableGLCanvasRenderer() performance
Post by: Mr.Marbles on April 05, 2007, 05:24:03 pm
Another interesting fact   ;D

I just discovered that wireframe rendering:
Code: [Select]
World.drawWireframe(FrameBuffer, Color)has a higher framerate in software mode!  :o

Any ideas for this one?  ;)
Title: Re: FrameBuffer.enableGLCanvasRenderer() performance
Post by: EgonOlsen on April 05, 2007, 05:30:32 pm
Yes, wireframe rendering in hardware is done without any optimizations. The buffer overhead for serving the draw thread is quite huge in that case. That isn't the case in software mode, so that i can be faster than hardware. When using the "normal" OpenGL renderer, this shouldn't be the case though.