Offscreen render target slowdown

In our app, we are wanting to implement some post-render effects that use both pixel data and z-depth. We generally run at high res, with screen dims ~ 1500 x 1000 (ie big and not a power of 2). In order to do this, I first implemented a Frame Buffer Object, rendered our scenes into that, and copied the result onto a visible quad. This resulted in a MASSIVE slowdown on my 256MB ATI card. On a 512MB nVidia card, it ran fine, however.

Conclusion: either I’m running out of card memory (though a quick calculation of how much space might be required for one of our scenes comes to about 50MB); OR something within ATI is broken. I want to test on a 256MB nVidia card but we don’t have one here :frowning:

So I tried a few experiments. First, I changed it so that I rendered to the screen again (frame rate around 40-50) but then copied the pixels and z into two auxiliary textures using glCopyTexture2D(). That was quicker - but only by a shade over the FBO case. Then I shrunk the size of the window (to less than 1024 x 768 and then 640 x 480) ; if it was running out of vRAM, you might expect to see a sudden speed-up, but instead there was just a very gradual increase. If I take the copying code out, it runs at normal speed again.

So I’m baffled now. Has anyone got any bright ideas as to what might be going on, or how to work around this?

Update: it now seems that it’s the z-buffer copy that’s really dragging, the pixel copy seems fine. I’ve tried fixing the buffer to be 512 x 512 and there’s no change, so it’s nothing to do with not being a power-of-2 size. Bizarrely, our old shadow mapping code used this exact same technique with no drop in frame rate. So maybe it’s something to do with state? :-\

This is usual issues observed with the Java framework. I’ve been using it for more than one whole year intensively and the problem still occurs with frame rate. But I noticed that it can roughly vary when launching from the debugger or the standard command-line while Applets in browser do have unpredictable behaviours, depending on some Java Security options.

In fact, while I test my applications (it is a small game 2D Sprites-rendering demo) with the NetBeans Debug, it really is slow unlike the browser or the standard command line launcher “java -jar myDemo_signed.jar -options…”.
You may try to launch your application from various locations, say the WebBrowser or the java command line or Java Web Start which is a bit slower than command-line java tool, by the way… :-\

Well, we made no progress with this problem so we side-stepped it. I put an nVidia card in my machine and it runs just fine, but now there’s another problem.

I use a frame buffer object as a render target. It has a texture attached for both depth and pixels as I need to use both in post-processing. I then render a quad to the screen, and my pixel buffer renders just fine. However my depth buffer is solid white - it’s as if it was never written to. Yet my pixel buffer wouldn’t render correctly without depth information (and it does). So what the heck is going on?

This is the business end of my FBO wrap:


    private void createBuffers()
    {
        int [] params = new int [1];
        gl.glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, frameBufferID );        
        
        if ( (flags & PIXEL_BUFFER) != 0 )
        {   
            // Create a colour pixel texture.
            gl.glGenTextures( 1, params, 0 );
            pixelBufferID = params[0];
            gl.glBindTexture( GL_TEXTURE_2D, pixelBufferID );
            gl.glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8,  width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null ); 
            
            // Default and user setup.
            gl.glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
            gl.glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );                        
            setUpPixelBuffer( gl );         
            
            // Attach to the frame buffer.
            gl.glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, pixelBufferID, 0 );                
        }
        else        
        {
            // No pixel drawing required do shut down the read / write channels.
            gl.glDrawBuffer( GL_NONE );
            gl.glReadBuffer( GL_NONE );
        }

        if ( (flags & DEPTH_BUFFER) != 0 )
        {
            // Create a depth texture.
            gl.glGenTextures( 1, params, 0 );
            depthBufferID = params[0];           
            gl.glBindTexture( GL_TEXTURE_2D, depthBufferID );
            gl.glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, null );                            
            
            // Set the texture quality
            gl.glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
            gl.glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
            gl.glTexParameterf( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY );
            
            setUpDepthBuffer( gl );
            
            // Attach depth buffer to the frame buffer.
            gl.glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depthBufferID, 0 );
        }
                    
        int status = gl.glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
        if ( status != GL_FRAMEBUFFER_COMPLETE_EXT )
        {
            String errorMsg = getErrorMessage( status );
            throw new Error( "Could not create offscreen render target - " + errorMsg );
        }        

        gl.glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );        
    }

To use it I bind, render the scene, unbind - and I should have a useable pixel and depth texture. Should! Can anyone help?