PDA

View Full Version : Transform Feedback is not using the Vertexshader



glRed
10-12-2010, 08:23 AM
Hi guys,

I need to use Transform Feedback in order to speed up a certain rendering process. I have a good amount of OpenGL experience and I think I understand how to use Transform Feedback. I'm just missing a detail here and looking for someone to review my code.

Not sure if this is really an advanced topic though. I have read all the other topics on transform feedback on this forum.

I set up a sample project to test certain things. I will later apply it to my (much more complex) scenario.

Here is my initialization section:



// setup shader, create program
...

// bind input variables
glBindAttribLocation(m_vertexExcludeProgram, 0, "in_Vertex");
glBindAttribLocation(m_vertexExcludeProgram, 3, "in_Color");


// specify the set of vertex attributes recorded in transform feedback mode
const char * outputVaryings[] = {"out_Position", out_Color"};

glTransformFeedbackVaryings(m_vertexExcludeProgram , 2, &outputVaryings[0], GL_INTERLEAVED_ATTRIBS);

// link
glLinkProgram(m_vertexExcludeProgram);

// gives me '2' -> correct
int numAttribs;
glGetProgramiv(m_vertexExcludeProgram, GL_ACTIVE_ATTRIBUTES, &numAttribs);

// I don't get the locations of the output variables. Is that normal?
GLint locationVertex = glGetAttribLocation(m_vertexExcludeProgram, "in_Vertex"); // 0
GLint locationColor = glGetAttribLocation(m_vertexExcludeProgram, "in_Color"); // 3

GLint locationPosition = glGetAttribLocation(m_vertexExcludeProgram, "out_Position"); // -1
GLint locationColorO = glGetAttribLocation(m_vertexExcludeProgram, "out_Color"); // -1



First thing I noticed is, that I cannot get the indices of the output variables.
After that i perform the transform feedback once:



glUseProgram(m_vertexExcludeProgram);

unsigned int numPrimitivesWritten = 0;



// bind current vertexbuffer for rendering
int numEntities = vbuffer->getSize() / vbuffer->getVertexFormat()->getStride();

vbuffer->apply();



// bind the transform feedback buffer glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfBufferHandle);


// render
glBeginTransformFeedback(GL_TRIANGLES);

// No rasterisation will be performed
glEnable(GL_RASTERIZER_DISCARD);
glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRIT TEN, query);

glDrawArrays(GL_QUADS, 0, numEntities);
glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTE N);

glDisable(GL_RASTERIZER_DISCARD);

glEndTransformFeedback();


// Query the number of primitives written in the transform buffer.

glGetQueryObjectuiv(query, GL_QUERY_RESULT, &numPrimitivesWritten);

glUseProgram(0);


This should be pretty standard. One thing is mysterious though. The original vertexbuffer contains 24 vertices, while numPrimitivesWritten tells me it recorded 8.

And here is my simple test vertexshader:


in vec4 in_Vertex;
in vec4 in_Color;

out vec4 out_Position;
out vec4 out_Color;

void transformFeedbackTest()
{
out_Position = vec4(in_Vertex.x + 1, in_Vertex.y + 1, in_Vertex.z, 1.0);
out_Color = vec4(0.0, in_Color.x, 0.0, 1.0);
}


All I want to see is that the mesh is offset by a bit and the color has changed. Instead, nothing changes. It seems that the shader is not being applied or OpenGL can't write to my output variables and just skips the shader.

I hope someone is able to spot my mistake.

Thank you

alder
10-12-2010, 10:41 AM
24 vertices == 8 triangles.

The varying won't show up as attributes. You can query the number of varyings with glGetProgramiv + GL_TRANSFORM_FEEDBACK_VARYINGS and then check that glGetTransformFeedbackVarying returns what you'd expect.

You do have a main() in your vertex shader which calls transformFeedbackTest(), right? It probably wouldn't link otherwise..

glRed
10-13-2010, 12:47 AM
Ok, it is recording triangles. That makes sense.

Alright --- I checked the varyings (out) and the input variables:



glGetProgramiv(m_vertexExcludeProgram, GL_ACTIVE_ATTRIBUTES, &numAttribs);

for (int i = 0; i < numAttribs; i++) {
glGetActiveAttrib(m_vertexExcludeProgram, i, 100, &amp;nameLength, &amp;size, &amp;type, buffer);
}


glGetProgramiv(m_vertexExcludeProgram, GL_TRANSFORM_FEEDBACK_VARYINGS, &amp;numVaryings);

for (int i = 0; i < numVaryings; i++) {
glGetTransformFeedbackVarying(m_vertexExcludeProgr am, i, 100, &amp;nameLength, &amp;size, &amp;type, buffer);
}


Everything looks fine. The first call gives me 2 attributes, "in_Vertex" and "in_Color".

The call using GL_TRANSFORM_FEEDBACK_VARYINGS gives me 2 varyings, "out_Position" and "out_Color". Good! It does know the outputs it is supposed to write to.

Btw: I do have a mechanism that replaces the function names with "main" before compilation. This allows me to have multiple functions in one file. And yeah, it does compile fine.
If I specify a wrong output varying, I get linker errors (I tried that just to make sure).

It seems as if, for some reason, GL bypasses the vertexshader and just copies the original values into the new buffer.

Some HW info:
I'm using a GTX 285 with OpenGL 3.3 on Windows 7.

DmitryM
10-17-2010, 06:40 PM
OpenGL can't just 'bypass' your vertex shader. There is no 'default' behavior in this case.

Your TF works as you get a correct GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query result.
Make sure your destination buffer is not used as a source and that your check of the result uses the correct buffer.

glRed
10-21-2010, 04:21 AM
Ok,

I decided to reduce my code to a minimum and not using shaders at all.



I'm now drawing a triangle using a simple glBegin/glEnd.


glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformedBuffer->getHandle(), 0, 3 * vertexFormat->getStride());

glBeginTransformFeedback(GL_TRIANGLES);

// No rasterisation will be performed
glEnable(GL_RASTERIZER_DISCARD);

glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRIT TEN, query);


glBegin( GL_TRIANGLES );
glColor4f( 1.0, 0.0, 0.0, 1 );
glVertex4f( -0.5, -0.5, 0, 1 );
glColor4f( 1.0, 0.0, 0.0, 1 );
glVertex4f( 0.5, 0.5, 0, 1 );
glColor4f( 1.0, 0.0, 0.0, 1 );
glVertex4f( -0.5, 0.5, 0, 1 );
glEnd();

glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTE N);

glDisable(GL_RASTERIZER_DISCARD);

glEndTransformFeedback();

glGetQueryObjectuiv(query, GL_QUERY_RESULT, &amp;numPrimitivesWritten);


Drawing:


transformedBuffer->apply();

glDrawArrays(GL_TRIANGLES, 0, 1);


And still nothing. I have no clue why it doesn't record anything. Did I miss turning on some state?
The buffer contents of transformedBuffer are identical before and after recording (uninitialized memory).

I hope someone is able to see whats wrong here.