fdncred's picture

[Solved] VBO slow. Why?

Any ideas why my VBOs are so slow? I'm getting about 1.1 FPS but with DisplayLists it's about 60. Here's most of the code.

struct Vbo
{
    public int VertexBufferID;
    public Vector3[] Vertices;
    public int ColorBufferID;
    public Color4[] Colors;
    public int NumElements;
}
 
 public void LoadVBO(string sFileName)
{
    // Create a VBO structure [1/26/2011 9:11:05]
    vbo = new Vbo();
    // Load the image [1/26/2011 9:11:15]
    LoadHeightMapITMakeTriangles(sFileName, 1.0f, 1.0f);
 
    if (vbo.Vertices == null) return;
    if (vbo.Colors == null) return;
    int buffersize;
 
    // Create the VBO... finally [1/26/2011 11:42:21]
    if (vbo.Colors != null)
    {
        // Generate the Array Buffer Id [1/26/2011 11:43:57]
        GL.GenBuffers(1, out vbo.ColorBufferID);
 
        // Bind current context to Array Buffer Id [1/26/2011 11:44:10]
        GL.BindBuffer(BufferTarget.ArrayBuffer, vbo.ColorBufferID);
 
        // Send data to buffer [1/26/2011 11:44:41]
        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vbo.Colors.Length * Color4SizeInBytes), vbo.Colors, BufferUsageHint.StaticDraw);
 
        // Validate that the buffer is the correct size [1/26/2011 11:46:46]
        GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out buffersize);
        if (vbo.Colors.Length * Color4SizeInBytes != buffersize)
            throw new ApplicationException("Color array not uploaded correctly");
 
        // Clear the buffer Binding [1/26/2011 11:48:03]
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
    }
 
    if (vbo.Vertices != null)
    {
        GL.GenBuffers(1, out vbo.VertexBufferID);
        GL.BindBuffer(BufferTarget.ArrayBuffer, vbo.VertexBufferID);
        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vbo.Vertices.Length * Vector3.SizeInBytes), vbo.Vertices, BufferUsageHint.StaticDraw);
        GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out buffersize);
        if (vbo.Vertices.Length * Vector3.SizeInBytes != buffersize)
            throw new ApplicationException("Vertex array not uploaded correctly");
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
    }
}
 
void DrawVBO()
{
    // Push current Array Buffer state so we can restore it later
    GL.PushClientAttrib(ClientAttribMask.ClientVertexArrayBit);
 
    if (vbo.VertexBufferID == 0) return;
    // Color Array Buffer (Colors not used when lighting is enabled)
    if (vbo.ColorBufferID != 0)
    {
        // Enable the client state so it will use this array buffer pointer
        GL.EnableClientState(ArrayCap.ColorArray);
 
        // Bind to the Array Buffer ID
        GL.BindBuffer(BufferTarget.ArrayBuffer, vbo.ColorBufferID);
 
        // Set the Pointer to the current bound array describing how the data is stored
        GL.ColorPointer(4, ColorPointerType.Float, Color4SizeInBytes, IntPtr.Zero);
    }
 
    // Vertex Array Buffer
    if (vbo.VertexBufferID != 0)
    {
        // Enable the client state so it will use this array buffer pointer
        GL.EnableClientState(ArrayCap.VertexArray);
 
        // Bind to the Array Buffer ID
        GL.BindBuffer(BufferTarget.ArrayBuffer, vbo.VertexBufferID);
 
        // Set the Pointer to the current bound array describing how the data is stored
        GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, IntPtr.Zero);
    }
 
    GL.DrawArrays(BeginMode.Triangles, 0, vbo.NumElements);
    // Restore the state
    GL.PopClientAttrib();
}
 
protected override void OnRenderFrame(FrameEventArgs e)
{
    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
    GL.MatrixMode(MatrixMode.Modelview);
    GL.LoadIdentity();
 
    GL.LoadMatrix(ref cameraMatrix);
    DoMouseRotate();
 
    DrawCenterPoint();
 
    DrawPlane();
 
    DrawAxis();
 
    /*lock (matrixLock)
    {
        ThisTransformation.get_Renamed(matrix);
    }
    GL.PushMatrix();
    GL.MultMatrix(matrix);
 
    switch (terrainRenderStyle)
    {
        case BeginMode.Lines:
            GL.CallList(lineDspLst);
            break;
        case BeginMode.Points:
            GL.CallList(pointDspLst);
             break;
        case BeginMode.Quads:
            GL.CallList(quadDspLst);
            break;
        case BeginMode.Polygon:
            GL.CallList(polyDspList);
            break;
        default:
         break;
    }
 
 
    GL.PopMatrix();
    GL.Flush();*/
 
    // Update FPS and diagnostics on window title every 1 second
    if (stopwatch.ElapsedMilliseconds > 1000.0)
    {
        try
        {
            //this.Title = "FPS: " + (1.0 / e.Time).ToString() + " | GLVertex3 calls: " + diagVertices.ToString() + " | Right-click for help";
            this.Title = String.Format("FPS: {0:0.00} | GLVertex3 calls {1} | Right-click for help", (1.0/e.Time), diagVertices.ToString());
            stopwatch.Reset();
            stopwatch.Start();
        }
        catch (System.Exception ex)
        {
            //Console.WriteLine("{0}",ex.Message);
            stopwatch.Reset();
            stopwatch.Start();
        }
    }
 
    DrawVBO();
 
    this.SwapBuffers();
}

When I run VS2010 Profiler it shows that all the time is in GL.DrawArrays(BeginMode.Triangles, 0, vbo.NumElements). Very strange.

[SOLVED]
The fix was rebooting. I guess my Nvidia Quadro FX700 drivers got whacked somehow. Not sure.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
pigu66's picture

Hello
In my experience, it is not a good idea to use multiple buffer objects to store draw array data. I suggest you to store all data in the same buffer, using BufferSubData OGL function to put vertex, normal, color or tex coords in the GL memory after creating the whole buffer with BufferData function (see OpenGL programming guide od OpenGL superbible for examples). Then use VertexPointer (or ColorPointer, etc.) to set data offset inside buffer before calling DrawArrays.
My test application performs very fast object drawin using texturing (decal mode) instead of vertex color (this could be another cause of slow rendering ...). I stored vertex, normals and texture coords in this way.
Good luck ...

fdncred's picture

I may try BUfferSubData even though my solution was rebooting to reset the video card. Thanks for the help anyway.