Created attachment 411 [details]
Stand-alone test program
When calling glDrawElements after binding a Vertex Array Object which contains bindings for both ARRAY_BUFFER and ELEMENT_ARRAY_BUFFER jogl throws a GLException with the message “element vertex_buffer_object must be enabled to call this method”. According to the OpenGL 3.2 core spec, this behavior is incorrect. A workaround is binding the ELEMENT_ARRAY_BUFFER again after binding the VAO. To reproduce:
1) Setup VAO:
// glEnableVertexAttribArray + glVertexAttribPointer …
2) Upon drawing, this throws a GLException:
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0L);
3) The expected behavior is for glDrawElements to succeed.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); // This shouldn't be necessary
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0L);
Online I found only one reference to this issue, on a forum post without replies from 2009: http://www.java-gaming.org/index.php?topic=21093.0
In the self-contained example program submitted as an attachment I call directly the native entry point for glDrawElements through reflection, thus avoiding the buffer checks which throw the exception. This way the call succeeds and behaves as expected.
I am using jogl 2.0 rc11 (javax.media.opengl implementation version 2.0-b66-20121101) with Java 7u13 64-bit on Windows 7. The GPU is the NVIDIA Quadro 1000M with drivers version 311.00.
The results of the test program are the same on an Intel HD Graphics 3000 GPU, driver version 220.127.116.1132 (Windows 7 64-bit.)
Thank you Edgar.
Yes indeed - I see that our VBO validation is wrong is using VAO (ctx >= GL3.1).
Either we have to skip VBO tracking [maybe if VAO is in use],
or would need to add full VAO/VBO tracking .. which I don't favor ofc.
Let me look at the details next week.
.. working on it now ..
Add modified version of Edgar Velazquez-Armendariz's test case for testing alternating VAO and VBO usage.
Alternating VBO/VAO usage triggers bug 692, where our VBO enable check throws an exception:
javax.media.opengl.GLException: element vertex_buffer_object must be enabled to call this method
Add tracking of VERTEX_ARRAY_BINDING, and enable allowing a bound non default VAO
to pass VBO enabled test, even if VBO is disabled.
VAO is available if: GL >= 3.0 or is having GL_ARB_vertex_array_object extension.
checkBufferObject(..) checks whether VERTEX_ARRAY_BINDING has a non default VAO bound
in case no VBO is being bound and VAO is allowed.
glBindVertexArray(int) is being tracked, i.e. on state VERTEX_ARRAY_BINDING
From what I can see, only one side of the problem has been fixed. JOGL now seems to properly understand that an element buffer has been bound when I bind a VAO that previously had such a buffer attached.
However, when I unbind the VAO (that is, when I call gl.glBindVertexArray(0)), JOGL does not seem to track that the element buffer associated with the previous VOA is now unbound, and I get the following exception when I try to call glDrawElements with an element buffer in an ordinary java.nio Buffer:
Caused by: javax.media.opengl.GLException: element vertex_buffer_object must be disabled to call this method
at haven.FastMesh.cdraw(FastMesh.java:103) <-- My program
It starts working if I just add a call to glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0) whenever I call glBindVertexArray(0), but it does not seem to me that the should be necessary.
By the way, I'm using 2.0.2, which the website currently links to as both jogamp-current and jogamp-next.
Comment 5 [seems] to be invalid:
+ * Note that VAO initialization does unbind the VBO .. since otherwise they are still bound
+ * and the CPU_SRC test will fail!<br/>
+ * The OpenGL spec does not mention that unbinding a VAO will also unbind the bound VBOs
+ * during their setup.<br/>
+ * Local tests here on NV and AMD proprietary driver resulted in <i>no ourput image</i>
+ * when not unbinding said VBOs before the CPU_SRC tests.<br/>
+ * Hence Bug 692 Comment 5 is invalid, i.e. <https://jogamp.org/bugzilla/show_bug.cgi?id=692#c5>,
+ * and we should throw an exception to give users a hint!
(In reply to comment #7)
> + * The OpenGL spec does not mention that unbinding a VAO will also
> unbind the bound VBOs
The vertex_array_object extension states that a VAO tracks all the state in tables 6.6, 6.7 and 6.8 from the OpenGL 2.1 specification, excepting only the CLIENT_ACTIVE_TEXTURE and ARRAY_BUFFER_BINDING state. Table 6.8 does however also contain ELEMENT_ARRAY_BUFFER_BINDING state.
That should imply that the OpenGL spec implies that the element array buffer should be unbound when rebinding a VAO that had no bound such state, shouldn't it?
(In reply to comment #8)
> (In reply to comment #7)
> > + * The OpenGL spec does not mention that unbinding a VAO will also
> > unbind the bound VBOs
> The vertex_array_object extension states that a VAO tracks all the state
> in tables 6.6, 6.7 and 6.8 from the OpenGL 2.1 specification, excepting
> only the CLIENT_ACTIVE_TEXTURE and ARRAY_BUFFER_BINDING state. Table 6.8
> does however also contain ELEMENT_ARRAY_BUFFER_BINDING state.
> That should imply that the OpenGL spec implies that the element array buffer
> should be unbound when rebinding a VAO that had no bound such state,
> shouldn't it?
> : http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt
> : www.opengl.org/registry/doc/glspec21.20061201.pdf
I read the 3.2 and 4.4 spec (w/ compatibility) and yes, they are _tracked_,
but it doesn't explicitly state that unbinding clears them if 'manually' bound earlier (for VAO setup).
At least I couldn't find such statement.
However, I tested the clearing, you can see this in the unit test change and GLBufferStateTracker,
but got no visible result :(
Long story short: Can you try to patch GLBufferStateTracker
(enable the clearance .. and clear the states you think which should be cleared
by unbinding a VAO .. w/ your above reference) and the unit tests init_vao().
If you got 'visible' results .. we can go from there.
Or .. if you have a better unit tests, please provide it.
Today is 2.1.2 .. release, maybe we can get this in .. if working,
otherwise .. next release.
I finally got this tested. Instead of trying to understand JOGL's build system to patch the tests, I wrote a small test program i C. You can get it at <http://www.dolda2000.com/~fredrik/tmp/vaotest.c>. It uses SDL for the window system interface.
It does seem to work quite fine for me. As you can see, I never explicitly unbind the GL_ELEMENT_ARRAY_BUFFER binding, but simply reset the VAO binding to 0. I also explicitly leave the first vertex unused in the triangle that I draw from memory, just to make sure that the element arrays are different for the VAO triangle and the client-memory triangle.
Also, this makes sense to me, seeing as how OpenGL seems to define glBindVertexArray(0) not as "unbinding" the VAO, but simply as rebinding the default VAO (named 0), which should already be tracking its own GL_ELEMENT_ARRAY_BUFFER binding as being unbound.
I'm therefore reopening the bug, if you don't bind.