// Compile with: // c++ -std=c++11 transform_feedback.cc $(pkg-config --cflags --libs sdl2 gl) #define GL_GLEXT_PROTOTYPES 1 #include #include #include #include namespace { constexpr const char * program_1_vertex_shader_source = R"delimiter(#version 330 out ivec3 a; void main() { a = ivec3(0, 0, 0); } )delimiter"; constexpr const char * program_2_vertex_shader_source = R"delimiter(#version 330 out float id; void main() { id = float(gl_VertexID); // As a workaround, you can write a dummy gl_Position here. } )delimiter"; constexpr const char * program_2_geometry_shader_source = R"delimiter(#version 330 layout(points) in; in float id[]; layout(points, max_vertices = 1) out; out float a; out vec3 b; out float c; void main() { // If id[0] was replaced with a constant expression, // then the bug does not happen. a = id[0]; b = vec3(1,2,3); c = 4; EmitVertex(); } )delimiter"; } int main() { if (SDL_Init(SDL_INIT_VIDEO) < 0) assert(false); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_Window * const window = SDL_CreateWindow( "", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_OPENGL); assert(window); const SDL_GLContext context = SDL_GL_CreateContext(window); assert(context); const GLuint program_1_vertex_shader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(program_1_vertex_shader, 1, &program_1_vertex_shader_source, NULL); glCompileShader(program_1_vertex_shader); const GLuint program_1_program = glCreateProgram(); glAttachShader(program_1_program, program_1_vertex_shader); const char * const program_1_varyings = "a"; glTransformFeedbackVaryings(program_1_program, 1, &program_1_varyings, GL_INTERLEAVED_ATTRIBS); glLinkProgram(program_1_program); const GLuint program_2_vertex_shader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(program_2_vertex_shader, 1, &program_2_vertex_shader_source, NULL); glCompileShader(program_2_vertex_shader); const GLuint program_2_program = glCreateProgram(); glAttachShader(program_2_program, program_2_vertex_shader); const GLuint program_2_geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); glShaderSource(program_2_geometry_shader, 1, &program_2_geometry_shader_source, NULL); glCompileShader(program_2_geometry_shader); glAttachShader(program_2_program, program_2_geometry_shader); const char * const program_2_varyings[] = {"a", "b", "c"}; glTransformFeedbackVaryings(program_2_program, 3, program_2_varyings, GL_INTERLEAVED_ATTRIBS); glLinkProgram(program_2_program); // Neither shader program takes any vertex attributes. GLuint vertex_array; glGenVertexArrays(1, &vertex_array); glBindVertexArray(vertex_array); // Create a buffer to receive transform feedback results. GLuint program_2_buffer; glGenBuffers(1, &program_2_buffer); glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, program_2_buffer); glBufferStorage(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(GLfloat) * 5, NULL, 0); glEnable(GL_RASTERIZER_DISCARD); // First draw // Use a shader that has transform feedback varyings set. glUseProgram(program_1_program); glDrawArrays(GL_POINTS, 0, 1); // Second draw // Use a different shader, with multiple interleaved transform // feedback attributes, collecting the results. glUseProgram(program_2_program); glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, program_2_buffer, 0, sizeof(GLfloat) * 5); glBeginTransformFeedback(GL_POINTS); glDrawArrays(GL_POINTS, 0, 1); glEndTransformFeedback(); // Print the data produced with transform feedback. // The output should be "0 1 2 3 4". Instead I see "0 1 2 4 0". glBindBuffer(GL_ARRAY_BUFFER, program_2_buffer); GLfloat v[5]; glGetBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(v), v); for (const auto f: v) std::cout << f << " "; std::cout << "\n"; }