problems migrating to Windows 7 64 bits

Started by Achim, January 02, 2010, 10:44:08 AM

Previous topic - Next topic

EgonOlsen

Many thanks. Judging from the log, you are creating 2 textures with 256mb each. That means that you have two textures, each 8192*8192 in size. I assume that at least one is a shadow map. But what's the other one? Is it a normal texture map with that enormous size? Or are you rendering into two gl contexts, i.e. into two frame buffer? Anyway, 8192*8192 is very large and with a lowly card like the 220, may run out of texture memory but you run out of processing power for sure. Try to lower to size of the textures/shadow maps to 1024 or 2048 to see if that helps with performance. Maybe that RDPDD thing isn't the problem then...

EgonOlsen

#16
I've looked into jPCT's shadow code a little deeper. The two textures with 256mb each both belong to the shadow map. One is for alpha and one for depth information. I've tried to render a 8192*8192 shadow map on my ATI Radeon 5870...it didn't work at all even if the card can do up to 16384*16384 in theory. It's just too big. Try to lower the size...

Achim

this is the output of your test program above:
\Display0
--> D3DGraphicsConfig[dev=D3DGraphicsDevice[screen=0],pixfmt=0]
Process exited with exit code 0.

The parameters suggested by the lwgl forum had no effect.

terrain demo: inital fps approx. 130, after some flying around 270 ....

I have to look at the shadow maps. Curious thing is though that on my old system with onboard graphics (!) everything worked allright (it was a 3.6 GHz system, though).



EgonOlsen

Most likely because your old system didn't support such large maps. jPCT falls back to the maximum size the hardware supports. If it had Intel onboard graphics, it didn't even support an offscreen buffer, so the max size of the shadow map was limited to the largest power of two that fits on screen, which usually doesn't exceed 1024.

Achim

Perhaps I am doing somthing really stupid - therefore here the code snippet which sets up the shadow map:

   void setupShadowCaster() {
       if (!SW_RENDERING) {
           sh = null;
           if (useShadows) {
               projector = new Projector();
               projector.setPosition(sun.getPosition());
               projector.lookAt(md.getTransformedCenter());        //NOTE: this requires that structure is setup first
               projector.setFOV(0.7f); //set this value large enough so that the complete shadow is casted
               projector.setYFOV(0.7f);
   
               sh = new ShadowHelper(world, buffer, projector, 1024);
               sh.addReceiver(background);
               sh.setAmbientLight(new Color(64, 64, 64)); //sets the color of the shadow
              // sh.setFiltering(true);
           }
       }
   }

when using HW renderer and Shadow map (i.e. SW_RENDERING = false, useShadows=true)

Loading Texture...karoXY.jpg
Loading Texture...karoYZ.jpg
Loading Texture...karoXZ.jpg
Loading Texture...karobw.jpg
Loading Texture...envmap-alu.jpg
Java version is: 1.6.0_17
-> support for BufferedImage
Version helper for 1.5+ initialized!
-> using BufferedImage
Software renderer (OpenGL mode) initialized
Software renderer disposed
Using LWJGL's AWTGLCanvas
Adding Lightsource: 0
Thread[AWT-EventQueue-0,6,main]
Driver is: RDPDD/6.1.7600.16385 on NVIDIA Corporation / GeForce GT 220/PCI/SSE2
GL_ARB_texture_env_combine supported and used!
FBO supported and used!
OpenGL renderer initialized (using 4 texture stages)
Hardware supports textures up to 8192*8192 in size!
Additional visibility list (2) created with size: 4096
Additional visibility list (3) created with size: 4096
Additional visibility list (4) created with size: 4096
Allocating 4194304 bytes of direct memory!
Caching 4194304 bytes of direct memory!
Allocating 262144 bytes of direct memory!
Caching 262144 bytes of direct memory!


>>> Very slow.


Setting useShadows to false: buffer is only cleared, nothing is rendered (but my simulation worker thread is running)

Loading Texture...karoXY.jpg
Loading Texture...karoYZ.jpg
Loading Texture...karoXZ.jpg
Loading Texture...karobw.jpg
Loading Texture...envmap-alu.jpg
Java version is: 1.6.0_17
-> support for BufferedImage
Version helper for 1.5+ initialized!
-> using BufferedImage
Software renderer (OpenGL mode) initialized
Software renderer disposed
Using LWJGL's AWTGLCanvas
Adding Lightsource: 0
Driver is: RDPDD/6.1.7600.16385 on NVIDIA Corporation / GeForce GT 220/PCI/SSE2
GL_ARB_texture_env_combine supported and used!
FBO supported and used!
OpenGL renderer initialized (using 4 texture stages)

