Serious problems with JOGL backend

Have jReality programming problems or questions? Post them here.
Post Reply
STRESS
Posts: 141
Joined: Mon 19. Jan 2009, 12:10

Serious problems with JOGL backend

Post by STRESS » Mon 9. Feb 2009, 12:52

I have got a serious problem with the JOGL backend when using medium sized geometry. I've got a 512x512 QuadMesh grid in a SceneComponentGraph node. So far everything works fine.

But when I remove that scene node, regenerate the node, add the node again (and I repeat that process maybe once more) my geometry suddenly doesn't show up after the add at all anymore. And it never comes back even when I continue removing and adding.
It just renders a blank scene.

However no error messages comes up onto the console.

Strangely enough when I reduce the grid to 256^2 it never seems to happen.

Also it only seems to happen with filled triangles when I render points it doesn't seem to happen.

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Mon 9. Feb 2009, 13:10

This is indeed mysterious. Here's one thing you can do to try to debug it.

Code: Select all

 ap.setAttribute(CommonAttributes.ANY_DISPLAY_LISTS, false);
Sometimes display lists in the JOGL backend cause problems.

Another thing you can try is not to remove the SceneGraphComponent, but use the sgc.setVisible(false) method to deactivate the rendering. Then change the geometry, and set the scene graph component to be visible again. Does that show the same problem?

Finally, if it's possible to wrap up the offending code in a small example, you're welcome to post it here, then I can run it and see what's happening, hopefully.
jReality core developer

STRESS
Posts: 141
Joined: Mon 19. Jan 2009, 12:10

Post by STRESS » Mon 9. Feb 2009, 13:30

gunn wrote:This is indeed mysterious. Here's one thing you can do to try to debug it.

Code: Select all

 ap.setAttribute(CommonAttributes.ANY_DISPLAY_LISTS, false);
Sometimes display lists in the JOGL backend cause problems.
Yeah that removes the problem but sure slows down the performance. I am surprised that JOGL is using display lists they are known as being not any longer recommended to use by most IHVs and are considered to be outdated for modern graphics hardware.
Another thing you can try is not to remove the SceneGraphComponent, but use the sgc.setVisible(false) method to deactivate the rendering. Then change the geometry, and set the scene graph component to be visible again. Does that show the same problem?
I will try this as well but unfortunately that will not work in all of my cases since sometimes the grid size might change over the course of runtime.
Finally, if it's possible to wrap up the offending code in a small example, you're welcome to post it here, then I can run it and see what's happening, hopefully.
Okay that shouldn't be a problem I am sure I can modify one of the tutorial examples to do the same thing.

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Mon 9. Feb 2009, 16:25

I will try this as well but unfortunately that will not work in all of my cases since sometimes the grid size might change over the course of runtime.
I don't think that will cause problems. You can simply overwrite the geometry of the scene graph component using the setGeometry() method on SceneGraphComponent. In fact, you should be able to do this without calling setVisible(false) beforehand. If you try this, let me know if you still have to turn off display lists.

