FloatBuffers killing Vertex Array performance?

Has anyone out there run into something like this?

I’m trying to build my renderer from the ground up to use vertex arrays for all rendering. I’m getting a big chunk of agp memory using the nvidia extension and splitting it into 2 vertex arrays. When one fills, or runs out of data, I set a fence and swap to using the other vertex array. I think that this should in theory give me pretty optimal vertex submission, as the GPU can chew over what I’ve just sent it while I’m filling the other buffer.

That was the theory anyway…

When I come to run it I can get about 50 fps with 4000 triangles on screen. When I profile to see wtf is going on, it’s spending 50% of its time copying into the floatbuffer that is used for the vertex array!!

Now I’m only running a GF2 but it seems like a long way off the pace to me, when something like benmark is doing in the order of 30 or 40 times that.

I am just using drawArrays which seems to be discouraged, and just drawing random triangles could be a pretty pathological case but does anyone have any ideas?

Post up the -Xprof output.
Drawing random triangles is a pathological case, and indeed, the worst possible use.
You should be able to get performance identical to C with float buffers.

Cas :slight_smile:

Please try using display lists and check how many fps you will get with them.

It is perfectly possible to get any number of frames with any number of triangles. I have managed to get few fps per second with 256 quads - they were just occuping entire screen each, sorted in worst order…

Hi,`

Can someone post some VertexArray usage Code, im not sure how to get this working, using plain OpenGL 1.1 code.

My problems are occure if i call
GL.glDrawElements(GL.GL_QUADS,indexesBuffer);

Mostly the VM crashed if i try to Draw the Elements with a given array. Also i flip the Buffer before calling DrawElements !

  • jens

Jacko - make sure you aren’t creating the float buffer each frame. Create it once, then clear/put/flip each frame.

Mac-Systems - I can give you some code if you want. E-mail?

Here’s the method of my renderer that handles rendering of meshes. This uses Vertex Arrays. Perhaps this can help you out. TriMesh is a class that contains all the buffers.


/**
     * <code>draw</code> renders a <code>TriMesh</code> object including it's
     * normals, colors, textures and vertices.
     * @see com.jme.renderer.Renderer#draw(com.jme.scene.TriMesh)
     * @param t the mesh to render.
     */
    public void draw(TriMesh t) {
        // set world matrix
        Matrix3f rotation = t.getWorldRotation();
        Vector3f translation = t.getWorldTranslation();
        float scale = t.getWorldScale();
        float[] modelToWorld =
            {
                scale * rotation.get(0, 0),
                scale * rotation.get(1, 0),
                scale * rotation.get(2, 0),
                0.0f,
                scale * rotation.get(0, 1),
                scale * rotation.get(1, 1),
                scale * rotation.get(2, 1),
                0.0f,
                scale * rotation.get(0, 2),
                scale * rotation.get(1, 2),
                scale * rotation.get(2, 2),
                0.0f,
                translation.x,
                translation.y,
                translation.z,
                1.0f };

        GL.glMatrixMode(GL.GL_MODELVIEW);
        GL.glPushMatrix();
        worldBuffer.clear();
        worldBuffer.put(modelToWorld);
        worldBuffer.flip();
        GL.glMultMatrixf(worldBuffer);

        // render the object

        GL.glVertexPointer(3, 0, t.getVerticeAsFloatBuffer());
        GL.glEnableClientState(GL.GL_VERTEX_ARRAY);

        FloatBuffer afNormals = t.getNormalAsFloatBuffer();
        if (afNormals != null) {
            GL.glEnableClientState(GL.GL_NORMAL_ARRAY);
            GL.glNormalPointer(0, afNormals);
        } else {
            GL.glDisableClientState(GL.GL_NORMAL_ARRAY);
        }

        FloatBuffer afColors = t.getColorAsFloatBuffer();
        if (afColors != null) {
            GL.glEnableClientState(GL.GL_COLOR_ARRAY);
            GL.glColorPointer(4, 0, afColors);
        } else {
            GL.glDisableClientState(GL.GL_COLOR_ARRAY);
        }

        FloatBuffer afTextures = t.getTextureAsFloatBuffer();
        if (afTextures != null) {
            GL.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
            GL.glTexCoordPointer(2, 0, afTextures);
        } else {
            GL.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY);
        }

        GL.glDrawElements(GL.GL_TRIANGLES, t.getIndexAsBuffer());

        GL.glMatrixMode(GL.GL_MODELVIEW);
        GL.glPopMatrix();
    }

Interresting …

you made a call

GL.glVertexPointer(3, 0, t.getVerticeAsFloatBuffer());
GL.glEnableClientState(GL.GL_VERTEX_ARRAY);

…i thought the glEnableClientState should be called
before glVertexPointer…

thx,
Jens

The only order that is important is that the states are enabled before the call to glDrawElements

Simple Question:

GL.glVertexPointer(3, 0, t.getVerticeAsFloatBuffer());

You are drawing Triangles ?

  • Jens

yes

GL.glDrawElements(GL.GL_TRIANGLES, t.getIndexAsBuffer());

Ok,
my problem was that had some parameter problems, mostly because the Syntax differs a bit from the Orginal GL Method. So i called it with some other parameters.

Fazit: We need some better Docu, but this should be allready in work, if i understood princec and Matzon right ?

  • Jens