no rendering at all after this (buffer is only cleared)....

EgonOlsen

#20
Setup of the shadows looks fine to me. Can i have a look at the actual render code (i.e. the call to render(...) and that stuff)?

Edit: When not rendering the shadows, make sure that you a) are doing the correct world.render(...); world.draw(...); sequence yourself and b) ensure that you haven't setup the ShadowHelper even if you are not using it later. It adds an additional texture layer for the shadows, which will cause the rendering to look strange if not used later.

Here's a test program in native OpenGL mode. It renders a simple scene with shadows (can be disabled in the code by setting a flag). It prints its frame rate to the console. Please give it a try and report the results.


import java.awt.*;
import com.threed.jpct.*;
import com.threed.jpct.util.*;

public class SimpleShadows {

private FrameBuffer fb = null;
private World world = null;
private Object3D plane = null;
private Object3D cube = null;
private Object3D sphere = null;
private Projector projector=null;
private ShadowHelper sh = null;
private Light sun=null;

private boolean shadows=true;

public SimpleShadows() {
Logger.setOnError(Logger.ON_ERROR_THROW_EXCEPTION);
Config.glColorDepth = 24;
Config.glFullscreen = false;
Config.farPlane = 1000;
Config.glShadowZBias = 0.8f;
Config.glTrilinear=true;
Config.glUseFBO=true;
}

private void initStuff() throws Exception {
fb = new FrameBuffer(800, 600, FrameBuffer.SAMPLINGMODE_NORMAL);
world = new World();
fb.enableRenderer(IRenderer.RENDERER_OPENGL, IRenderer.MODE_OPENGL);
fb.disableRenderer(IRenderer.RENDERER_SOFTWARE);

Config.lightMul=1;

plane = Primitives.getPlane(20, 30);
plane.rotateX((float) Math.PI / 2f);

cube=Primitives.getCube(15);
cube.setAdditionalColor(Color.RED);
cube.translate(0, -30, -10);

sphere=Primitives.getSphere(12);
sphere.translate(0, 0, -50);
sphere.setAdditionalColor(new Color(0,0,50));

world.addObject(sphere);
world.addObject(plane);
world.addObject(cube);

plane.compile(false);
cube.compile(false);
sphere.compile(false);

projector = new Projector();

if (shadows) {
sh = new ShadowHelper(world, fb, projector, 1024);
sh.setCullingMode(false);
sh.addCaster(cube);
sh.addCaster(sphere);
sh.addReceiver(plane);
sh.addReceiver(cube);
sh.addReceiver(sphere);
sh.setAmbientLight(new Color(30,30,30));
sh.setFiltering(true);
}

world.setAmbientLight(90,90,90);
world.buildAllObjects();

sun=new Light(world);
sun.setIntensity(250, 250, 250);
}

private void doIt() throws Exception {
Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 150);
cam.moveCamera(Camera.CAMERA_MOVEUP, 100);
cam.lookAt(plane.getTransformedCenter());

projector.setFOV(0.5f);
projector.setYFOV(0.5f);

SimpleVector pos=cube.getTransformedCenter();

projector.setPosition(pos);
projector.moveCamera(Camera.CAMERA_MOVEUP, 200);
projector.lookAt(pos);
SimpleVector offset=new SimpleVector(1,0,-1).normalize();
projector.moveCamera(offset, 215);

int fps=0;
long time=System.currentTimeMillis();

while (!org.lwjgl.opengl.Display.isCloseRequested()) {
projector.lookAt(cube.getTransformedCenter());
offset.rotateY(0.007f);
projector.setPosition(pos);
projector.moveCamera(new SimpleVector(0,-1,0), 200);
projector.moveCamera(offset, 215);
SimpleVector sp=projector.getPosition();
sp.y+=150;
sun.setPosition(sp);
sun.setAttenuation(-1);

if (shadows) {
sh.updateShadowMap();
fb.clear();
sh.drawScene();
} else {
fb.clear();
world.renderScene(fb);
world.draw(fb);
}

fb.update();
fb.displayGLOnly();

if (System.currentTimeMillis() - time >= 1000) {
System.out.println(fps);
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}
fb.disableRenderer(IRenderer.RENDERER_OPENGL);
fb.dispose();
System.exit(0);
}

public static void main(String[] args) throws Exception {
SimpleShadows cd = new SimpleShadows();
cd.initStuff();
cd.doIt();
}
}


