static void draw() { static const GLenum bo_modes[] = { GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY, GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY, GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, GL_DYNAMIC_COPY, }; int i; bool pass = true; glEnable(GL_RASTERIZER_DISCARD); for (i = 0; i < ARRAY_SIZE(bo_modes); i++) { static GLuint xfb_buf; float *readback; /* Make a new TFB output buffer with the chosen usage * mode. Note, from ARB_vertex_buffer_object: * * "The specified usage value does not constrain * the actual usage pattern of the data store." */ glGenBuffers(1, &xfb_buf); glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buf); glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float), NULL, bo_modes[i]); piglit_BindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buf); /* Do the draw call. Here's where we segfaulted before. */ piglit_BeginTransformFeedback(GL_POINTS); glDrawArrays(GL_POINTS, 0, 1); piglit_EndTransformFeedback(); /* Test the output, just to be sure. */ readback = glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); if (readback[0] != 1.0) { fprintf(stderr, "Readback found %f, expected 1.0\n", readback[0]); pass = false; } glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); glDeleteBuffers(1, &xfb_buf); } piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
enum piglit_result piglit_display(void) { GLint input_index = glGetAttribLocation(prog, "input_uint"); GLuint *readback; GLuint buffer[BUFFER_SIZE]; GLuint expected[BUFFER_SIZE]; int i; GLboolean pass = GL_TRUE; piglit_UseProgram(prog); glBindBuffer(GL_ARRAY_BUFFER, 0); glVertexAttribIPointer(input_index, 1, GL_UNSIGNED_INT, sizeof(GLuint), &verts); glEnableVertexAttribArray(input_index); pass = piglit_check_gl_error(0) && pass; glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buf); memset(buffer, 0xffffffff, sizeof(buffer)); glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(buffer), buffer, GL_STREAM_READ); piglit_BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buf, additional_offset, sizeof(buffer) - additional_offset); piglit_BeginTransformFeedback(GL_POINTS); glDrawArrays(GL_POINTS, 0, 4); piglit_EndTransformFeedback(); pass = piglit_check_gl_error(0) && pass; readback = glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); pass = piglit_check_gl_error(0) && pass; /* Figure out expected output */ memset(expected, 0xffffffff, sizeof(expected)); for (i = 0; i < EXPECTED_NUM_OUTPUTS; ++i) { expected[i + additional_offset / 4] = 0x00010203 + 0x04040404 * i; } /* Check output */ for (i = 0; i < BUFFER_SIZE; ++i) { if (expected[i] != readback[i]) { printf("readback[%u]: %u, expected: %u\n", i, readback[i], expected[i]); pass = GL_FALSE; } } piglit_present_results(); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
enum piglit_result piglit_display(void) { GLboolean pass = GL_TRUE; static const float verts[] = { 10, 10, 10, 20, 20, 20, 20, 10 }; static const float v3[] = {0.55, 0.66, 0.77}; static const float frontcolor[] = {1.0, 0.9, 0.8, 0.7}; static const float v2[] = {0.2, 0.7}; static const float texcoord1[] = {0.6, 0.0, 0.1, 0.6}; glClear(GL_COLOR_BUFFER_BIT); /* Render into TFBO. */ glLoadIdentity(); piglit_UseProgram(prog); glEnable(GL_RASTERIZER_DISCARD); piglit_BeginTransformFeedback(GL_TRIANGLES); glVertexPointer(2, GL_FLOAT, 0, verts); glDrawArrays(GL_QUADS, 0, 4); piglit_EndTransformFeedback(); glDisable(GL_RASTERIZER_DISCARD); assert(glGetError() == 0); pass = probe_buffer(buf[0], 0, 3, v3) && pass; pass = probe_buffer(buf[1], 1, 4, frontcolor) && pass; pass = probe_buffer(buf[2], 2, 2, v2) && pass; pass = probe_buffer(buf[3], 3, 4, texcoord1) && pass; assert(glGetError() == 0); piglit_present_results(); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
static GLboolean test(int bind_size, int num_varyings, int num_primitives, int mode_index) { float initial_xfb_buf[XFB_BUFFER_SIZE]; float vertex_data[MAX_VERTICES]; int i, j; int vertices_per_prim = mode_vertices_per_prim[mode_index]; int expected_primitives_written = MIN2(num_primitives, bind_size / num_varyings / vertices_per_prim); int expected_vertices_written = expected_primitives_written * vertices_per_prim; GLuint query_result; GLboolean pass = GL_TRUE; float expected_xfb_results[XFB_BUFFER_SIZE]; float *readback; printf("size=%d, num_varyings=%d, num_primitives=%d, mode=%s: ", bind_size, num_varyings, num_primitives, mode_names[mode_index]); /* Setup program and initial buffer contents */ piglit_UseProgram(progs[num_varyings - 1]); for (i = 0; i < MAX_VERTICES; ++i) vertex_data[i] = i; glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, sizeof(float), &vertex_data); glEnableVertexAttribArray(0); for (i = 0; i < XFB_BUFFER_SIZE; ++i) initial_xfb_buf[i] = 0.0; glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buf); glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(initial_xfb_buf), initial_xfb_buf, GL_STREAM_READ); piglit_BindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buf, 0, sizeof(float) * bind_size); /* Start queries and XFB */ glBeginQuery(GL_PRIMITIVES_GENERATED, query_prims_generated); glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query_prims_written); piglit_BeginTransformFeedback(modes[mode_index]); /* Draw */ glDrawArrays(modes[mode_index], 0, num_primitives * vertices_per_prim); /* Stop XFB and check queries */ piglit_EndTransformFeedback(); glEndQuery(GL_PRIMITIVES_GENERATED); glGetQueryObjectuiv(query_prims_generated, GL_QUERY_RESULT, &query_result); if (query_result != num_primitives) { printf("\n Expected %u primitives generated, got %u\n", (unsigned) num_primitives, query_result); pass = GL_FALSE; } glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); glGetQueryObjectuiv(query_prims_written, GL_QUERY_RESULT, &query_result); if (query_result != expected_primitives_written) { printf("\n Expected %u primitives written, got %u", (unsigned) expected_primitives_written, query_result); pass = GL_FALSE; } /* Check transform feedback buffer */ memcpy(expected_xfb_results, initial_xfb_buf, sizeof(initial_xfb_buf)); for (i = 0; i < expected_vertices_written; ++i) { for (j = 0; j < num_varyings; ++j) { expected_xfb_results[i * num_varyings + j] = 100.0 * (j + 1) + i; } } readback = glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY); for (i = 0; i < XFB_BUFFER_SIZE; ++i) { if (expected_xfb_results[i] != readback[i]) { printf("\n Expected buf[%i] = %f, got %f", i, expected_xfb_results[i], readback[i]); pass = GL_FALSE; } } if (pass) printf("PASS\n"); else printf(" FAIL\n"); return pass; }
enum piglit_result piglit_display(void) { GLboolean pass = GL_TRUE; GLuint q; float *ptr; unsigned i, qresult; static const float verts[] = { 10, 10, 10, 20, 20, 20, 20, 10 }; static const float expected[] = { -0.687500, -0.375000, 0.000000, 1.000000, -0.687500, 0.250000, 0.000000, 1.000000, -0.375000, -0.375000, 0.000000, 1.000000, -0.687500, 0.250000, 0.000000, 1.000000, -0.375000, 0.250000, 0.000000, 1.000000, -0.375000, -0.375000, 0.000000, 1.000000, }; static const unsigned indices[] = { 0, 1, 3, 1, 2, 3 }; static const float clearcolor[] = {0.2, 0.2, 0.2}; static const float white[] = {1, 1, 1}; static const float red[] = {1, 0, 0}; glClear(GL_COLOR_BUFFER_BIT); /* Set up queries. */ switch (test) { case PRIMGEN: glGenQueries(1, &q); glBeginQuery(GL_PRIMITIVES_GENERATED_EXT, q); break; case PRIMWRITTEN: glGenQueries(1, &q); glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT, q); break; } /* Render into TFBO. */ glLoadIdentity(); piglit_UseProgram(prog); if (discard) glEnable(GL_RASTERIZER_DISCARD_EXT); piglit_BeginTransformFeedback(GL_TRIANGLES); glBindBuffer(GL_ARRAY_BUFFER, 0); glVertexPointer(2, GL_FLOAT, 0, verts); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices); piglit_EndTransformFeedback(); if (discard) glDisable(GL_RASTERIZER_DISCARD_EXT); assert(glGetError() == 0); switch (test) { case READBACK: puts("Testing readback."); ptr = glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, GL_READ_ONLY); for (i = 0; i < BUF_FLOATS; i++) { float value = i >= offset && i < offset+range ? expected[i-offset] : DEFAULT_VALUE; //printf("%f, ", ptr[i]); if (fabs(ptr[i] - value) > 0.01) { printf("Buffer[%i]: %f, Expected: %f\n", i, ptr[i], value); pass = GL_FALSE; } } glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER_EXT); break; case RENDER: puts("Testing rendering."); piglit_UseProgram(prog_passthrough); glBindBuffer(GL_ARRAY_BUFFER, buf); glVertexPointer(4, GL_FLOAT, 0, (void*)(intptr_t)(offset * sizeof(float))); glDrawArrays(GL_TRIANGLES, 0, range == MAX_RANGE ? 6 : 3); pass = piglit_probe_pixel_rgb(33, 18, range == MAX_RANGE ? red : clearcolor) && pass; pass = piglit_probe_pixel_rgb(28, 12, red) && pass; break; case PRIMGEN: puts("Testing a primitives-generated query."); glEndQuery(GL_PRIMITIVES_GENERATED_EXT); glGetQueryObjectuiv(q, GL_QUERY_RESULT, &qresult); { int expected = 2; /* RASTERIZER_DISCARD should not affect this. */ if (qresult != expected) { printf("Primitives generated: %i, Expected: %i\n", qresult, expected); pass = GL_FALSE; } } break; case PRIMWRITTEN: puts("Testing a primitives-written query."); glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT); glGetQueryObjectuiv(q, GL_QUERY_RESULT, &qresult); { int expected = range == MAX_RANGE ? 2 : 1; if (qresult != expected) { printf("Primitives written: %i, Expected: %i\n", qresult, expected); pass = GL_FALSE; } } break; default: piglit_report_result(PIGLIT_SKIP); } pass = piglit_probe_pixel_rgb(5, 5, clearcolor) && pass; pass = piglit_probe_pixel_rgb(15, 15, discard ? clearcolor : white) && pass; assert(glGetError() == 0); piglit_present_results(); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }