Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (476)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (530)
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  
  Finally! Thank you! JSR-231 works the way I want opengl support to work! :D  (Read 5505 times)
0 Members and 1 Guest are viewing this topic.
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Posted 2006-01-12 22:59:30 »

Now I can finally have opengl in java without the silly listener structure from JOGL!

A spinning triangle now yields the insane number of thousands of fps it should, without any synchronisation with the awt display threads or returning from methods to cause buffers to flip. Cheesy

* Markus_Persson grins and starts shuffling some code around in wurm


[edit: 251?]

Play Minecraft!
Offline kaffiene
« Reply #1 - Posted 2006-01-13 00:50:40 »

What are the specific changes that makes it better?  I've not looked at the new release yet.
Offline Ken Russell

JGO Coder




Java games rock!


« Reply #2 - Posted 2006-01-13 03:18:43 »

I hardly think the listener structure is silly and still recommend it as the most portable way of writing applications. Nonetheless, you're welcome for the new design. Kevin Rushforth, Daniel Rice and Travis Bryson from Sun deserve all of the credit for the refactoring of the API into GLDrawable / GLContext classes. Please post here if you have any problems with the new implementation, although it's received quite a bit of testing and seems to be universally more robust and correct than JOGL 1.1.1.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #3 - Posted 2006-01-13 09:27:23 »

Forcing opengl to behave in a way it really doesn't is very silly indeed, not to mention pointless and makes it harder to port opengl code from other platforms to java.

I strongly discourage anyone from using the default GLCanvas with the listener structure.. you'll get nothing but headache from it.

I'm sorry for expressing such strong views about this, but I just cannot for the life of me see anything good about it. It does not speed up development time, it does not provide more robust code, and it does not speed up the rendering.

Play Minecraft!
Offline DzzD
« Reply #4 - Posted 2006-01-13 09:48:54 »

... API into GLDrawable / GLContext classes. ...

may be a stupid question because i dont really know jogl and java opengl api but reading that topic i was asking myself why thoses classes are called GLDrawable and GLContext and not : OGLDrawable and OGLContext with respective super class GLDrawable and GLContext ?

Bruno

Offline Ken Russell

JGO Coder




Java games rock!


« Reply #5 - Posted 2006-01-13 15:20:23 »

\I'm sorry for expressing such strong views about this, but I just cannot for the life of me see anything good about it. It does not speed up development time, it does not provide more robust code, and it does not speed up the rendering.

It does produce more robust code. In the GLEventListener paradigm the library can decide on what thread the OpenGL work is performed instead of leaving this up to the user. Most vendors' OpenGL drivers are still not really robust in the face of multithreading, and the inherent multithreaded nature of the AWT and Java makes it all too easy to do OpenGL work on more than one thread, even just accidentally. When JOGL switched to executing all GLEventListeners on a single thread instead of multiple threads, the library became much more stable where before it had produced crashes in some situations on almost all supported platforms. Users' code did not change in any way when this single-threading was introduced.

The listener mechanism also happens to decouple the OpenGL work from the specific widget being drawn into so that the same code can trivially (and correctly) draw into e.g. a pbuffer, a lightweight Swing widget, or a heavyweight AWT widget.

You're right about the speed issue although for every real-world application I've seen the overhead of the listener mechanism (and associated single-threading, etc.) has been small. It doesn't necessarily look good for microbenchmarks or 200+ FPS games but is it really necessary to drive the display any faster than the monitor's refresh rate?
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #6 - Posted 2006-01-13 15:51:26 »

Sorry, but the GLEventListener kludge is most certainly NOT more robust code than a simple singlethreaded while (true) { render(); swapbuffers(); } loop.

The listener mechanism might have advantages in a very few specialized cases, but it should absolutely not be the only provided way of doing opengl, as was the case in the past.

And, yes, rendering should be done much faster than the monitor's refresh rate if you want to have some cpu cycles left over for things such as AI, networking and game logic. (At least if you want your game to run at the refresh rate)

Play Minecraft!
Offline Ken Russell

JGO Coder




Java games rock!


« Reply #7 - Posted 2006-01-13 17:53:08 »

Sorry, but the GLEventListener kludge is most certainly NOT more robust code than a simple singlethreaded while (true) { render(); swapbuffers(); } loop.

