jbhunter's picture

GameWindow FPS limits/performance versus GLControl for raycasting

I am using OpenTK to do some ray casting hoping that hardware acceleration will drasically improve my performace. I do not need to visualize so I am not worried about display quality, pixel size, etc.

I initially started a prototype with a windows form control OpenTK.GLControl. When using this I noticed that I was able to obtain approximatley 1000-1200 frames per second.

For my actual implementation I had planned to use the OpenTK.GameWindow class. I also planned to try to eliminate the need for a form/window with this, hopfully the Visible=false in the load method will do this but I have not tried it yet, thanks to Fiddler for answering someone's recent post to help me on that. I implemented a GameWindow class to open a single form with a .Net thread to do the raycasting. At first I noticed that the GameWindow.Run method takes an argument for FPS, with a maximum 200. This seemed a bit odd to me, I used 200. After some testing it apprears that I am only able to get about 60 FPS. Why is this? Should I try something different to do background rendering? What can I do to improve performance?

For more details the single mesh that I am raycasting on is about 26k facets. My GLControl and GameWindow is set to 50x50 pixels. I am calling each frame render with a dispaylist.

            GL.NewList(displayList, ListMode.Compile);
            GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
            GL.Color3(Color.Red);
            GL.Begin(BeginMode.Triangles);
            for (int i = 0; i < partMesh.mesh.Count; i++)
            {
                Vector n = partMesh.mesh[i].normal;
                GL.Normal3(VectorConvert(n));
                for (int j = 0; j < 3; j++)
                {
                    Vector v = partMesh.mesh[i].vertices[j];
                    GL.Vertex3(VectorConvert(v));
                }
            }
            GL.End();
            GL.EndList();

On each frame render I am doing:

                            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
                            GL.ClearColor(Color.SkyBlue);
                            GL.MatrixMode(MatrixMode.Modelview);
                            GL.LoadIdentity();
                            GL.CallList(displayList);

When I run under GLControl and I get 1200 FPS. I notice using Process Explorer (Great program by the way) that I have about 12% CPU usage and 60% GPU usage in my thread.

When I am in GameWindow and getting about 60 FPS I get about 2% CPU usage and 12% GPU usage. If I do not run in a .NET thread I get slightly better performance but in the noise.


Comments

Comment viewing options

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

I'm not any expert, but you could try:

protected override void OnLoad (EventArgs e)
        {
            VSync = VSyncMode.Off;
        }
the Fiddler's picture

Exactly, 60 fps means that you are synchronized to the refresh rate of the monitor, which is what you usually want.

Set VSync = VSyncMode.Off to turn this off (vsync is also known as "hard" sync, as it is handled by the drivers / gpu.)

Moreover, use GameWindow.Run() or instead of GameWindow.Run(60.0, 60.0) to turn off the "soft" frame limiter.

GameWindow is optimized to not allocate memory or cause GC during normal operation. GLControl (and WinForms in general) are not, and will allocate memory every time you e.g. move your mouse. Use GameWindow if you need reliable performance (e.g. for a game or simulation). GLControl is only meant for GUIs.

jbhunter's picture

Wow, this worked great! I changed to simply GameWindow.Run() and set VSync = VSyncMode.Off. With these two changes I went from 50 fps to about 1500 like I achieved with GLControl.

I then changed to GameWindow.Visible = false and went up to 1650 fps or so.

Two other questions that may help with performance...

1) Can I use multiple GameWindows to execute the ray casting from a .NET ThreadPool? Does this even make sense or would the GPU already be at its peak with one or two? I am executing the ray casting for each object of a 3d array, voxels. So this shouldn't be too difficult to implement for say, one thread per x/y grid. Each object would have many rays to cast.

2) For each scene/frame I check the color of a single pixel, right in the center of a viewport. Would there be a method to extract this quicker than GL.ReadPixels? I am using...

                            GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
                            Byte pixels = new Byte();
                            GL.ReadBuffer(ReadBufferMode.Front);
                            GL.ReadPixels((this.width / 2), (this.height / 2), 1, 1, PixelFormat.Blue, PixelType.UnsignedByte, ref pixels);

I am looking into using FrameBuffer as well to see if this will help speed things up even more than using the GameWindow. Thanks again for the help.

the Fiddler's picture

You can instantiate multiple GameWindows on different threads, but performance is going to be *extremely* driver dependent. Keep in mind that you only have a single GPU (usually) that is going to be shared between all OpenGL contexts. Some drivers handle this better than others, so you will have to test on your specific configuration.

Regarding GL.ReadPixels(), apparently this is well-optimized on "professional" GPUs (Quadro, FireGL and the like). On consumer GPUs, again, it depends on the drivers and the hardware. The best place to find such information would be on the developer forums and/or documentation of your specific GPU. FBOs are certainly worth a try.

This actually looks like something that would possibly be better-suited to OpenCL than OpenGL (but I do not know the details of your project.)