I've got a JOGL application in which I am rendering 1 million textures (all the same texture) and 1 million lines between those textures. Basically it's a ball-and-stick graph.

I am storing the vertices in a vertex array on the card and referencing them via index arrays, which are also stored on the card. Each pass through the draw loop I am basically doing this:

gl.glBindBuffer(GL.GL_ARRAY_BUFFER, <buffer id>);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, <buffer id>);
gl.glDrawElements(GL.GL_POINTS, <size>, GL.GL_UNSIGNED_INT, 0);

gl.glBindBuffer(GL.GL_ARRAY_BUFFER, <buffer id>);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, <buffer id>);
gl.glDrawElements(GL.GL_LINES, <size>, GL.GL_UNSIGNED_INT, 0);

I noticed that the JOGL library is pegging one of my CPU cores. Every frame, the run method internal to the library is taking quite long. I'm not sure why this is happening since I have called setHardwareAccelerated(true) on the GLCapabilities used to create my canvas.

What's more interesting is that I changed it to setHardwareAccelerated(false) and there was no impact on the performance at all.

Is it possible that my code is not using hardware rendering even when it is set to true? Is there any way to check?


As suggested, I have tested breaking my calls up into smaller chunks. I have tried using glDrawRangeElements and respecting the limits that it requests. All of these simply resulted in the same pegged CPU usage and worse framerates.

I have also narrowed the problem down to a simpler example where I just render 4 million textures (no lines). The draw loop then just doing this:


<... Camera and transform related code ...>


<... Bind texture ...>

gl.glBindBuffer(GL.GL_ARRAY_BUFFER, <buffer id>);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, <buffer id>);
gl.glDrawElements(GL.GL_POINTS, <size>, GL.GL_UNSIGNED_INT, 0);



Where the first buffer contains 12 million floats (the x,y,z coords of the 4 million textures) and the second (element) buffer contains 4 million integers. In this simple example it is simply the integers 0 through 3999999.

I really want to know what is being done in software that is pegging my CPU, and how I can make it stop (if I can).

My buffers are generated by the following code:

gl.glBindBuffer(GL.GL_ARRAY_BUFFER, <buffer id>);
gl.glBufferData(GL.GL_ARRAY_BUFFER, <size>
    * BufferUtil.SIZEOF_FLOAT, <buffer>,

gl.glVertexAttribPointer(0, 3, GL.GL_FLOAT, false, 0, 0);


gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, <buffer id>);
    <size> * BufferUtil.SIZEOF_INT,
    <buffer>, GL.GL_STATIC_DRAW);


Here is my initialization code:

gl.setSwapInterval(1); //Also tried 0


gl.glPointParameterfv(GL.GL_POINT_SIZE_MIN, MIN_POINT_SIZE, 0);
gl.glPointParameterfv(GL.GL_POINT_SIZE_MAX, MAX_POINT_SIZE, 0);


gl.glClearColor(clearColor.getX(), clearColor.getY(),
        clearColor.getZ(), 0.0f);

Also, I'm not sure if this helps or not, but when I drag the entire graph off the screen, the FPS shoots back up and the CPU usage falls to 0%. This seems obvious and intuitive to me, but I thought that might give a hint to someone else.

  • \$\begingroup\$ Try turning off VSync and limiting your framerate manually to see if it's the routine that waits for the VSync on your monitor which does peg a core at 100% (a problem in both DirectX and OpenGL). \$\endgroup\$ Commented Mar 15, 2012 at 12:14
  • \$\begingroup\$ I tried turning off VSync too - assuming I'm doing it correctly - and still no change. I called gl.setSwapInterval(0) to turn it off. \$\endgroup\$
    – Luke
    Commented Mar 15, 2012 at 12:45
  • \$\begingroup\$ have you tried profiling to see exactly which call is using the most CPU time? \$\endgroup\$ Commented Mar 15, 2012 at 13:00
  • \$\begingroup\$ See my response to @MrCranky, but yes. It's com.sun.opengl.util.FPSAnimator$1.run() and javax.media.opengl.GLCanvas$DisplayOnEventDispatchThreadAction.run() (each almost exactly 50%) \$\endgroup\$
    – Luke
    Commented Mar 15, 2012 at 13:07
  • \$\begingroup\$ Let me amend that statement, that was before I changed the default profiler settings. More specifically, the two functions are javax.media.opengl.Threading.invokeOnOpenGLThread() and com.sun.opengl.impl.windows.WindowsOnscreenGLDrawable.swapBuffers() - I'm looking into those deeper right now. \$\endgroup\$
    – Luke
    Commented Mar 15, 2012 at 19:28

3 Answers 3


If you weren't using hardware acceleration at all you would be getting less than 1 fps. Unless that applies we can discount that possibility.

My hunch is that your vertex pipeline has dropped back to software emulation. You're saying that you've got one million lines and you're calling glDrawElements with GL_UNSIGNED_INT, which - depending on your hardware - may be overflowing your hardware maximum for number of vertexes per draw call and max vertex index.

