Hi,
I'm a senior developer and have been working with OpenGL for almost two decades now.
I recently bought a laptop with AMD A9 9420 (integrated Radeon R530).
The installed driver on Windows 10 64 bit is: Adrenalin Edition 18.8.1 (18.30.01.01 RC5), atiglpxx.dll version 8.14.01.6564
I've noticed a problem with OpenGL 4.3 feature ARB_vertex_attrib_binding (VAB), when used with a single vertex array object (VAO).
In my minimal example I'm drawing with two programs configuring the VAB for each draw, but reusing the same VAO and the problem manifests itself as driver not honoring the set VAB config, specifically glVertexAttribBinding and/or glBindVertexBuffer.
Initial VAO/VAB config is done like this:
glBindVertexArray(d->vao); // VAO has an element array bound for drawing single quad
// shaderA uses 2 vertex attrib inputs (VA idx 1, 2 - vert and col) coming from vbo0 at vertex binding index 0
// shaderB uses 2 vertex attrib inputs (VA idx 1, 2 - vert and col) coming from vbo1 at vertex binding index 1
// shaderB uses 1 vertex array input (VA idx 0 - integer index) coming from vbo2 at vertex binding index 2
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
// this vert input and VAB index is used with shaderB
glVertexAttribIFormat(0, 4, GL_UNSIGNED_BYTE, 0); // VA 0 is integer vbo3
glVertexAttribBinding(0, 2); // it goes to VAB index 2
glBindVertexBuffer(2, d->vbos[2], 0, 4); // and it sources from vbo2
// these inputs are used with both shaderA and shaderB
glVertexAttribFormat(1, 4, GL_FLOAT, 0, 0); // VA 1 is float vec4 vert
glVertexAttribFormat(2, 4, GL_FLOAT, 0, 16); // VA 2 is float vec4 col
glVertexAttribBinding(1, 0); // it goes to VAB index 0. initially
glVertexAttribBinding(2, 0); // it goes to VAB index 0. initially
glBindVertexBuffer(0, d->vbos[0], 0, 32); // and it sources from vbo0 (for shaderA, and from vbo1 for shaderB)
// we will render with shaderA first, which doesn't need vertex attrib 0
glDisableVertexAttribArray(0);
Frame drawing looks like this:
glClear(GL_COLOR_BUFFER_BIT);
// both shaders use the same VAO and it's already bound
// shaderA uses 2 vertex attrib inputs (VA idx 1, 2 - vert and col) coming from vbo0 at vertex binding index 0
glDisableVertexAttribArray(0);
glVertexAttribBinding(1, 0);
glVertexAttribBinding(2, 0);
glBindVertexBuffer(0, d->vbos[0], 0, 32);
glUseProgram(d->progA);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
// shaderB uses 2 vertex attrib inputs (VA idx 1, 2 - vert and col) coming from vbo1 at vertex binding index 1
// shaderB uses 1 vertex array input (VA idx 0 - integer index) coming from vbo2 at vertex binding index 2
glEnableVertexAttribArray(0);
glVertexAttribBinding(0, 2);
glVertexAttribBinding(1, 1);
glVertexAttribBinding(2, 1);
glBindVertexBuffer(2, d->vbos[2], 0, 4);
glBindVertexBuffer(1, d->vbos[1], 0, 32);
glUseProgram(d->progB);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
This should draw two colored quads, but on my card it draws only one (the second draw in this minimal example, but in real life example it draws everything, but with wrong buffer bound in the later calls).
I have managed to do a workaround in this minimal example by forcing VAO rebind before setting up VAB before every draw.
If adding those, two quads are drawn as expected
glBindVertexArray(0);
glBindVertexArray(d->vao);
// ... set up vertex attribs and VAB and do draw call 1
glBindVertexArray(0);
glBindVertexArray(d->vao);
// ... set up vertex attribs and VAB and do draw call 2
It seems to me that after issuing a draw call, VAO state gets somehow reused for the following draw calls, not honoring VAB calls which configure vertex attrib binding indexes.
I have the full minimal example (with binaries, and all needed to build on Windows) attached here:
Hi Tom,
Thanks for reporting the problem.
Our OpenGL developer forum is better place to post/report this OpenGL related issue. I'm moving it there.
Also, I've whitelisted you, so now you will be able to post anywhere in our DevGurus community.
Thanks.
Thanks, I will post here in the future.
Hello,
So the expected output is as follow?
Yes, that would be the correct output.
On my laptop I only see the green quad
I also tried using two VAOs and then it works correctly on my laptop too....
I will try to test it on another AMD GPU and will post the results here.
Actually, the first frame is correct as expected, then the following frames have problems: the colored quad is drawn at the same location as the green quad(see the following picture), then the green quad would overwrite the colored the quad in the same frame. Explicitly unbinding then binding the VAO (your workaround)would force the driver to validate some attributes fields. We will continue working to fix it and will keep you updated, thanks.
Thanks for taking the time with this. I also saw a frame or two being drawn correctly in my main project, but was not able to stop it there using AMD GPU PerfStudio. However behavior was the same as you described (using wrong vbo in later calls).
Besides explicitly unbinding I also tried using two VAOs for this minimal example, configured once for every shader and then in frame drawing only setting (buffers and) offsets using glBindVertexBuffer (after binding correct VAO). This also works correctly.
My friend tested minimal example from here on:
GL version=4.5.13467 Core Profile Context FireGL 21.19.384.0 (renderer=AMD FirePro W5130M)
and it behaves the same as on my Radeon - not drawing correctly by default, drawing correctly with VAO unbind workaround.
He also tried it on Intel: GL version=4.4.0 - Build 21.20.16.4627 (renderer=Intel(R) HD Graphics 530) and it worked as expected.
I tried this on a lot of NV hardware supporting vertex_attrib_binding and all worked as expected.
We will investigate internally first and keep you updated if any progress, thanks.