Edit: And here's the same thing for the AWTGLRenderer:


import java.awt.*;

import javax.swing.JFrame;

import com.threed.jpct.*;
import com.threed.jpct.util.*;

public class SimpleShadowsAWT implements IPaintListener {

private FrameBuffer fb = null;
private World world = null;
private Object3D plane = null;
private Object3D cube = null;
private Object3D sphere = null;
private Projector projector=null;
private ShadowHelper sh = null;
private Light sun=null;
private JFrame frame;
private Canvas canvas;
private int fps=0;
private long time=System.currentTimeMillis();

private boolean shadows=true;

public SimpleShadowsAWT() {
Logger.setOnError(Logger.ON_ERROR_THROW_EXCEPTION);
Config.glColorDepth = 24;
Config.glFullscreen = false;
Config.farPlane = 1000;
Config.glShadowZBias = 0.8f;
Config.glTrilinear=true;
Config.glUseFBO=true;
}

private void initStuff() throws Exception {
fb = new FrameBuffer(800, 600, FrameBuffer.SAMPLINGMODE_NORMAL);
world = new World();
canvas=fb.enableGLCanvasRenderer();
fb.disableRenderer(IRenderer.RENDERER_SOFTWARE);

frame=new JFrame("Hello world");
frame.setSize(800, 600);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
frame.add(canvas);
fb.setPaintListener(this);

Config.lightMul=1;

plane = Primitives.getPlane(20, 30);
plane.rotateX((float) Math.PI / 2f);

cube=Primitives.getCube(15);
cube.setAdditionalColor(Color.RED);
cube.translate(0, -30, -10);

sphere=Primitives.getSphere(12);
sphere.translate(0, 0, -50);
sphere.setAdditionalColor(new Color(0,0,50));

world.addObject(sphere);
world.addObject(plane);
world.addObject(cube);

plane.compile(false);
cube.compile(false);
sphere.compile(false);

projector = new Projector();

if (shadows) {
sh = new ShadowHelper(world, fb, projector, 1024);
sh.setCullingMode(false);
sh.addCaster(cube);
sh.addCaster(sphere);
sh.addReceiver(plane);
sh.addReceiver(cube);
sh.addReceiver(sphere);
sh.setAmbientLight(new Color(30,30,30));
sh.setFiltering(true);
}

world.setAmbientLight(90,90,90);
world.buildAllObjects();

sun=new Light(world);
sun.setIntensity(250, 250, 250);
}

private void doIt() throws Exception {
Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 150);
cam.moveCamera(Camera.CAMERA_MOVEUP, 100);
cam.lookAt(plane.getTransformedCenter());

projector.setFOV(0.5f);
projector.setYFOV(0.5f);

SimpleVector pos=cube.getTransformedCenter();

projector.setPosition(pos);
projector.moveCamera(Camera.CAMERA_MOVEUP, 200);
projector.lookAt(pos);
SimpleVector offset=new SimpleVector(1,0,-1).normalize();
projector.moveCamera(offset, 215);

while (frame.isShowing()) {
projector.lookAt(cube.getTransformedCenter());
offset.rotateY(0.007f);
projector.setPosition(pos);
projector.moveCamera(new SimpleVector(0,-1,0), 200);
projector.moveCamera(offset, 215);
SimpleVector sp=projector.getPosition();
sp.y+=150;
sun.setPosition(sp);
sun.setAttenuation(-1);

if (shadows) {
sh.updateShadowMap();
fb.clear();
sh.drawScene();
} else {
fb.clear();
world.renderScene(fb);
world.draw(fb);
}

fb.update();
fb.displayGLOnly();
canvas.repaint();
Thread.yield();
}
fb.dispose();
System.exit(0);
}

public static void main(String[] args) throws Exception {
SimpleShadowsAWT cd = new SimpleShadowsAWT();
cd.initStuff();
cd.doIt();
}

public void finishedPainting() {
if (System.currentTimeMillis() - time >= 1000) {
System.out.println(fps);
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}

public void startPainting() {
}
}


Achim

