[Piglit] [v4 11/11] arb_transform_feedback3: add test for re-drawing multiple streams
Topi Pohjolainen
topi.pohjolainen at intel.com
Thu Nov 14 04:20:34 PST 2013
Passes on NVIDIA (304.88 on GTX 660).
v2:
- dropped unnecessary requirement for 1.50 glsl - test
requires GL version 3.2 already
- use fragment shader in re-drawing also instead of using
deprecated vertex shader alone (gl_FrontColor)
Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
tests/all.tests | 1 +
.../spec/arb_transform_feedback3/CMakeLists.gl.txt | 1 +
.../ext_interleaved_draw_streams.c | 399 +++++++++++++++++++++
3 files changed, 401 insertions(+)
create mode 100644 tests/spec/arb_transform_feedback3/ext_interleaved_draw_streams.c
diff --git a/tests/all.tests b/tests/all.tests
index 1cc318f..7fc8870 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -2493,6 +2493,7 @@ arb_transform_feedback3['arb_transform_feedback3-set_invalid_varyings'] = PlainE
arb_transform_feedback3['arb_transform_feedback3-ext_interleaved_max_buffers_and_varyings_vs'] = PlainExecTest(['arb_transform_feedback3-ext_interleaved_max_buffers_and_varyings', '-auto', 'vs'])
arb_transform_feedback3['arb_transform_feedback3-ext_interleaved_max_buffers_and_varyings_gs'] = PlainExecTest(['arb_transform_feedback3-ext_interleaved_max_buffers_and_varyings', '-auto', 'gs'])
arb_transform_feedback3['arb_transform_feedback3-ext_interleaved_max_streams'] = PlainExecTest(['arb_transform_feedback3-ext_interleaved_max_streams', '-auto'])
+arb_transform_feedback3['arb_transform_feedback3-ext_interleaved_draw_streams'] = PlainExecTest(['arb_transform_feedback3-ext_interleaved_draw_streams', '-auto'])
arb_transform_feedback3['arb_transform_feedback3-ext_interleaved_two_bufs_vs'] = PlainExecTest(['arb_transform_feedback3-ext_interleaved_two_bufs', '-auto', 'vs'])
arb_transform_feedback3['arb_transform_feedback3-ext_interleaved_two_bufs_gs'] = PlainExecTest(['arb_transform_feedback3-ext_interleaved_two_bufs', '-auto', 'gs'])
diff --git a/tests/spec/arb_transform_feedback3/CMakeLists.gl.txt b/tests/spec/arb_transform_feedback3/CMakeLists.gl.txt
index d786f4b..9bbd024 100644
--- a/tests/spec/arb_transform_feedback3/CMakeLists.gl.txt
+++ b/tests/spec/arb_transform_feedback3/CMakeLists.gl.txt
@@ -17,5 +17,6 @@ piglit_add_executable (arb_transform_feedback3-set_invalid_varyings set_invalid_
piglit_add_executable (arb_transform_feedback3-ext_interleaved_max_buffers_and_varyings ext_interleaved_max_buffers_and_varyings.c xfb3_common.c)
piglit_add_executable (arb_transform_feedback3-ext_interleaved_max_streams ext_interleaved_max_streams.c xfb3_common.c)
piglit_add_executable (arb_transform_feedback3-ext_interleaved_two_bufs ext_interleaved_two_bufs.c)
+piglit_add_executable (arb_transform_feedback3-ext_interleaved_draw_streams ext_interleaved_draw_streams.c)
# vim: ft=cmake:
diff --git a/tests/spec/arb_transform_feedback3/ext_interleaved_draw_streams.c b/tests/spec/arb_transform_feedback3/ext_interleaved_draw_streams.c
new file mode 100644
index 0000000..7e7888f
--- /dev/null
+++ b/tests/spec/arb_transform_feedback3/ext_interleaved_draw_streams.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "piglit-util-gl-common.h"
+
+/**
+ * @file ext_interleaved_draw_streams.c
+ *
+ * Records three separate vertex streams and re-draws two of them. This test is
+ * based on the tf2-draw-auto test which draws three rectangles but records
+ * only the first and the third. Here the primitives are instead recorded into
+ * separate vertex streams (and hence into a separate buffers).
+ *
+ * The first round emits nine point primitives through the vertex stage to the
+ * geometry stage. First four are recorded in one stream, the fifth in another
+ * and finally the last four in third. The geometry program takes advantage of
+ * the builtin primitive counter (gl_PrimitiveID) when distributing the vertices
+ * into the streams.
+ * The first and the second stream represent four points with color values each.
+ * These are re-drawn as two separate rectangles and the results are checked
+ * between and after the two re-draw rounds.
+ *
+ * The rectangles represent the first quarter and the second half of the
+ * framebuffer. The fifth point is given to the second stream and does not take
+ * part in the re-drawing. The resulted framebuffer should hence have color
+ * values as depicted below:
+ *
+ * 0 +-------------------+ 2
+ * | red |
+ * 1 +-------------------+ 3
+ * | clear color |
+ * 5 +-------------------+ 7
+ * | |
+ * | blue |
+ * 6 +-------------------+ 8
+ */
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+ config.supports_gl_compat_version = 32;
+ config.supports_gl_core_version = 32;
+
+ config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static const char vstext_tf[] =
+ "#version 150\n"
+ "attribute vec2 in_pos;\n"
+ "void main() {"
+ " gl_Position = vec4(in_pos.x, in_pos.y, 0.0, 1.0);\n"
+ "}\n";
+
+/**
+ * First four point primitives are emitted in stream zero, the fifth into
+ * stream one, six to eight are skipped, and finally the last four are emitted
+ * into stream two.
+ */
+static const char gs_text[] =
+ "#version 150\n"
+ "#extension GL_ARB_gpu_shader5 : enable\n"
+ "layout(points) in;\n"
+ "layout(points, max_vertices = 1) out;\n"
+ "in int gl_PrimitiveID;\n"
+ "\n"
+ "layout(points, stream = 0) out;\n"
+ "out vec4 col_0;\n"
+ "out vec4 pos_0;\n"
+ "layout(points, stream = 1) out;\n"
+ "out vec4 col_1;\n"
+ "out vec4 pos_1;\n"
+ "layout(points, stream = 2) out;\n"
+ "out vec4 col_2;\n"
+ "out vec4 pos_2;\n"
+ "\n"
+ "void main() {\n"
+ " if (gl_PrimitiveID < 4) {\n"
+ " pos_0 = gl_in[0].gl_Position;\n"
+ " col_0 = vec4(1.0, 0.0, 0.0, 1.0);\n"
+ " EmitStreamVertex(0);\n"
+ " }\n"
+ "\n"
+ " if (gl_PrimitiveID == 4) {\n"
+ " pos_1 = gl_in[0].gl_Position;\n"
+ " col_1 = vec4(0.0, 1.0, 0.0, 1.0);\n"
+ " EmitStreamVertex(1);\n"
+ " }\n"
+ "\n"
+ " if (gl_PrimitiveID > 4) {\n"
+ " pos_2 = gl_in[0].gl_Position;\n"
+ " col_2 = vec4(0.0, 0.0, 1.0, 1.0);\n"
+ " EmitStreamVertex(2);\n"
+ " }\n"
+ "}\n";
+
+static const char vs_text_redraw[] =
+ "#version 150\n"
+ "attribute vec4 in_pos;\n"
+ "attribute vec4 in_col;\n"
+ "out vec4 color;\n"
+ "void main() {"
+ " gl_Position = in_pos;\n"
+ " color = in_col;\n"
+ "}\n";
+
+static const char fs_text_redraw[] =
+ "#version 150\n"
+ "in vec4 color;\n"
+ "void main() {\n"
+ " gl_FragColor = color;\n"
+ "}\n";
+
+/**
+ * The spec for ARB_transform_feedback3 says:
+ *
+ * If a string in <varyings> is "gl_NextBuffer", it does not identify a varying
+ * variable, but instead serves as a buffer separator value to direct subsequent
+ * varyings at the next transform feedback binding point.
+ */
+static const char *varyings[] = {
+ "col_0", "pos_0", "gl_NextBuffer",
+ "col_1", "pos_1", "gl_NextBuffer",
+ "col_2", "pos_2"
+};
+
+#define STREAM_N 3
+
+/**
+ * Single transform feedback object can track multiple vertex streams, i.e.,
+ * the individual amount of vertices emitted in each stream. Later on calling
+ * 'DrawTransformFeedbackStream()' additionally designates the stream to be
+ * replayed.
+ */
+GLuint tfb;
+static GLuint xfb[STREAM_N];
+static const unsigned tf_vertex_n[] = { 4, 1, 4 };
+
+/**
+ * Each stream tracks color (copy of 'gl_FrontColor') and position (copy of
+ * 'gl_Position') both consisting of four floats.
+ */
+#define N_FLOATS_PER_VERTEX (4 + 4)
+
+static void
+check_driver(void)
+{
+ GLint streams, comps;
+
+ piglit_require_extension("GL_ARB_transform_feedback3");
+ piglit_require_extension("GL_ARB_gpu_shader5");
+
+ glGetIntegerv(GL_MAX_VERTEX_STREAMS, &streams);
+ if (streams < STREAM_N) {
+ printf("Test requires %d(%d) vertex streams\n",
+ STREAM_N, streams);
+ piglit_report_result(PIGLIT_SKIP);
+ }
+
+ glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &comps);
+ if (comps < 4 * N_FLOATS_PER_VERTEX) {
+ printf("Test requires space for %u components per three "
+ "streams each\n", 4 * N_FLOATS_PER_VERTEX);
+ piglit_report_result(PIGLIT_SKIP);
+ }
+}
+
+static void
+build_and_setup_tf_program(void)
+{
+ GLuint prog = piglit_build_simple_program_multiple_shaders(
+ GL_VERTEX_SHADER, vstext_tf,
+ GL_GEOMETRY_SHADER, gs_text, 0);
+
+ glBindAttribLocation(prog, 0, "in_pos");
+
+ /**
+ * In the EXT style feedback gathering the varyings to be tracked need
+ * to be specified after the program is compiled but before linking.
+ *
+ * It should be noticed that when mixed mode is used, i.e., where
+ * one records multiple attributes per buffer but also uses separate
+ * buffers, the mode must be set to interleaved.
+ */
+ glTransformFeedbackVaryings(prog, ARRAY_SIZE(varyings), varyings,
+ GL_INTERLEAVED_ATTRIBS);
+
+ if (!piglit_check_gl_error(GL_NO_ERROR))
+ piglit_report_result(PIGLIT_FAIL);
+
+ glLinkProgram(prog);
+ if (!piglit_link_check_status(prog))
+ piglit_report_result(PIGLIT_FAIL);
+ if (!piglit_check_gl_error(GL_NO_ERROR))
+ piglit_report_result(PIGLIT_FAIL);
+
+ glUseProgram(prog);
+}
+
+static void
+setup_tf_bufs_and_queries(GLuint *generated_queries, GLuint *written_queries)
+{
+ unsigned i;
+
+ glGenBuffers(STREAM_N, xfb);
+ glGenQueries(STREAM_N, generated_queries);
+ glGenQueries(STREAM_N, written_queries);
+ for (i = 0; i < STREAM_N; ++i) {
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, xfb[i]);
+ glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
+ tf_vertex_n[i] * N_FLOATS_PER_VERTEX * sizeof(float),
+ NULL, GL_STREAM_READ);
+
+ glBeginQueryIndexed(GL_PRIMITIVES_GENERATED, i,
+ generated_queries[i]);
+ glBeginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, i,
+ written_queries[i]);
+ }
+}
+
+static void
+check_tf_counters(GLuint *generated_queries, GLuint *written_queries)
+{
+ unsigned i;
+
+ for (i = 0; i < STREAM_N; ++i) {
+ GLuint query_result;
+
+ glEndQueryIndexed(GL_PRIMITIVES_GENERATED, i);
+ glEndQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, i);
+
+ glGetQueryObjectuiv(generated_queries[i], GL_QUERY_RESULT,
+ &query_result);
+ if (query_result != tf_vertex_n[i]) {
+ printf("Expected %u primitives generated for stream %u,"
+ " got %u\n", tf_vertex_n[i], i, query_result);
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ glGetQueryObjectuiv(written_queries[i], GL_QUERY_RESULT,
+ &query_result);
+ if (query_result != tf_vertex_n[i]) {
+ printf("Expected %u primitives written for stream %u,"
+ " got %u\n", tf_vertex_n[i], i, query_result);
+ piglit_report_result(PIGLIT_FAIL);
+ }
+ }
+}
+
+static void
+setup_vertices(void)
+{
+ /* First quarter, one vertex to be discarded, second half */
+ static const float verts[] = {
+ -1.0f, 0.5f,
+ 1.0f, 0.5f,
+ -1.0f, 1.0f,
+ 1.0f, 1.0f,
+
+ 0.5f, 0.5f,
+
+ -1.0f, -1.0f,
+ 1.0f, -1.0f,
+ -1.0f, 0.0f,
+ 1.0f, 0.0f,
+ };
+ GLuint vao, buf;
+
+ /* Test is run under desktop OpenGL 3.2 -> use of VAOs is required */
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ glGenBuffers(1, &buf);
+ glBindBuffer(GL_ARRAY_BUFFER, buf);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
+ glEnableVertexAttribArray(0);
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+ GLuint generated_queries[STREAM_N];
+ GLuint written_queries[STREAM_N];
+
+ check_driver();
+
+ build_and_setup_tf_program();
+
+ /**
+ * The feedback object is used to store internally the number of
+ * vertices recorded. This is used internally when the streams are
+ * re-drawn.
+ */
+ glGenTransformFeedbacks(1, &tfb);
+ glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfb);
+
+ setup_tf_bufs_and_queries(generated_queries, written_queries);
+
+ if (!piglit_check_gl_error(GL_NO_ERROR))
+ piglit_report_result(PIGLIT_FAIL);
+
+ setup_vertices();
+
+ /* Draw into tfb */
+ glBeginTransformFeedback(GL_POINTS);
+ glDrawArrays(GL_POINTS, 0, 4 + 1 + 4);
+ glEndTransformFeedback();
+ glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+
+ if (!piglit_check_gl_error(GL_NO_ERROR))
+ piglit_report_result(PIGLIT_FAIL);
+
+ check_tf_counters(generated_queries, written_queries);
+}
+
+/**
+ * Draw one rectangle from feedback stream 'i' and check the first and second
+ * quarter and second half colors.
+ */
+static bool
+redraw_and_check(unsigned i, const float *quarter_1_col,
+ const float *quarter_2_col, const float *second_half_col)
+{
+ bool pass = true;
+
+ glBindBuffer(GL_ARRAY_BUFFER, xfb[i]);
+ glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE,
+ N_FLOATS_PER_VERTEX * sizeof(float),
+ (void *)(intptr_t)(4 * sizeof(float)));
+ glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE,
+ N_FLOATS_PER_VERTEX * sizeof(float), NULL);
+ glDrawTransformFeedbackStream(GL_TRIANGLE_STRIP, tfb, i);
+
+ if (!piglit_check_gl_error(GL_NO_ERROR))
+ piglit_report_result(PIGLIT_FAIL);
+
+ pass = piglit_probe_pixel_rgba(piglit_width / 2, 7 * piglit_height / 8,
+ quarter_1_col) && pass;
+ pass = piglit_probe_pixel_rgba(piglit_width / 2, 5 * piglit_height / 8,
+ quarter_2_col) && pass;
+ pass = piglit_probe_pixel_rgba(piglit_width / 2, 3 * piglit_height / 8,
+ second_half_col) && pass;
+
+ return pass;
+}
+
+enum piglit_result
+piglit_display(void)
+{
+ bool pass = true;
+ GLuint prog;
+ static const float red[] = {1.0, 0.0, 0.0, 1.0};
+ static const float blue[] = {0.0, 0.0, 1.0, 1.0};
+ static const float clearcolor[] = {0.2, 0.2, 0.2, 1.0};
+
+ glClearColor(0.2, 0.2, 0.2, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ prog = piglit_build_simple_program(vs_text_redraw, fs_text_redraw);
+
+ glBindAttribLocation(prog, 0, "in_pos");
+ glBindAttribLocation(prog, 1, "in_col");
+
+ glUseProgram(prog);
+
+ /**
+ * Initial recording round already provided coordinates in attribute
+ * position zero. Here the colors are additionally provided in position
+ * one which needs to be activated as well.
+ */
+ glEnableVertexAttribArray(1);
+
+ pass = redraw_and_check(0, red, clearcolor, clearcolor) && pass;
+ pass = redraw_and_check(2, red, clearcolor, blue) && pass;
+
+ glDeleteTransformFeedbacks(1, &tfb);
+
+ return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
--
1.8.3.1
More information about the Piglit
mailing list