Poor Performance with glVertexAttribPointer

classic Classic list List threaded Threaded
21 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Poor Performance with glVertexAttribPointer

bgroenks96
I'm trying to use glVertexAttribPointer to get both the position and texture coordinates from a single VBO into my vertex shader.  The vertex shader is basic and doesn't do much other than transform and output.

The test scene is a few non-textured quads, a non-textured background quad, and several hundred textured quads.

With the following code and no textured quads I get a solid ~2200 fps

                        gl.glEnableVertexAttribArray(0);
                        gl.glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);

                        gl.glMultiDrawArrays(buffObj.drawFunc.getGLCommand(), buffObj.vertIndices, 0, buffObj.vertNum, 0, buffObj.objCount);

                        // disable arrays
                        gl.glBindBuffer(GL_ARRAY_BUFFER, 0);
                        gl.glDisableVertexAttribArray(0);

Note: the VBOs for the non-textured quads are allocated to only hold position coordinates.

Adding the tex coord vertex attribute drops it down to <100 fps:

                        gl.glEnableVertexAttribArray(0);
                        gl.glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
                        if(texBound && texEnabled) {
                                gl.glEnableVertexAttribArray(1);
                                gl.glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 2 * buffObj.nverts * Buffers.SIZEOF_FLOAT);
                        }

                        gl.glMultiDrawArrays(buffObj.drawFunc.getGLCommand(), buffObj.vertIndices, 0, buffObj.vertNum, 0, buffObj.objCount);

                        // disable arrays
                        gl.glBindBuffer(GL_ARRAY_BUFFER, 0);
                        gl.glDisableVertexAttribArray(0);
                        if(texBound && texEnableD)
                            gl.glDisableVertexAttribArray(1);

The load shouldn't be a problem.  The same scene ran at ~2000 fps using fixed function glVertexPointer and glTexCoordPointer with the same VBO setup.

Am I doing something wrong?  What kind of state calls or optimizations should I consider with setting vertex attribute pointers?
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

gouessej
Administrator
Personally, I would do that:

                        if(texBound && texEnabled) {
                                gl.glEnableVertexAttribArray(1);
                                gl.glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 2 * buffObj.nverts * Buffers.SIZEOF_FLOAT);
                        } else {
                                gl.glEnableVertexAttribArray(0);
                                gl.glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
                        }

//same code ...

                        if(texBound && texEnableD)
                              gl.glDisableVertexAttribArray(1);
                        else
                              gl.glDisableVertexAttribArray(0);



Why not looking at the source code of JMonkeyEngine 3 shader based JOGL renderer? I think I use these calls appropriately.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

bgroenks96
If I do that, the textured quads don't get drawn because the vertex position attribute doesn't get set.

I think the performance bottleneck is coming in large part from my fragment shader's lighting calculations, which I haven't tested with the large number of quads since it was much less complex.

The odd thing still, however, is that the FPS start dropping each second while it's rendering.  That seems to me like an indication of some kind of memory leak or misused pointer.  Do you have any idea why that might happen?
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

bgroenks96
In reply to this post by gouessej
I'm looking at:
http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/jogl/com/jme3/renderer/jogl/JoglRenderer.java?spec=svn9910&r=9910

How many times does that glVertexAttribPointer get called?  Is it called for just position?  If so, how do you get texture coordinate data to the vertex shader?
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

gouessej
Administrator
It's called once but you should download the whole source code of the engine and look where the method containing this OpenGL call is called.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

jmaasing
In reply to this post by bgroenks96
bgroenks96 wrote
The odd thing still, however, is that the FPS start dropping each second while it's rendering.  That seems to me like an indication of some kind of memory leak or misused pointer.  Do you have any idea why that might happen?
By concidence I am hunting a similar problem in my game-project. I had FPS degradation, over a  few minutes it dropped very much. Turned out that I forgot to delete the vertex attribute buffers, eating GPU memory. Make sure every genBuffer you call is matched by a deleteBuffer. So yes, leaks somewhere can cause that type of FPS degradation.
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

bgroenks96
This post was updated on .
How many buffers are you creating?

With mine, I'm only generating three and then just reusing them.  Could that still be an issue?

I think I might have solved the issue for now by replacing glMapBuffer and glUnmapBuffer with glBufferSubData.  I don't really know why that all of a sudden changed...

How much performance difference should there be between glBufferSubData and writing everything to a local buffer and using glBufferData on draw?
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

gouessej
Administrator
I'm not completely surprised, maybe there is a leak in your driver that affects glMapBuffer & glUnmapBuffer, glBufferSubData doesn't do any memory allocation. In my humble opinion, you shouldn't rely on inconsistent speedups obtained by using glBufferData to invalidate the data store and resend the data, rather use glBufferSubData even to update the content of the whole buffer.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

