# An odd performance problem rendering a simple scene (less than 14k vertices) in OpenGL using two vbos with LWJGL

Problem

I have been having a strange degrading performance issue rendering a simple scene containing two "chunks" of 4x4x4 cubes each.

Video of problem

This is a screen capture showing my console output, look specifically at the FPS dropping (which is the issue).

http://assets.cognitive.io/bugconsole.swf

My machine (a mid-2009 mbp 15") is on average using something like 10% cpu, but the machine is getting very hot to touch so I believe the graphics card is working very hard.

Someone else tested this code on another machine and experienced 100% cpu usage on a quad-core AMD cpu (on one core) and the same kind of performance problem.

I can't quite figure out what's going on, multiple people have looked at this and we are not getting any smarter.

Currently there is no frustum culling or any other sort of culling. I do not think that is the problem, I should be able to render a much much higher number of vertices without experiencing problems.

I have a list of chunks (ArrayList) that is created on start, not within the render loop, that generates a vbo and all that.

In my renderer I loop through the list of chunks and for each one I bind the vbo, setup some uniform variables and such before calling glDrawArrays().

I have a version of this where I only have one vbo (but then also only one cube per vbo/glDrawArrays call, very inefficient) where everything is working fine.

Thoughts and ideas

I believe the problem is something related to either VRAM filling up or me doing something incredibly wrong.

I've tried looking at my project with OSX's OpenGL profiler application, which has given me two different results:

First I was just using glBufferData each frame to pass the data, which resulted in 90% of the gl time spent being spent on CGLFlushDrawable().

After some advice from someone on #opengl on Freenode, it was suggested I should setup the vbo once with glBufferData, and then call glMapBuffer to pass the data after that.

This results in the same performance problem but 99% of the gl time being spent on glMapBuffer().

I was hoping someone had some advice for me, I would really like to just be able to continue learning opengl instead of being stuck debugging this performance issue for weeks.

Code on GitHub

The code is available at https://github.com/flexd/Game/tree/chunkrenderer (specifically the chunkrenderer branch!, you can see that the lighting2 branch works without the same performance issue).

The main game class is Game.java which contains the main method and it's also where I setup OpenGL.

Chunk.java, Cube.java, Renderable.java and ChunkRenderer.java are also of interest. Shader.java is where the shader class lives, but I doubt that has anything to do with the issues, it's basically the same shader as before.

Thanks in advance, I hope to be able to find the issue soon :)

PS: Let me know if I am posting this in the wrong place, I don't know if there's a opengl category that's better suited for this.

• Here is a screenshot of the scene being rendered (two of these chunks). assets.cognitive.io/chunk.png I could not post this in the post above as I lack the reputation to post more than two links. :) Apr 26 '12 at 12:58

When I was tracking down graphics performance issues early in the development of my game, I utilized a program called dDEBugger. From their site:

gDEBugger is an advanced OpenGL and OpenCL Debugger, Profiler and Memory Analyzer. gDEBugger does what no other tool can - lets you trace application activity on top of the OpenGL and OpenCL APIs and see what is happening within the system implementation.

Not only is this a great tool, but it's free! Additionally, you can utilize CPU side profilers to asses memory usage and which calls are taking the most time. The built in for NetBeans is OK and there are some good ones for Eclipse too.

Beyond that I suspect your issue is with memory usage. I only looked at your code briefly, but I did notice things like generating a few new FloatBuffers per chunk per frame. Also, in Chunk.java after the initialization you're filling up VertexData, mapping driverSideBuffer then clearing VertexData then filling driverSideBuffer with an empty VertexData:

driverSideBuffer = glMapBuffer(GL_ARRAY_BUFFER, GL15.GL_WRITE_ONLY, driverSideBuffer);
vertexData.clear();
driverSideBuffer.clear();
driverSideBuffer.put(vertexData);
glUnmapBuffer(GL_ARRAY_BUFFER);


Now, since your drawing seems to be working, that's likely not a big issue, but it shows me that there are likely more subtle issues if this one has been missed.

• gDEBugger sadly does not (or at least didn't last week) run on OSX Lion yet, I do have OSX's built-in opengl profiler that at least allows me to see what calls are being made and what takes a lot of time. the glMapBuffer bit was something I added yesterday to try to fix this mess, I have noticed no performance gains or drops adding that vs. just having the glBufferData bit inside the if (!initialized) statement. I've been having this problem for nearly a week, I've stepped through the Java side with a debugger and I haven't noticed anything wrong. Others have also taken a look. Apr 26 '12 at 14:46
• Did the code ever perform well? If you have access to a Windows machine, you should try it out on there.
– House
Apr 26 '12 at 14:55
• This code (using multiple vbos) never worked well, someone else tried it on a Windows machine and it was using 100% cpu on a single core of a quad-core amd processor. But he has a much better graphics card so I assume the processor was the bottleneck there, instead of the card here. The single vbo cube rendering (one cube in the vbo per glDrawArrays call) in the lighting2 branch works without this problem, but is slow because of the huge amount of glDrawArrays() calls. Apr 26 '12 at 14:57
• You should package a jar file and put it on your github downloads. I'll give it a try on my machine with gDEBugger.
– House
Apr 26 '12 at 16:40
• Hmm, well something in the way you've compiled the jar file or how you have the game set to run, means I can't attach a debugger to it. It's like it's launching, then launching a sub-process that actually runs the game. So breaking the debugger does not actually stop code execution on the game and I get no stats in gDEBugger since it has attached its self to this "dummy" process. Sorry! Glad to hear you got it working anyway. Hope you found my answer somewhat useful.
– House
Apr 27 '12 at 15:27

I believe I've just fixed it myself!

I added a boolean dirty = true; to the Chunk class, with the default value of true, because I set the position initially.

I wrapped the entire code that generated the vertexData ByteBuffer in a if (dirty) {}

So that it only regenerates the vertexData buffer when the chunk has changed.

It's now rendering at 150+ fps.

• As was suggested Byte56, I suspect you were just thrashing the bandwidth to your GPU. From the sounds of it you were uploading as fast as possible, so no wonder it was 100%. You can do this with many things, not just buffers. Apr 27 '12 at 9:19
• Yeah that seems to have been the problem. It would still be cool to see what Byte56 can see with gDEBugger. Apr 27 '12 at 10:01