2
votes

using OpenGL 4.5 and an NVidia card, I have noticed that when switching transform feedback objects via glBindTransformFeedback(), the associated array buffer bindings established with glBindBufferBase(), do not get changed.

Have a look at the following snippets:

Let there be a pair of transform feedback and vertex buffer objects:

GLuint tfo1, vbo1;
glGenTransformFeedbacks(1, &tfo1);
glGenBuffers(1, &vbo1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glBufferData(GL_ARRAY_BUFFER, 123 * sizeof(float), nullptr, GL_DYNAMIC_DRAW);

glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo1);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo1);

Query result using glGetIntegerv():

GL_TRANSFORM_FEEDBACK_BINDING: 1
GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: 1

Let there be another pair of such objects:

GLuint tfo2, vbo2;
glGenTransformFeedbacks(1, &tfo2);
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glBufferData(GL_ARRAY_BUFFER, 123 * sizeof(float), nullptr, GL_DYNAMIC_DRAW);

glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo2);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo2);

Query result using glGetIntegerv():

GL_TRANSFORM_FEEDBACK_BINDING: 2
GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: 2

And now comes the issue: After having created the second pair, binding the previous transform buffer object tfo1...

glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo1);

...leads to the following query result:

GL_TRANSFORM_FEEDBACK_BINDING: 1
GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: 2   <--- WHY NOT 1?

The bound TFO is now tfo1 but the array buffer binding has not been changed. It looks like as if the buffer binding is not part of the TFO state but can that be? Isn't managing buffer bindings the main reason TFOs exist?

1
"Isn't managing buffer bindings the main reason TFOs exist?" No; the main reason feedback objects exist is to be able to pause and resume feedback operations. Granted, they do contain buffer object bindings. But you should show us the actual code where you query this stuff. Because I strongly suspect you're not querying the buffer correctly. - Nicol Bolas
A testcase for transform feedback source/target buffer selection link - matthias

1 Answers

2
votes

According to the OpenGL 4.5 core profile specification, both the generic GL_TRANSFORM_FEEDBACK_BUFFER_BINDING (which is to be queried with glGetIntegerv as well as the indexed bindings (to be queried with glGetIntegeri_v) are part of the transform feedback object state. Section 13.2.1 "Transform Feedback Objects" states (emphasis mine)

A transform feedback object is created by binding a name returned by GenTransformFeedbacks with the command void BindTransformFeedback( enum target, uint id ); The resulting transform feedback object is a new state vector, comprising all the state and with the same initial values listed in table 23.48.

with table 23.48 containing both:

TRANSFORM_FEEDBACK_BUFFER_BINDING | Z+   | GetIntegerv   | 0 | Buffer object bound to generic bind point for transform feedback 
TRANSFORM_FEEDBACK_BUFFER_BINDING |n x Z+| GetIntegeri_v | 0 | Buffer object bound to each transform feedback attribute stream
[...]

So, in your example, switching back to tfo1 also should restore the generic transform buffer feedback binding back to vbo1. I tried your example. On an AMD implementation (Windows 7, Firepro 15.201.2401 drivers), it is behaving as the spec says. However, with NVidia (Linux, 370.28), I got the same result you are describing. What is funny is that even Nvidia's own version of transfrom feedback objects from GL_NV_transform_feedback2 uses similar language, and explicitely defines the generic binding as part as the transform feedback object state. So I'd say that you just hit some Nvidia bug.