0

I am investigating OpenGL Android deqp test suit and confused with one of the cases. Test is dEQP-GLES31.functional.vertex_attribute_binding.usage.mixed_usage.mixed_api_change_binding_point. Sources can be found here, lines of interest is 1197-1213. I have no idea, that a trick is used.

        const int maxUsedLocation   = de::max(positionLoc, colorLoc);
        const int bindingPoint1     = maxUsedLocation + 1;
        const int bindingPoint2     = maxUsedLocation + 2;
        // bind data using old api
        gl.glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
        gl.glVertexAttribPointer(bindingPoint1, 4, GL_FLOAT, GL_FALSE, (glw::GLsizei)(2 * sizeof(tcu::Vec4)), (const deUint8*)DE_NULL);
        gl.glVertexAttribPointer(bindingPoint2, 4, GL_FLOAT, GL_FALSE, (glw::GLsizei)(2 * sizeof(tcu::Vec4)), (const deUint8*)DE_NULL + sizeof(tcu::Vec4));
        // change buffer binding point with vertex_attrib_binding
        gl.glVertexAttribFormat(positionLoc, 4, GL_FLOAT, GL_FALSE, 0);
        gl.glVertexAttribFormat(colorLoc, 4, GL_FLOAT, GL_FALSE, 0);
        gl.glVertexAttribBinding(positionLoc, bindingPoint1);
        gl.glVertexAttribBinding(colorLoc, bindingPoint2);

First of all, bindingPoint1 and bindingPoint2 was initialized in a strange way (increment of max number vertex locations in shader). Then it was used as vertex attrib location(?) in glVertexAttribPointer. After that it used as vertex buffer binding point in glVertexAttribBinding. And finally, there are no glBindVertexBuffer call, which buffer bindingPoint1 and bindingPoint2 was bound to? I try to understand ARB_vertex_attrib_binding extension, but I still don't understand this code.

For me it seems that glVertexAttribPointer is incorrect because of incorrect vertex attrib locations and glVertexAttribBinding is incorrect too, because no vertex binding point bound to vertex buffer. Can someone explain me, that is going on here?

exbluesbreaker
  • 2,160
  • 3
  • 18
  • 30

1 Answers1

2

What you are reading is a test, used to verify that an OpenGL driver has implemented the functionality correctly. It is not meant to be an example of reasonable code. It's basically testing a corner case, one that sane code would generally never trigger.

Vertex attrib binding effectively redefined the meaning of glVertexAttribPointer, specifying that it now works by using glVertexAttribFormat/etc internally. This test is intended to verify that the driver is implementing the redefined glVertexAttribPointer correctly.

Again, you shouldn't write code that mixes the two like this. But the specification allows it, so a good tester should verify that the implementation is doing its job.

So the two calls to glVertexAttribPointer effectively do the following:

glVertexAttribFormat(bindingPoint1, ..., 0);
glBindVertexBuffer(bindingPoint1, m_buffer, 0, (glw::GLsizei)(2 * sizeof(tcu::Vec4)));
glVertexAttribBinding(bindingPoint1, bindingPoint1);

glVertexAttribFormat(bindingPoint2, ..., 0);
glBindVertexBuffer(bindingPoint2, m_buffer, sizeof(tcu::Vec4), (glw::GLsizei)(2 * sizeof(tcu::Vec4)));
glVertexAttribBinding(bindingPoint2, bindingPoint2);

So this sets up two attributes as well as two buffer bindings. But the shader never actually uses these attributes.

The later code sets up two more attributes, but this:

    gl.glVertexAttribBinding(positionLoc, bindingPoint1);
    gl.glVertexAttribBinding(colorLoc, bindingPoint2);

Means that they get the attributes get their vertex data from the previously established binding points. So the two attributes the VS actually uses get their buffer data from the buffer binding points bindingPoint1 and bindingPoint2. The other two attributes, which also get their data from the same binding points, are not used by the VS and therefore are irrelevant.

And now let me re-reemphasize that in real code, you should never do this. Pick an API style and stick with it. Or failing that, pick an API style within the same VAO.

Community
  • 1
  • 1
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982