The listener mechanism might have advantages in a very few specialized cases, but it should absolutely not be the only provided way of doing opengl, as was the case in the past.

The simple rendering loop above is the specialized case, not the listener mechanism. Applications which are event-driven don't have the rendering loop structure. The rendering loop above assumes the target component isn't being removed from the component hierarchy and re-added later as in many applications. The GLEventListener interface handles these situations and more.

That having been said, I agree that the listener mechanism shouldn't be the only way to access OpenGL, as I used to think. It took a while for me and others to see how to incorporate both approaches into the same library.

Quote
And, yes, rendering should be done much faster than the monitor's refresh rate if you want to have some cpu cycles left over for things such as AI, networking and game logic. (At least if you want your game to run at the refresh rate)

The listener mechanism doesn't block unnecessarily or deliberately slow down the rendering to the screen refresh rate any more than your rendering loop above does. If vsync is enabled then both approaches will block on the swapBuffers call.
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #8 - Posted 2006-01-13 20:41:07 »

The simple rendering loop above is the specialized case, not the listener mechanism. Applications which are event-driven don't have the rendering loop structure. The rendering loop above assumes the target component isn't being removed from the component hierarchy and re-added later as in many applications. The GLEventListener interface handles these situations and more.

The listener structure is the specialized case. It's based on the more generic, proper way of exposing opengl.
Even you own code has the listener structure use the direct context control instead of the other way around (which would be silly).

My reason for preferring direct control over the listener structure is very similar to my reason for preferring jogl over java3d. Control, flexibility and speed.
It's not right for all applications, of course, but for pretty much all non-turnbased games, I'd say that using either java3d or the listener structure in jogl is Wrong(tm).


But.. my statement in the topic still holds. I'm very happy you finally took away my last thoughts about switching to LWJGL(*) by making this work. :-)

(* I'm not dissing LWJGL. It would just be a _lot_ of work. Wink)

Play Minecraft!
Offline Ken Russell

JGO Coder




Java games rock!


« Reply #9 - Posted 2006-01-14 01:42:03 »

The listener structure is the specialized case. It's based on the more generic, proper way of exposing opengl.
Even you own code has the listener structure use the direct context control instead of the other way around (which would be silly).

It is true that the listener mechanism is based on the lower-level GLContext APIs. Note however that the JSR-231 APIs are unique in that the GLContext.makeCurrent() call provides enough information to the caller to indicate whether the context was newly created during this makeCurrent call (or failed to be made current because the e.g. the underlying window was not yet realized). Code using the GLContext directly must check the return value from this method in order to correctly handle the window being realized/unrealized, properly reloading textures/display lists, etc. The GLEventListener mechanism avoids scattering this checking code throughout the application and puts it in one place. This is why it more easily supports more general application structures than using the GLContext APIs directly.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline quintesse

Junior Member




Java games rock!


« Reply #10 - Posted 2006-01-15 17:38:13 »

Quote
And, yes, rendering should be done much faster than the monitor's refresh rate if you want to have some cpu cycles left over for things such as AI, networking and game logic. (At least if you want your game to run at the refresh rate)

Have you done any benchmarking to support this that you can share with us? Just curious what the difference could be Smiley
Offline swpalmer

JGO Coder




Where's the Kaboom?


« Reply #11 - Posted 2006-01-15 18:52:38 »

Quote
And, yes, rendering should be done much faster than the monitor's refresh rate if you want to have some cpu cycles left over for things such as AI, networking and game logic. (At least if you want your game to run at the refresh rate)

Have you done any benchmarking to support this that you can share with us? Just curious what the difference could be Smiley

It's just simple logic.  Any CPU time not spent drawing the display is available for processing AI, networking and game logic.  Library code should always have efficiency as one of the goals when it will run along side other code (in this case the rest of the game or simulation that is being rendered).

Offline darkprophet

Senior Member




Go Go Gadget Arms


« Reply #12 - Posted 2006-01-15 19:50:32 »

Quote
And, yes, rendering should be done much faster than the monitor's refresh rate if you want to have some cpu cycles left over for things such as AI, networking and game logic. (At least if you want your game to run at the refresh rate)

I think Markus_Persson forgot to write a *not* after rendering and before should...

DP

Friends don't let friends make MMORPGs.

Blog | Volatile-Engine
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #13 - Posted 2006-01-17 10:24:04 »

Code using the GLContext directly must check the return value from this method in order to correctly handle the window being realized/unrealized, properly reloading textures/display lists, etc. The GLEventListener mechanism avoids scattering this checking code throughout the application and puts it in one place. This is why it more easily supports more general application structures than using the GLContext APIs directly.

The GLEventListener stuff is ideal for things like level editors or test programs where you want to have opengl work nicely with swing.
For (many/most) games, not so much. =)