jmaasing
In reply to this post by bgroenks96
bgroenks96 wrote
How many buffers are you creating?

With mine, I'm only generating three and then just reusing them.  Could that still be an issue?
...
Not recommended to do what I'm doing : I create between 10-30 (very small) buffers each frame at 60 FPS. Unless I delete them correctly FPS drops after a few seconds  I guess this will vary greatly between drivers.
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

bgroenks96
In reply to this post by gouessej
gouessej wrote
I'm not completely surprised, maybe there is a leak in your driver that affects glMapBuffer & glUnmapBuffer, glBufferSubData doesn't do any memory allocation. In my humble opinion, you shouldn't rely on inconsistent speedups obtained by using glBufferData to invalidate the data store and resend the data, rather use glBufferSubData even to update the content of the whole buffer.
So you mean write individual object data to a local FloatBuffer then upload everything at once on the draw call via glBufferSubData?
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

gouessej
Administrator
Yes this is a possibility, pass the buffer once to glBufferData and call glBufferSubData to update the content. We do something similar in several engines. The only drawback is that you have to handle direct NIO buffers carefully to avoid running out of native memory.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

bgroenks96
Ok.  If you store a single instance of the direct NIO Buffer, subsequent put calls should just overwrite data in existing memory correct?  That seems like the most efficient way to handle an object that you update frequently with new vertex data.
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

gouessej
Administrator
If you modify the data in the direct NIO buffer you created by yourself without passing them to OpenGL, the changes won't be reflected. Keep in mind that the direct NIO buffer on the CPU and the data store on the GPU are 2 different things.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

bgroenks96
gouessej wrote
If you modify the data in the direct NIO buffer you created by yourself without passing them to OpenGL, the changes won't be reflected. Keep in mind that the direct NIO buffer on the CPU and the data store on the GPU are 2 different things.
Yes I know.  Sorry, I should have clarified what I meant.

I mean allocate a single instance of the NIO Buffer -> write changes to it -> on draw call, upload via glBufferSubData -> repeat

I was referring to the memory being used by the NIO Buffer being kept on the client side.  The one that you modify with updates and then write to VRAM once all updates have been made.
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

Sven Gothel
Administrator
In reply to this post by gouessej
On 01/14/2014 08:23 PM, gouessej [via jogamp] wrote:
> Yes this is a possibility, pass the buffer once to glBufferData and call
> glBufferSubData to update the content.

Reason is, glBufferData recreates the GPU memory 'slot' !

~Sven


signature.asc (911 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

bgroenks96
Sven Gothel wrote
Reason is, glBufferData recreates the GPU memory 'slot' !
So that's what causes the memory leak?

When is it appropriate then to make the glBufferData(..., ..., null, ...) call?  Isn't it supposed to tell the driver to discard the previously held buffer data?
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

Sven Gothel
Administrator
On 01/14/2014 10:50 PM, bgroenks96 [via jogamp] wrote:
>     Sven Gothel wrote
>     Reason is, glBufferData recreates the GPU memory 'slot' !
>
> So that's what causes the memory leak?
>
> When is it appropriate then to make the glBufferData(..., ..., null, ...)
> call?  Isn't it supposed to tell the driver to discard the previously held
> buffer data?

yes, sure - recreate == dispose+create

Haven't said anything about a leak.
But recreation takes more time for memory management
where glBufferSubData simply updates the content.
Thought this discussion was about performance ..

~Sven



signature.asc (911 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

bgroenks96
It is/was.

Leaks can cause performance degradation right?

It's the only thing I can think of to explain the FPS drop over time.
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

Sven Gothel
Administrator
On 01/15/2014 01:59 AM, bgroenks96 [via jogamp] wrote:
> It is/was.
>
> Leaks can cause performance degradation right?
There is no simple yes/no answer to this question, sorry.

>
> It's the only thing I can think of to explain the FPS drop over time.

Since I currently work on
  Bug 942 https://jogamp.org/bugzilla/show_bug.cgi?id=942
  Bug 943 https://jogamp.org/bugzilla/show_bug.cgi?id=943

it may help if you can produce a small unit test demonstrating some
use of BufferData etc .. in a shader based environment (core profile).

We can use this one for some measurements .. leak detections.

If MapBuffer is involved and issued multiple times,
especially w/ multiple BufferData (new mapped buffers)
there are chances for a leak - working on it.

~Sven



signature.asc (911 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Poor Performance with glVertexAttribPointer

bgroenks96
I'll see what I can do.  Do you want me to submit said unit test on Bugzilla?
12