output for the awtgl version (runs like a charm):
Java version is: 1.6.0_17
-> support for BufferedImage
Version helper for 1.2+ initialized!
-> using BufferedImage
Software renderer (OpenGL mode) initialized
Using LWJGL's AWTGLCanvas
Software renderer disposed
Driver is: RDPDD/6.1.7600.16385 on NVIDIA Corporation / GeForce GT 220/PCI/SSE2
GL_ARB_texture_env_combine supported and used!
FBO supported and used!
OpenGL renderer initialized (using 4 texture stages)
Hardware supports textures up to 8192*8192 in size!
Adding Lightsource: 0
Subobject of object 2/object4 compiled using 2400 vertices in 62ms!
Object 2/object4 compiled to 1 subobjects in 101ms!
Subobject of object 0/object2 compiled using 2400 vertices in 19ms!
Object 0/object2 compiled to 1 subobjects in 29ms!
Subobject of object 1/object3 compiled using 48 vertices in 0ms!
Object 1/object3 compiled to 1 subobjects in 0ms!
Additional visibility list (2) created with size: 4096
Additional visibility list (3) created with size: 4096
Compiled 3 display lists!
8
54
60
61
60
61
60
60
61
60
61
61
60
Visibility lists disposed!


my rendering code:

    @Override   
    public void paint(Graphics g) {
        final int millisToPaint = 1000/framesPerSec;   //time interval for new paint (in thread awt)
        long millisSinceLastPaint = System.currentTimeMillis()-lastTimePainted;
        if (millisSinceLastPaint < millisToPaint) {
             try { thread.sleep(millisToPaint - millisSinceLastPaint); }
             catch (Exception e) {
                System.out.println(Thread.currentThread());
                System.out.println("$3 " + e);
             }
        }  else {
        try {
           // System.out.println("paint called at" + System.currentTimeMillis());
            buffer.clear(Color.DARK_GRAY);
            md.synchPositions();
            if (SW_RENDERING) {
//                if (millisSinceLastPaint < millisToPaint) { 
//                    thread.sleep(millisToPaint - millisSinceLastPaint);
//                }
                world.renderScene(buffer);
                world.draw(buffer);
                drawAnnotations();
                buffer.update();
                buffer.display(g);
            } else {
                if (sh != null) {
                     sh.updateShadowMap();
                    sh.drawScene();
                }
                drawAnnotations();
                buffer.update();
                buffer.displayGLOnly();
                canvas.repaint();
            }
        } catch (Exception e) {
            //the SW renderer sometimes produces concurrent access and nullpointer exceptions
            System.out.println(Thread.currentThread());
            System.out.println("$3 " + e + " " + canvas);
        }
        lastTimePainted = System.currentTimeMillis();
         }
    }

EgonOlsen

#22
60fps for the small test application isn't exactly great, but judging from the value, it seems to be limited by vertical sync (i.e. 60 HZ monitor refresh rate). jPCT doesn't use vsync by default in the native OpenGL renderer, but it's not possible to turn it off in the AWTGLRenderer because it sits on top of AWT, which uses it. Try to disable it in the driver settings to see how high the peek performance actually is.

However...back to your rendering code. The reason why everything is black when disabling shadows is obvious: You are not rendering anything at all in that case. Just change that part to


if (sh != null) {
    sh.updateShadowMap();
    sh.drawScene();
} else {
    world.renderScene(buffer);
    world.draw(buffer);
}


and make sure that you aren't creating the shadow helper at all in this case.

