On 11/14/2013 04:20 AM, Topi Pohjolainen wrote:
> 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 <[email protected]>
> ---
>  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.

The code I see in the shader doesn't seem to match this comment.  It
looks like a primitives > 4 are sent to stream two.  It also doesn't
match the description above.

> + */
> +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

This works, and I'm not going to ask you to change it.  But... the way
we usually do this is declare one of the arrays with a literal size
(e.g., static GLuint xfb[3]), then use the ARRAY_SIZE() macro to re-use
that size.

Assuming the comment is just stale, with the comment fixed, the patch is

Reviewed-by: Ian Romanick <[email protected]>

> +
> +/**
> + * 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;
> +}
> 

_______________________________________________
Piglit mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/piglit

Reply via email to