Play Minecraft!
Offline quintesse

Junior Member




Java games rock!


« Reply #14 - Posted 2006-01-18 23:25:28 »

Quote
It's just simple logic.  Any CPU time not spent drawing the display is available for processing AI, networking and game logic.  Library code should always have efficiency as one of the goals when it will run along side other code (in this case the rest of the game or simulation that is being rendered)

Well, yes, even I understand that  Wink

The thing is that going from a loop-based system to an event-based system is normally such a thin layer that you will hardly notice the difference, in fact Ken said so in one of his messages.

So that's why I wanted to know why Markus was so happy. If it was only for the direct control, fine, perfectly understandable, but the performance difference seen by him surprised me.

And if there's a way to substantiate Markus' claim there might also be a way to improve the situation... or not. DUnno. Like I said, just curious  Smiley
Online princec

JGO Kernel


Medals: 339
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #15 - Posted 2006-01-19 00:15:01 »

Once again it comes down to a question of style. Performance is probably basically unaffected.

Cas Smiley

Offline swpalmer

JGO Coder




Where's the Kaboom?


« Reply #16 - Posted 2006-01-19 04:51:42 »

Quote
It's just simple logic.  Any CPU time not spent drawing the display is available for processing AI, networking and game logic.  Library code should always have efficiency as one of the goals when it will run along side other code (in this case the rest of the game or simulation that is being rendered)

Well, yes, even I understand that  Wink

The thing is that going from a loop-based system to an event-based system is normally such a thin layer that you will hardly notice the difference, ...

The part you quoted was specifically about running faster than the refresh rate, not about the event-based vs. loop-based points Huh

Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #17 - Posted 2006-01-19 10:12:36 »

Once again it comes down to a question of style. Performance is probably basically unaffected.

Cas Smiley

Heh. Not really.

The gleventlistener structure synchronizes each render to the awt dispatch thread.
So if you have a single really long render call in which you, say, load a bunch of textues and set up your VBO structures, no other awt or jogl components work during that time either.