Personally, i suggest to not put the rendering code into paint() but in some other thread. You are putting a heavy load to the awt event dispatch thread (EDT) when doing this, which will make your GUI feel more sluggish than it has to. In addition, you are destroying the multi threaded nature of the AWTGLRenderer with this. This renderer does the actual painting in the EDT anyway (it has to, because it's bound to AWT), but the calls to renderScene() and draw() can and should be executed in another thread. That way, you are separating the calculations from the actual drawing, which will speed up things on multi core cpus. Can't you put this code into your own simulation worker thread and leave paint() alone? That should also fix the problems with...

Quote
//the SW renderer sometimes produces concurrent access and nullpointer exceptions

...because: No it doesn't. The renderer is stable. It's just that jPCT isn't thread safe (http://www.jpct.net/wiki/index.php/Multithreading#Thread_safety), so when doing the rendering in the EDT and manipulating the objects in another thread, you'll run into troubles...as you've obviously noticed judging from this comment... ;)

To summarize:


  • I don't really think that this RDPDD-thing is the problem. It's a bit odd, but most likely not a real problem.
  • Go to the driver setting and disable vertical sync.
  • Re-run my small test app and post the frames per second, so that we can be entirely sure that the hardware/driver combination actually delivers the performance that you can expect from it.
  • If possible, move the code out of paint() and into another thread. I would prefer your own worker thread, if that's possible. If it's not, synchronize your worker thread with the new rendering thread.
  • Remove the sleep-section of the code and add an fps counter (like in the small test app)
  • See, what happens then and how high the frame rate actually is.

Hope this helps...

BTW: Can i download this app somewhere, so that i could run it on my own machines to see how it performs on them?






Achim

Hi Egon,
I knew there must have been a stupid mistake - I'm still confused though, since this code ran on the old machine when shadowing is turned off. I also am skeptical whether your suggestions would increase the frame rate from the currently 1 fps (for medium complexity objects like the one you showed in the demo reel. Simpler ones are a bit faster).

I will let the problem rest for a while and take a fresh look at it in a couple of days, and also have a closer look at your examples.

Thanks a lot for your help so far.

EgonOlsen

Quote from: Achim on January 09, 2010, 10:45:49 PM
I also am skeptical whether your suggestions would increase the frame rate from the currently 1 fps (for medium complexity objects like the one you showed in the demo reel. Simpler ones are a bit faster).
Me too...they were mostly meant as general hints to make your code work as similar as possible to mine, so that it's easier to find the real problem and to get rid of the problem that your comment in the catch block implies. 1fps is really low... ???

But at least we can conclude that your system itself seems to be fine. Maybe it's a Swing related problem!? If you are adventurous, you can also give the Jogl-renderer a try (http://www.jpct.net/wiki/index.php/The_different_renderers#JOGL_support), to see if that changes something.

Achim

an update: in the meantime I have rewritten my app and cleaned up the multithreading model - I now have a main loop doing the jpct rendering, each tensegrity obejct has its own relaxation thread, the user interaction in the awt thread, delegating modifications to the objects to either the main thread or the tensegrity object threads.

This solved the problem - no speed issues any more. However, I still have trouble getting the shadow to work. After setting up the shadow helper, everything looks perfect until I move the camera. After a while, the shadowhelper seems to confuse the camera with the projector - the shadow jumps as if the camera is the shadow-casting light source. This happens faster and more often for big objects - strange.
Also, I notices if you set up the shadow helper while the canvas is not visible yet, the constructor waits indefinitely for an opportunity to paint into the awtgl canvas (jpct1.9 and 2.0 beta). You then have to kill the Java VM process.

EgonOlsen

QuoteThis solved the problem - no speed issues any more. However, I still have trouble getting the shadow to work. After setting up the shadow helper, everything looks perfect until I move the camera. After a while, the shadowhelper seems to confuse the camera with the projector - the shadow jumps as if the camera is the shadow-casting light source. This happens faster and more often for big objects - strange.
The shadow helper switched cameras of the world. If your code does something similar in another thread, it may get confused. Are you doing something like that in your code? If so, try to synchronize that with the calls to the ShadowHelper to see if that helps. I'll have a look at my code too to see, if i did something wrong though.

QuoteAlso, I notices if you set up the shadow helper while the canvas is not visible yet, the constructor waits indefinitely for an opportunity to paint into the awtgl canvas (jpct1.9 and 2.0 beta). You then have to kill the Java VM process.
Yes...the helper needs information from the GL context to initialize but without a visible canvas, no context is there...so it'll wait forever. I'll see if i can hack around this somehow or at least replace the infinite loop with an error instead.

EgonOlsen

You might want to give this beta of 1.21 a try: http://www.jpct.net/download/beta/jpct.jar
It synchronizes some ShadowHelper internals to some camera related methods in World. Maybe that helps....and maybe not... ;)

In addition, it treats an invisible canvas as an error. Depending on the setting in Logger, this will cause jPCT to raise an exception or the application to crash but at least doesn't cause an infinite loop anymore.

Achim

Hi Egon,
many thanks for the quick reply - I briefly tested the new jpct.jar - it doesn't solve my problem - I have to look closer and check whether some synchronisation helps.
I didn't test the improved error handling yet - I keep you updated on my progress.

btw: I will be presenting tensegrities in general and my tensegrity CAD program at RTT Excite - a conference the Munich-based visualization company holds every year - and will of cause mention jpct.
Achim