bartlm's picture

Poor performance

Hi there.

Im just wondering if anybody out there could have a look at my Paint method from my GLControl.
Any hint which could increase performance would be very welcome...

Here we go:

        private void glControl_Paint(object sender, PaintEventArgs e)
        {
            if (!isReady)
            {
                return;
            }
            int numQuads = 0;
            Stopwatch sw = new Stopwatch();
            sw.Start();
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
            Matrix4 mLookAt = Matrix4.LookAt(eye, target, up);
 
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref mLookAt);
 
            GL.Light(LightName.Light0, LightParameter.Ambient, LightAmbient);            
 
            for (int i = 0; i < surface.Count - 1; i++)
            {
                List<Vector3> currentArch = surface[i];
                List<Vector3> nextArch = surface[i + 1];
 
                GL.BindTexture(TextureTarget.Texture2D, texSand);
                GL.Begin(BeginMode.Quads);
                GL.Color3(Color.FromArgb(255, Color.White));
                if (currentArch.Count >= 2 && currentArch.Count >= 2)
                {
                    for (int j = 0; j < currentArch.Count - 1; j++)
                    {
                        if (j < nextArch.Count - 1)
                        {
                            GL.Normal3(surfaceNormals[i][j]);
                            GL.TexCoord2(((j % 10) * 0.1f), 0 + ((j % 10) * 0.1f));
                            GL.Vertex3(currentArch[j]);
                            GL.TexCoord2(((j % 10) * 0.1f), 0.1 + ((j % 10) * 0.1f));
                            GL.Vertex3(nextArch[j]);
                            GL.TexCoord2(0.1 + ((j % 10) * 0.1f), 0.1 + ((j % 10) * 0.1f));
                            GL.Vertex3(nextArch[j + 1]);
                            GL.TexCoord2(0.1 + ((j % 10) * 0.1f), ((j % 10) * 0.1f));
                            GL.Vertex3(currentArch[j + 1]);
                            numQuads++;
                        }
                   }
                }
 
                GL.End();
            }
 
            for (int i = 0; i < dome.Count - 1; i++)
            {
                List<Vector3> currentArch = dome[i];
                List<Vector3> nextArch = dome[i + 1];
 
                if ((i % 20) == 0)
                {
                    Vector3 lightPos = new Vector3();
                    lightPos.X = currentArch[0].X + ((currentArch[currentArch.Count - 1].X - currentArch[0].X) / 2);
                    lightPos.Y = currentArch[0].Y;
                    lightPos.Z = currentArch[currentArch.Count / 2].Z - 0.5f;
                    GL.Light(LightName.Light0, LightParameter.Diffuse, LightDiffuse);
                    GL.Light(LightName.Light0, LightParameter.Position, new Vector4(lightPos, 1));
                }
 
                GL.BindTexture(TextureTarget.Texture2D, texStone);
                GL.Begin(BeginMode.Quads);
                GL.Color3(Color.FromArgb(255, Color.White));
                if (currentArch.Count >= 2 && currentArch.Count >= 2)
                {
                    for (int j = 0; j < currentArch.Count - 1; j++)
                    {
                        if (j < nextArch.Count - 1)
                        {
                            GL.Normal3(domeNormals[i][j]);
                            GL.TexCoord2(((j % 10) * 0.1f), 0 + ((j % 10) * 0.1f));
                            GL.Vertex3(currentArch[j]);
                            GL.TexCoord2(((j % 10) * 0.1f), 0.1 + ((j % 10) * 0.1f));
                            GL.Vertex3(nextArch[j]);
                            GL.TexCoord2(0.1 + ((j % 10) * 0.1f), 0.1 + ((j % 10) * 0.1f));
                            GL.Vertex3(nextArch[j + 1]);
                            GL.TexCoord2(0.1 + ((j % 10) * 0.1f), ((j % 10) * 0.1f));
                            GL.Vertex3(currentArch[j + 1]);
                            numQuads++;
                        }
                    }
                }
                GL.End();
            }

What i have is about 10000 Quads and this results to a framerate of about 9 fps.
Graphics card is an ATI Radeon HD 2400 PRO with brand new drivers installed. This should do the job in my opinion, so the "bad guy" has to be my piece of code ;-)

Thanks in advance.

Greetings,
Markus


Comments

Comment viewing options

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

Which OS, runtime and OpenTK version is this? 9fps for 10K quads sounds pretty low.

Some simple things to test:

  • Are you getting hardware acceleration? (GL.GetString(StringName.Vendor) should not contain "Microsoft")
  • Are you using the debug version of OpenTK.dll? If so, try testing with the release version which is significantly faster.
  • Are you testing your program in debug mode? Try compiling for release and run the executable outside the IDE (this can make a large difference).
  • Are you running on Mono 2.2? For some reason, OpenTK runs very slowly on this runtime.

One last thing to keep in mind is that immediate mode (GL.Begin-End) will never be fast, especially with calculations like (j % 10) * 0.1f for every single vertex. Vertex buffer objects can easily improve performance by one or two orders of magnitude.

bartlm's picture

Thanks a lot for your help.
Im using Win Vista as OS, IDE is Visual Studio 2005 and OpenTK in version 1.0-beta-1.

  • Im getting hardware acceleration - StringName.Vendor reports ATI... as expected
  • The debug version of OpenTK was a really great hint. Using the release version boost framerate up to 40fps...

Im going to try the other stuff you told me and report back, especially using Vertex buffer sounds really cute ;-)

the Fiddler's picture

40fps is closer to the mark (still a little on the slow side but not entirely unexpected given the number of calculations, array accesses and general .Net p/invoke overhead).

The reason why debug OpenTK.dll is so slow is that it checks GL.GetError after each and every OpenGL function you make. This is invaluable when you are trying to hunt down an error but it also carries significant overhead.

In any case, VBOs should easily bring you into three-digit fps numbers.

bartlm's picture

Yeah.
VBOs really do the trick.
I dont know if my stopwatch-thing does the job of measuring time correctly, but i get framerates beyond the 1k :-D
Everything is moving smooth now.
Thanks a lot.