If you're making a game with a single thread doing all rendering, direct control over the contexts is less buggy, faster, and easier. Especially if you're using pbuffers.
If you're making a game with several threads doing the rendering, you can use the gleventlistener structure. But the only real benefit it has is to make sure it's a single thread doing all the rendering. (Meaning you're back at my previous point)

Play Minecraft!
Offline quintesse

Junior Member




Java games rock!


« Reply #18 - Posted 2006-01-21 22:54:02 »

Quote
The part you quoted was specifically about running faster than the refresh rate, not about the event-based vs. loop-based points

True, but if you read all of the thread it kinda makes sense  Smiley

It is true Ken introduced the refresh rate, but knowing Markus is a developer on a MMORPG-type game it is obvious he will want the fastest rendering possible so he has some time left for other things (AI for example). So any system that introduces to much overhead, even if it eases development in some cases, is out of the question.

I just wanted to know how an event-driven layer like JOGL uses could introduce a lot of overhead.

But reading Markus' reply above I think it is not so much overhead (like saying: "look this spinning cube does 300 fps when using a loop and only 200 when using events". Still would like to hear if that is the case.) but more a case of having more control when to do rendering, when to do AI etc and still have a responsive GUI even if the work takes a while.

At least hat is how I understand it now  Smiley
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #19 - Posted 2006-01-22 13:15:46 »

Test case:
A skinned animation test application



All tests were run with JDK 1.5.0_04.
The fps weren't measured until they had been stable for ten seconds, to account for warmup time, and were measured as a counter that get increased every time a frame is rendered, then gets System.out'ed and reset once every second, according to System.currentTimeMillis.

With direct context control and a while(true) loop:
Client JVM: 2185-2195 fps
Server JVM: 2450-2460 fps

With the GLEventListener structure:
Client JVM: 800-825 fps
Server JVM: 835-845 fps

Notes and conclusions:
Please note that this slowdown is CONSTANT per frame, not linear, meaning that the longer you take to render a frame (and the lower fps you have), the lower effect the slowdown of the GLEventListener structure is. You do not need 2500 fps.

For the server JVM, the average rendering time was 0.41 ms with direct context management, and 1.19 ms with the GLEventListener, meaning the GLEventListener overhead is 0.78 ms per render on my computer.
For the client JVM, the numbers are 0.46 ms for direct context, 1.23 for GLEventListener, and an overhead of 0.77 ms.

This means that if you want to run your game at X fps, and run Y amount of AI at the same time, you'll have 0.77 ms more per frame to do so if you don't use the GLEventListener.
If your target fps is 60, that computes to 4.8% extra time for game logic and rendering operations if you change from GLEventListener to direct context control.
If your target fps is 100, the gain is 8.3%.

I have to point out that it's usually not considered worth optimising for a gain of 5-8%. If the code for your application becomes easier with the GLEventListener structure, USE IT.
But if the direct context control is better suited (because you're making, say, a fullscreen game), you'll also gain some  rendering speed by not using it. And that never hurts, right?

[edit: cleared up the bit about the slowdown being constant]

Play Minecraft!
Offline Ken Russell

JGO Coder




Java games rock!


« Reply #20 - Posted 2006-01-22 17:58:21 »

Thanks for the detailed writeup and objective conclusions. Would you consider putting this on a web page somewhere to make it a little more permanent? We need to start a wiki or at least some pages with FAQs and informational links like this one.
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #21 - Posted 2006-01-22 18:51:35 »

I thought http://wiki.java.net/bin/view/Games/WebHome was The Wiki(tm)

If anyone wants to clean up and copy my test there, you're more than welcome to do so. =)

Play Minecraft!
Offline Aikavanak

Junior Newbie





« Reply #22 - Posted 2006-01-23 06:40:15 »

Hello everybody!
As you can probably guess by my lack of posts, I'm new to JOGL but want to write my games using it. (I've played around with DirectX a fair bit, so I'm not completely new to 3D graphics, but then I decided that having multiplatform support would be a good thing for games.) Anyway, as I'll be using JOGL for games, I became very excited as I was reading  this thread, because naturally I want the best performance possible. Unfortunately, I haven't seen any tutorials or code samples on the new direct implementation. So, I looked over the current javadocs in an attempt to teach myself, but failed. So, some questions. If Ken or Markus could answer these, or better yet, post some sample code, I'd greatly appreciate it.

1. Should I just use a GLDrawableFactory to get a drawable, then use that drawable to get a GLContext, and use that context to get the GL object?
2. Is it best to use the normal AWT Canvas for rendering or is there a faster way?
3. If I use a canvas, do I have to call paint() or anything to get the OpenGL graphics to display? I know I have to manually call swapBuffers() in the render loop, but is that all?
4. Are there any other issues I should be aware of with the new implementation? Multithreading, etc?

Thanks in advance!
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #23 - Posted 2006-01-23 21:24:49 »

Some example code:

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  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
package com.mojang.joxsi.demo;

import java.awt.*;
import javax.media.opengl.*;
import javax.media.opengl.glu.*;

public class SingleThreadedGlCanvas extends Canvas implements Runnable
{
    private GLDrawable drawable;
    private GLContext context;
    private boolean ok = false;

    public SingleThreadedGlCanvas()
    {
        this(null);
    }

    public SingleThreadedGlCanvas(GLCapabilities capabilities)
    {
        this(capabilities, null, null, null);
    }

    public SingleThreadedGlCanvas(GLCapabilities capabilities, GLCapabilitiesChooser chooser, GLContext shareWith, GraphicsDevice device)
    {
        super(unwrap((AWTGraphicsConfiguration)GLDrawableFactory.getFactory().chooseGraphicsConfiguration(capabilities, chooser, new AWTGraphicsDevice(device))));
        drawable = GLDrawableFactory.getFactory().getGLDrawable(this, capabilities, chooser);
        context = drawable.createContext(shareWith);
    }

    public void addNotify()
    {
        super.addNotify();
        drawable.setRealized(true);
        ok = true;
    }

    public void update(Graphics g)
    {
    }

    public void paint(Graphics g)
    {
    }

    protected void renderLoop(GL gl, GLU glu)
    {
        while(true) // While the game is still running
       {
             // normal opengl rendering goes here
           drawable.swapBuffers();
        }
    }

    public void run()
    {
        try
        {
            while (!ok || !isVisible())
            {
                Thread.sleep(100);
            }

            while (context.makeCurrent() == GLContext.CONTEXT_NOT_CURRENT)
            {
                Thread.sleep(100);
            }
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }

        GL gl = context.getGL();
        GLU glu = new GLU();

        renderLoop(gl, glu);

        context.release();
        context.destroy();
        System.exit(0);
    }

    private static GraphicsConfiguration unwrap(AWTGraphicsConfiguration config)
    {
        if (config == null) { return null; }
        return config.getGraphicsConfiguration();
    }
}



1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
        JFrame frame = new JFrame("Model Displayer");

        SingleThreadedGlCanvas canvas = new SingleThreadedGlCanvas();
        frame.add(canvas);

        frame.setLocation(200, 0);
        frame.setSize(512, 384);
        frame.setVisible(true);

        new Thread(canvas).start();



And, to answer your questions:
1. See the example code.
2. AWT Canvases are almost certainly the fastest way
3. Yep, after the context is set up, that is all.
4. Don't touch the opengl context or GL/GLU objects outside of the thread running the renderLoop() method. Also, you will have to add some code to deal with contexts that goes bad/lost. I'm not entirely sure how this can happen, but I understand it can.

Play Minecraft!
Offline Aikavanak

Junior Newbie





« Reply #24 - Posted 2006-01-24 02:45:24 »

Thanks Markus!
I have followed your example and it looks like OpenGL is working. I haven't actually done any framerate benchmarks yet, soon I plan on adding a framerate counting/limiting system to my renderer. Before I do that though, I ran into a small issue. Your example adds the SingleThreadedGlCanvas to a JFrame, but based on my reading these forums and the user guide, I thought that Swing components can cause problems. Or is this only when I try to overlap them, use many components in the same container, etc? Either way, I used a JFrame in my code, and was wondering what to about closing the window. As I would like the program to exit when the user closes the windw, obviously there's setDefaultCloseOperation(EXIT_ON_CLOSE), but when I tried that, I get an exception (I named my canvas extension RenderCanvas instead of SingleThreadedGlCanvas):

1  
2  
3  
4  
5  
Exception in thread "Thread-2" javax.media.opengl.GLException: Error swapping buffers
        at com.sun.opengl.impl.windows.WindowsOnscreenGLDrawable.swapBuffers(WindowsOnscreenGLDrawable.java:113)
        at RenderCanvas.renderLoop(RenderCanvas.java:48)
        at RenderCanvas.run(RenderCanvas.java:74)
        at java.lang.Thread.run(Thread.java:595)


Is it correct to assume that this is because the program is calling System.exit immediately, without calling context.release() or context.destroy(); first? If so, is there an easy way around this, or should I just write a windowClosing event listener that calls context.release() and context.destroy()? Might this cause a threading issue?

Thanks for the help.
Offline Ken Russell

JGO Coder




Java games rock!


« Reply #25 - Posted 2006-01-24 08:53:38 »

JOGL reports all OpenGL errors during context management as exceptions rather than silently squelching them. You're correct that the reason you're getting the exception is that you're attempting to do OpenGL rendering while the system is tearing down the windows. To correct this you should add some synchronization to your program to ensure you aren't attempting to render while in the middle of System.exit(). The jogl-demos workspace contains several examples of how to do this, though in the context of the GLEventListener and Animator.
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #26 - Posted 2006-01-24 09:51:30 »

In my example code above, the correct way of quitting is to return from the renderLoop() method.
To do this, you need to change while(true) into while(keepRunning) or something, then set keepRunning to false when the quit button is pressed.

This will ensure that System.exit only gets run after the context has been properly disposed.

Play Minecraft!
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.

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

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

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

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

ctomni231 (43 views)
2014-07-18 06:55:21

Zero Volt (38 views)
2014-07-17 23:47:54

danieldean (32 views)
2014-07-17 23:41:23

MustardPeter (34 views)
2014-07-16 23:30:00

Cero (50 views)
2014-07-16 00:42:17

Riven (50 views)
2014-07-14 18:02:53
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!