Transform Feedback draws nothing

Started by mrdlink, March 06, 2018, 20:33:23

Previous topic - Next topic

mrdlink

Hi,
I just digged into transform feedback feature with OpenGL 3.3. But somehow the transform feedback shader is not processed correctly. I tried several tutorials, but they always use a very different setup, so that didn't help much. This is the main tutorial I followed: http://prideout.net/blog/?tag=opengl-transform-feedback

This is how I draw everything:
val tfShader = TFShaderProgram("assets/tf.vert")

val maxTriangles = 10_000_000
var tb = 0

fun setup() {
    val vao = glGenVertexArrays()
    glBindVertexArray(vao)

    val vertices = MemoryUtil.memAllocFloat(maxTriangles * 8*3)
    for(i in 1..maxTriangles)
        vertices.put(floatArrayOf(
                0f,0f, 1f,1f,1f,1f, 0f,0f,
                0.5f,0f, 1f,1f,1f,1f, 1f,0f,
                0f,0.5f, 1f,1f,1f,1f, 0f,1f ))
    vertices.flip()

    val vbo = glGenBuffers()
    glBindBuffer(GL_ARRAY_BUFFER, vbo)
    glBufferData(GL_ARRAY_BUFFER, vertices, GL_DYNAMIC_DRAW)

    glEnableVertexAttribArray(0)
    glEnableVertexAttribArray(1)
    glEnableVertexAttribArray(2)
    glVertexAttribPointer(0, 2, GL_FLOAT, false, 8 * 4, 0)
    glVertexAttribPointer(1, 4, GL_FLOAT, false, 8 * 4, 2 * 4)
    glVertexAttribPointer(2, 2, GL_FLOAT, false, 8 * 4, 6 * 4)

    tb = glGenTransformFeedbacks()
    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tb)
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo)
}

fun render() {
    glClear(GL_COLOR_BUFFER_BIT)

    val queryObject = glGenQueries()

    glEnable(GL_RASTERIZER_DISCARD)
    glUseProgram(tfShader.program)
            glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tb)
            glBeginTransformFeedback(GL_POINTS)
                glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, queryObject)
                glDrawArrays(GL_POINTS, 0, 3 * maxTriangles)
                //glDrawTransformFeedback(GL_POINTS, tb)
                glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)
                println("Points drawn: " + glGetQueryObjecti(queryObject, GL_QUERY_RESULT))
            glEndTransformFeedback()
            glFlush()
    glUseProgram(0)
    glDisable(GL_RASTERIZER_DISCARD)

    glUseProgram(shaderProgram.program)
    glDrawArrays(GL_TRIANGLES, 0, 3)
    //glDrawTransformFeedback(GL_TRIANGLES, tb)
}

private fun loadFile(file: String) = String(Files.readAllBytes(File(file).toPath()))

class TFShaderProgram(vertFile: String) {

    val program: Int

    init {
        val vert = loadFile(vertFile)

        val vertexShader = glCreateShader(GL_VERTEX_SHADER)
        glShaderSource(vertexShader, vert)

        glCompileShader(vertexShader)
        val vStatus = glGetShaderi(vertexShader, GL_COMPILE_STATUS)
        if (vStatus != GL_TRUE) {
            throw RuntimeException(glGetShaderInfoLog(vertexShader))
        }

        program = glCreateProgram()
        glAttachShader(program, vertexShader)

        val varyings = arrayOf("outValue")
        glTransformFeedbackVaryings(program, varyings, GL_INTERLEAVED_ATTRIBS )

        glLinkProgram(program)
        val pStatus = glGetProgrami(program, GL_LINK_STATUS)
        if (pStatus != GL_TRUE) {
            throw RuntimeException(glGetProgramInfoLog(program))
        }

        glDeleteShader(vertexShader)
    }
}


The query prints "Points drawn: 0". So the transform shader isn't processed properly. But all the input and output variables are properly setup:
#version 330

layout(location = 0) in vec2 inValue;

out vec2 outValue;

void main() {
    outValue = inValue + vec2(0.00025f, 0f);
}

KaiHH

You are using the same GL buffer object for sourcing vertex data for the draw call and for writing transform feedback data into.
I am pretty sure you are getting GL errors for trying that. Did you check GL11.glGetError() or better, use a debug context and install a debug callback?

mrdlink

Ok, I bound a seperate buffer for the output vertices. I did get an error INVALID_OPERATION for the first glDrawArrays. Now everything is processed. But can't you define a single VBO as an input and output buffer for transform feedback. Or do you just copy the the feedback buffer into the VBO for drawing?
I mean, isn't this transform feedback could be used for? Updating VBOs just on the GPU through shaders?
For example, if you wanted to make a particle system that is just updated on the GPU with millions of paticles; copying all that data for every transformation is very expensive. Why not just write it into the same same VBO then?

KaiHH

Quote from: mrdlink on March 06, 2018, 22:08:02
Ok, I bound a seperate buffer for the output vertices. I did get an error INVALID_OPERATION for the first glDrawArrays. Now everything is processed. But can't you define a single VBO as an input and output buffer for transform feedback. Or do you just copy the the feedback buffer into the VBO for drawing?
I mean, isn't this transform feedback could be used for? Updating VBOs just on the GPU through shaders?
For example, if you wanted to make a particle system that is just updated on the GPU with millions of paticles; copying all that data for every transformation is very expensive. Why not just write it into the same same VBO then?
If you had actually read that tutorial you were supposedly following, you would have realized that this is exactly what they are doing there. They ping-pong between two buffer objects, one time used for sourcing vertex attributes for a draw call (i.e. VBO) and another time as transform feedback target. No copying involved. Just a reassignment of the role of each buffer object.

mrdlink

I feel stupid now. That wasn't the actual tutorial I meant XD. But now that I took a closer look, it makes a whole lot of sense.