A final hint regarding OpenGL problems: try running the application with the VM option -Djava.jreality.debugGL=true set. This will catch some OpenGL exceptions that normally go unreported.
Yeah that removes the problem but sure slows down the performance. I am surprised that JOGL is using display lists they are known as being not any longer recommended to use by most IHVs and are considered to be outdated for modern graphics hardware.
Yes that's something I've heard. But until we get vertex arrays working 100%, (and with some of the jReality shading options it's somewhat tricky) they still provide a significant speed-up, as you've found out.
jReality core developer

STRESS
Posts: 141
Joined: Mon 19. Jan 2009, 12:10

Post by STRESS » Mon 9. Feb 2009, 16:56

gunn wrote:
I will try this as well but unfortunately that will not work in all of my cases since sometimes the grid size might change over the course of runtime.
I don't think that will cause problems. You can simply overwrite the geometry of the scene graph component using the setGeometry() method on SceneGraphComponent. In fact, you should be able to do this without calling setVisible(false) beforehand. If you try this, let me know if you still have to turn off display lists.
I will do this but my feeling is that the display list is maybe getting too big I am not sure but I think remembering in the old OpenGL days there was a problem with that.
A final hint regarding OpenGL problems: try running the application with the VM option -Djava.jreality.debugGL=true set. This will catch some OpenGL exceptions that normally go unreported.
Thanks I will try this that will definitely help to narrow it.
Yes that's something I've heard. But until we get vertex arrays working 100%, (and with some of the jReality shading options it's somewhat tricky) they still provide a significant speed-up, as you've found out.
Hmm yes I had a short glimpse at the JOGL backend code. Rewriting it to use VBOs looks to be like quite a massive task not sure if it is worth for the user group jReality is targeting.

But looking at how it is at the moment as a rough personal estimate you're probably get a tenth of the actual possible OpenGL throughput performance. Not sure how much JOGL eats up of that though.

STRESS
Posts: 141
Joined: Mon 19. Jan 2009, 12:10

Post by STRESS » Mon 9. Feb 2009, 17:35

gunn wrote: I don't think that will cause problems. You can simply overwrite the geometry of the scene graph component using the setGeometry() method on SceneGraphComponent. In fact, you should be able to do this without calling setVisible(false) beforehand. If you try this, let me know if you still have to turn off display lists.
Thanks gunn that works :D without using setVisible and without deactivating DisplayList. Okay that will hopefully do the trick for now I think I can restructure my code to work around this problem for the time being.

Btw activating OpenGL debug didn't come up with anything useful :(.

If you are still interested I can post some code that levitates the problem.

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Mon 9. Feb 2009, 20:27

If it's not too much trouble and the code isn't too complicated, please post it. I've seen intermittent problems like this but never have had an example that could be easily debugged. Can't promise I'll find time to do anything about it.
jReality core developer

STRESS
Posts: 141
Joined: Mon 19. Jan 2009, 12:10

Post by STRESS » Tue 10. Feb 2009, 12:00

Sure gunn no problem

Code: Select all


import javax.swing.JFrame;
import java.awt.event.KeyListener;
import java.awt.*;
import de.jreality.geometry.QuadMeshFactory;
import de.jreality.scene.*;
import de.jreality.shader.CommonAttributes;
import de.jreality.shader.DefaultGeometryShader;
import de.jreality.shader.DefaultLineShader;
import de.jreality.ui.viewerapp.ViewerApp;
import de.jreality.util.SceneGraphUtility;
import de.jreality.shader.ShaderUtility;
import de.jreality.util.CameraUtility;


public class MeshFrame implements KeyListener {
	
	private SceneGraphComponent dispGraph = null;
	private SceneGraphComponent root;
	
	private IndexedFaceSet createSurface( int N, int mode ) {
		double [][][] coords = new double [N][N][3];
		double [][][] colors = new double [N][N][3];
		for( int i=0; i<N; i++) {
			double v = -.4 + .8*(i/(N-1.0));
			for (int j = 0; j<N; ++j)	{
				double u = -.3 + .6*(j/(N-1.0));
				coords[i][j][0] = 10.0f - (20.0f/(float)N) * (float)(i);
				coords[i][j][1]= 10.0f - (20.0f/(float)N) * (float)(j);
				if (mode == 0)
					coords[i][j][2]= Math.sin((i+j)*0.1);
				else
					coords[i][j][2]= Math.cos((i+j)*0.01);

				colors[i][j][2]= Math.max(0.5 + 0.5 * coords[i][j][2],0.0);
					
			}
		}
		
		QuadMeshFactory factory = new QuadMeshFactory();
		factory.setVLineCount(N);		
		factory.setULineCount(N);		
		factory.setClosedInUDirection(false);	
		factory.setClosedInVDirection(false);	
		factory.setVertexCoordinates(coords);	
		factory.setVertexColors(colors);
		factory.setGenerateFaceNormals(true);
		factory.setGenerateTextureCoordinates(true);
		factory.setGenerateEdgesFromFaces(true);
		factory.setEdgeFromQuadMesh(true);
		factory.update();
		
		return factory.getIndexedFaceSet();
	}
	
	private SceneGraphComponent buildNewGraph(int mode, 
								       char renderMode)
	{
		SceneGraphComponent graph =
				SceneGraphUtility.createFullSceneGraphComponent("graph");
		graph.setGeometry(createSurface(512,mode));
		Appearance ap = graph.getAppearance();
		ap.setAttribute(CommonAttributes.LIGHTING_ENABLED,false);
		//ap.setAttribute(CommonAttributes.ANY_DISPLAY_LISTS, false);
		DefaultGeometryShader dgs = ShaderUtility.createDefaultGeometryShader(ap, true);
		if (renderMode == 'f' ||
		    renderMode == 'F')
		{
			dgs.setShowFaces(true);
			dgs.setShowLines(false);
			dgs.setShowPoints(false);
		} else {
			dgs.setShowFaces(false);
			dgs.setShowLines(true);
			dgs.setShowPoints(false);
		}
		DefaultLineShader dls = (DefaultLineShader) dgs.createLineShader("default");
		dls.setLineLighting(false);
		dls.setTubeDraw(false);
		dls.setLineWidth(1.0);
		dls.setVertexColors(true);
		return graph;
	}
	
	public MeshFrame()
	{
		root = SceneGraphUtility.createFullSceneGraphComponent("world");
		JFrame f = new JFrame();
		ViewerApp va = new ViewerApp(root);
		dispGraph = buildNewGraph(0,'F');
		root.addChild(dispGraph);
		Camera sceneCamera = 
			CameraUtility.getCamera( va.getCurrentViewer());
		sceneCamera.setFieldOfView(60);
		sceneCamera.setNear(1.0);
		sceneCamera.setFar(100);
		CameraUtility.encompass( va.getCurrentViewer());		
		Component comp = (Component)va.getViewingComponent();
		comp.addKeyListener(this);
		f.getContentPane().add(comp);
		f.setSize(512, 512);
		f.validate();
		f.setVisible(true);
	}
	
	public void keyPressed(java.awt.event.KeyEvent e)
	{
	}
	
	public void keyReleased(java.awt.event.KeyEvent e)
	{
	}
	
	public void keyTyped(java.awt.event.KeyEvent e)
	{
		if (e.getKeyChar() == '0' ||
		    e.getKeyChar() == '1')
		{
			root.removeChild(dispGraph);
			dispGraph = null;
			System.gc();			
			if (e.getKeyChar() == '0')
				dispGraph = buildNewGraph(0,'F');
			else
				dispGraph = buildNewGraph(1,'F');
			root.addChild(dispGraph);
		}
	}	
	
}

And

Code: Select all

public class MeshFrameExample {

	public static void main(String[] args) {
		MeshFrame f = new MeshFrame();
	}

}
Just press 1 and 0 a couple of times and probably after the third time it disappears (on my machine). Or suprisingly enough when you change the 512 in createSurface to lets say 768 it doesn't even render the first time.

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Thu 19. Feb 2009, 12:17

Thanks for the code. I ran it as suggested. On my machine, using the parameter 512, it runs slow but I can toggle between '0' and '1' without any problems. When I set the parameter to 768, on the second iteration I ran out of memory. When I set the memory up from 1G to 3G, I was also able to toggle this a couple times -- more I didn't have time for.

So it seems to depend on the configuration of the system you're running. Of course, if you don't need to set vertex colors, vertex normals, edges, etc, you'll have that much more free space. Also, to see how much memory you're using you can use the InfoOverlay class. Add following code to MeshFrame() method: (see this tutorial for another example).

Code: Select all

import de.jreality.jogl.plugin.InfoOverlay
...
if (va.getCurrentViewer() instanceof de.jreality.jogl.Viewer) {
    InfoOverlay io =InfoOverlay.perfInfoOverlayFor((de.jreality.jogl.Viewer)va.getCurrentViewer());
    io.setVisible(true);
}

[/url]
jReality core developer

STRESS
Posts: 141
Joined: Mon 19. Jan 2009, 12:10

Post by STRESS » Thu 19. Feb 2009, 18:56

gunn wrote:Thanks for the code. I ran it as suggested. On my machine, using the parameter 512, it runs slow but I can toggle between '0' and '1' without any problems.
Hmm so it could be platform related either it is a problem in the Windows 32bit JOGL implementation or it's the OpenGL NVidia driver. I can try updating it. I haven't checked this particular program on a Linux machine. Btw 512^2 runs at acceptable speed when using VertexArrays for me.
gunn wrote: When I set the parameter to 768, on the second iteration I ran out of memory. When I set the memory up from 1G to 3G, I was also able to toggle this a couple times -- more I didn't have time for.
Strange again I can run 768 with 1G of Java heap
gunn wrote: Also, to see how much memory you're using you can use the InfoOverlay class. Add following code to MeshFrame() method:
Thanks I will have a look at that

Post Reply