Note that glDrawElements itself doesn't specify these maximums, but you can bet that they do exist in hardware.

To resolve this you can try splitting up your glDrawElements calls so that your indexes fit in unsigned shorts. Yes, it's more draw calls, but it will fit within hardware limits for everything and won't choke your vertex pipeline.

  • \$\begingroup\$ I pulled the values of GL_MAX_ELEMENTS_VERTICES and GL_MAX_ELEMENTS_INDICES, and they are both 1,048,576. This would seem to agree with your hunch. Are you saying that I need to break my vertex array buffers (GL.GL_ARRAY_BUFFER) up into smaller chunks or just my index array buffers(GL.GL_ELEMENT_ARRAY_BUFFER)? If I had to break both up into smaller chunks, that would be nightmarish for my current application... \$\endgroup\$
    – Luke
    Commented Mar 12, 2012 at 19:49
  • \$\begingroup\$ You could get away with the indexes and just set new array pointers with different offsets. \$\endgroup\$ Commented Mar 12, 2012 at 20:35
  • \$\begingroup\$ Note that MAX_ELEMENTS_VERTICES and MAX_ELEMENTS_INDICES are for glDraw<b>Range</b>Elements. It has nothing to do with glDrawElements. \$\endgroup\$ Commented Mar 13, 2012 at 3:39
  • 1
    \$\begingroup\$ Yup, I've noted it, and have also noted that both glDrawElements and glDrawRangeElements predate hardware T&L. Bottom line is that if a limit exists in hardware then the spec can say that the moon is a blue cube for all it matters, and this is a limit that exists in hardware. \$\endgroup\$ Commented Mar 13, 2012 at 11:09
  • \$\begingroup\$ I don't think this is it. I've narrowed the problem down to a simpler test case, which is simply rendering 4 million textures. When I draw them all in one glDrawElements call I get 19 FPS. When I split it up into chunks of 750k indexed by an int, it drops to 17 FPS, when I split it up into chunks of 32k indexed by a short it drops to 11 FPS. I also tried 32k chunks indexed by an int, it's still 11 FPS. I believe the limits are for internal performance optimization of glDrawRangeElements only and performance reverts to that of glDrawElements if the conditions are not met. \$\endgroup\$
    – Luke
    Commented Mar 13, 2012 at 14:56

My bet would be that your performance is not bound by GPU operations, and that hardware acceleration makes no difference because the amount of time spent doing the GPU work is dwarfed by 'something else'; be that marshalling on the driver side, something in the OpenGL libs itself, or even possibly your own code. The trouble is, figuring out what overhead is getting you isn't straightforward unless you know what's going on under the hood.

That diagnosis would be consistent with your reply to mh01's answer; increasing the number of draw calls to render the same primitives adds yet more overhead, while keeping the number of primitives drawn the same. Have you tried making the task less complex to see if there's one element of the problem that causes a massive drop in performance? E.g. does disabling textures but rendering the same amount of primitives work fine?

My advice would be to dig out a sampling profiler (something that breaks into your process every X microseconds and grabs the callstack), and see which module it's spending all this time in.

  • \$\begingroup\$ I ran jvisualvm and determined that the slowdown was not in my user code. The functions using all the CPU are com.sun.opengl.util.FPSAnimator$1.run() and javax.media.opengl.GLCanvas$DisplayOnEventDispatchThreadAction.run(). I have stripped the code down. I tried disabling textures, depth testing, alpha testing, etc. Nothing seemed to help performance at all. Further, there shouldn't be much that needs marshalled. If I understand correctly my code should simply tell the card the address and number of points to draw. It's not like it's sending the whole buffer each frame. \$\endgroup\$
    – Luke
    Commented Mar 15, 2012 at 12:20
  • \$\begingroup\$ The deeper functions called by those 2 functions are actually: javax.media.opengl.Threading.invokeOnOpenGLThread() and com.sun.opengl.impl.windows.WindowsOnscreenGLDrawable.swapBuffers() \$\endgroup\$
    – Luke
    Commented Mar 15, 2012 at 19:29
  • \$\begingroup\$ Hmm, a spin-wait in swapBuffers is consistent with a heavy GPU load , so that probably rules my theory out. \$\endgroup\$
    – MrCranky
    Commented Mar 17, 2012 at 8:44

The answer is that the GPU was taking too long to render the frame and subsequent frames ended up doing a CPU intensive busy wait before moving onto the next frame.

The busy wait was occurring in: com.sun.opengl.impl.windows.WindowsOnscreenGLDrawable.swapBuffers()

The solution was 2 fold.

First, to prevent frames from backing up I changed my FPSAnimator to have scheduleAtFixedRate as false. That is:

new FPSAnimator(canvas, 30, false);

The second change was to render my entire scene into a Framebuffer Object and simply draw the Framebuffer Object to the screen each frame. Since my scene is mostly static, I was able to use this to increase the FPS while my scene is not changing. When the scene does change, I render it to the Framebuffer Object again.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .