2

Transform feedback works the first frame, but not after that.

This is particle system based on "GLSL Cookbook" example, though I'm converting it to OpenGL 3.3.

My program set up:

I have two sets of vertex array buffers for each attribute (2 for position, 2 for velocity, 2 for startTime). 2 VAOs, the first corresponding to the first set up buffers, and the second VAO corresponding the second set of buffers. The VAO sets up the vertex attributes to the for the corresponding buffers.

There are two shader programs, the first performs the transform feedback, the second one renders.

On each frame the transform feedback is performed first with the transform feedback shader program and a VAO, then the render shader with the other VAO renders. On each successive frame the VAOs are swapped.

If I use a query with GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN I can see that only the first time all the primitives are written, after that the primitives written value is 0. Also I can visually see the first pass worked by seeing points flicker on screen (flicker between the start location of the points and the location they were transformed in the first frame).

I am seeing this problem on Mac OS X only (it works perfectly on Linux and Windows). I know Mac is a little behind with some OpenGL functionality but I cannot find anything that indicates that would be an issue in this case.

Also I checked for OpenGL errors while rendering and there were none.

Before linking the transform feedback shader:

const char * outputNames[] = { "position", "velocity", "startTime" };
glTransformFeedbackVaryings(
    m_transformShader.programId(),
    3, 
    outputNames,
    GL_SEPARATE_ATTRIBS);

Here is the render function code I am using:

// ************** Transform feedback pass

m_transformShader.bind();

glEnable(GL_RASTERIZER_DISCARD);

glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, positionBuffer[drawBuf]);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, velocityBuffer[drawBuf]);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 2, startTimeBuffer[drawBuf]);

m_vao[1-m_drawBuf].bind();

glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, numParticles);
glEndTransformFeedback();

glDisable(GL_RASTERIZER_DISCARD);

// ************** Render pass

m_renderShader.bind();

glClear( GL_COLOR_BUFFER_BIT );
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_texture);
m_renderShader.setUniformValue("texSampler", 0);

m_vao[m_drawBuf].bind();
glDrawArrays(GL_POINTS, 0, numParticles);
m_vao[m_drawBuf].release();

m_renderShader.release();

m_drawBuf = 1 - m_drawBuf;

Vertex Shader for transform feedback shader (m_transformShader):

#version 330

layout (location = 0) in vec3 vertexPosition;
layout (location = 1) in vec3 vertexVelocity;
layout (location = 2) in float vertexStartTime;
layout (location = 3) in vec3 vertexInitialVelocity;

out vec3 position;
out vec3 velocity;
out float startTime;

uniform float time;
uniform float H;

uniform vec3 accel;
uniform float lifespan;

void main()
{
    position = vertexPosition;
    velocity = vertexVelocity;
    startTime = vertexStartTime;

    if ( time >= startTime )
    {
        float age = time - startTime;
        if ( age > lifespan )
        {
            position = vec3(0.0);
            velocity = vertexInitialVelocity;
            startTime = time;
        }
        else
        {
            position += velocity * H;
            velocity += accel * H;
        }
    }
}

Rendering vertex shader:

#version 330

layout (location = 0) in vec3 vPosition;
layout (location = 2) in float vStartTime;

out float alpha;

uniform mat4 MVP;
uniform float time;
uniform float lifespan;

void main()
{
    gl_PointSize = 10.0;
    float age = time - vStartTime;
    alpha = 1.0 - age / lifespan;
    gl_Position = MVP * vec4(vPosition, 1.0);
}

I am using OpenGL 3.3 context.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
leyota
  • 37
  • 4
  • How do you know it even works? I do not see shaders or GL API calls that use the results anywhere. Often if it works the first frame and fails to work on subsequent frames you have done something silly like forget to unmap the transform feedback buffer (assuming you're reading it on the CPU). – Andon M. Coleman Oct 17 '13 at 05:04
  • As I said in my post, I tested on Windows and Linux and it works perfectly. I am not reading back to the CPU, this is a particle system where the results are rendered as GL_POINTS and continuously fed back to the feedback system. I did not post the whole setup (shaders, VBOs, VAOs, etc...) for brevity. Could be something silly as I haven't used transform feedback much, and I'm attempting to convert a gl 4.0 example to 3.3. But it works on both linux and windows and not on mac, so I'm not sure what's going on... – leyota Oct 17 '13 at 05:39
  • That does not always mean a lot, believe it or not undefined behavior may behave identically on platform A and B (particularly if they use a GPU from the same vendor), but not C. You only realize you are invoking undefined behavior when you discover it behaves differently on C :) Whereas Linux and Windows drivers are usually implemented by the Individual Hardware Vendor, on OS X, Apple implements (most of) the driver, so you see a *LOT* of inconsistencies between Linux/Windows and OS X. It is equally likely that it is an Apple bug, but without your shader code there is no way to say. – Andon M. Coleman Oct 17 '13 at 05:50
  • Also, I doubt you are actually using an OpenGL 3.3 context as you claim. Apple only implements OpenGL 2.1 and 3.2 core in OS X 10.7/8. Which also means your shaders should start with `#version 150 core` on this platform. – Andon M. Coleman Oct 17 '13 at 06:02
  • Updated with the vertex shaders. – leyota Oct 17 '13 at 06:10
  • I've upgraded to Mac OS X 10.9, which is supposed to support up to OpenGL 4, so having a 3.2 context shouldn't be a problem. – leyota Oct 23 '13 at 08:12
  • Did you figure it out? You also still need to ensure you're actually getting a 3.2 context (you can print out the GL_VERSION string to check.) – James Bedford May 30 '14 at 23:32
  • Did you ever get a solution to this? Encountering something almost identical myself – Godwhacker May 24 '20 at 00:13

0 Answers0