[Piglit] [PATCH 3/3] sso: Combine 20 vertex shaders and 20 fragment shaders in various ways.

Paul Berry stereotype441 at gmail.com
Mon Oct 14 11:20:47 PDT 2013


On 1 October 2013 18:22, Ian Romanick <idr at freedesktop.org> wrote:

> From: Ian Romanick <ian.d.romanick at intel.com>
>
> Verify that the right shaders are used in the right combinations several
> ways.
>
> * The vertex shader has information baked-in that determines the X position
>   of the block on the screen.
>
> * The fragment shader has information baked-in that determines how the
>   block is colored.  This is combined with data passed from the vertex
>   shader.
>
> Since data is passed from the vertex shader to the fragment shader, the
> test can use either rendezvous-by-name (default) or rendezvous-by-location
> (with --by-location command line parameter).
>
> This test passes in both modes on NVIDIA (304.64 on GTX 260).
>
> Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
> ---
>  tests/all.tests                                    |   2 +
>  .../arb_separate_shader_objects/400-combinations.c | 377
> +++++++++++++++++++++
>  .../arb_separate_shader_objects/CMakeLists.gl.txt  |   1 +
>  3 files changed, 380 insertions(+)
>  create mode 100644
> tests/spec/arb_separate_shader_objects/400-combinations.c
>
> diff --git a/tests/all.tests b/tests/all.tests
> index 33556af..1e79514 100644
> --- a/tests/all.tests
> +++ b/tests/all.tests
> @@ -1279,6 +1279,8 @@ arb_separate_shader_objects['Mix BindProgramPipeline
> and UseProgram'] = concurre
>  arb_separate_shader_objects['ProgramUniform coverage'] =
> concurrent_test('arb_separate_shader_object-ProgramUniform-coverage')
>  arb_separate_shader_objects['Rendezvous by location'] =
> plain_test('arb_separate_shader_object-rendezvous_by_location -fbo')
>  arb_separate_shader_objects['ValidateProgramPipeline'] =
> concurrent_test('arb_separate_shader_object-ValidateProgramPipeline')
> +arb_separate_shader_objects['400 combinations by location'] =
> plain_test('arb_separate_shader_object-400-combinations -fbo --by-location')
> +arb_separate_shader_objects['400 combinations by name'] =
> plain_test('arb_separate_shader_object-400-combinations -fbo')
>
>  # Group ARB_sampler_objects
>  arb_sampler_objects = Group()
> diff --git a/tests/spec/arb_separate_shader_objects/400-combinations.c
> b/tests/spec/arb_separate_shader_objects/400-combinations.c
> new file mode 100644
> index 0000000..8593b6e
> --- /dev/null
> +++ b/tests/spec/arb_separate_shader_objects/400-combinations.c
> @@ -0,0 +1,377 @@
> +/*
> + * 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.
> + */
> +
> +/**
> + * \file 400-combinations.c
> + * Combine 20 vertex shaders and 20 fragment shaders in various ways.
> + *
> + * Verify that the right shaders are used in the right combinations
> several
> + * ways.
> + *
> + * * The vertex shader has information baked-in that determines the X
> position
> + *   of the block on the screen.
> + *
> + * * The fragment shader has information baked-in that determines how the
> + *   block is colored.  This is combined with data passed from the vertex
> + *   shader.
> + *
> + * Since data is passed from the vertex shader to the fragment shader, the
> + * test can use either rendezvous-by-name (default) or
> rendezvous-by-location
> + * (with --by-location command line parameter).
> + */
> +#include "piglit-util-gl-common.h"
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +
> +       config.supports_gl_compat_version = 10;
> +       config.supports_gl_core_version = 31;
> +       config.window_visual = PIGLIT_GL_VISUAL_RGB |
> PIGLIT_GL_VISUAL_DOUBLE;
>

I'd feel more comfortable if we added:

config.window_width = (tile_size + border_size) * ARRAY_SIZE(vs_programs);
config.window_height = (tile_size + border_size) * ARRAY_SIZE(fs_programs);

That way (a) the fact that this test requires a sufficiently large window
is explicit, and (b) if we try to run this test with a different default
piglit window size (as we often do when running piglit with a hardware
simulator) it won't fail.


> +
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +/**
> + * Size of each square that will be drawn.
> + */
> +static const unsigned tile_size = 5;
> +
> +/**
> + * Size of the gap between the squares.
> + */
> +static const unsigned border_size = 2;
> +
> +static GLuint vs_programs[20];
> +static GLuint fs_programs[20];
> +
> +static GLuint pipe;
> +
> +static GLuint vao = 0;
> +static GLuint bo = 0;
> +
> +struct combination {
> +       unsigned char row;
> +       unsigned char col;
> +};
> +
> +static struct combination combinations[ARRAY_SIZE(vs_programs)
> +                                      * ARRAY_SIZE(fs_programs)];
> +
> +static const char *vs_code =
> +       "#version %d\n"
> +       "#extension GL_ARB_separate_shader_objects: require\n"
> +       "#extension GL_ARB_explicit_attrib_location: require\n"
> +       "\n"
> +       "layout(location = 0) in vec4 piglit_vertex;\n"
> +       "layout(location = 1) in vec3 vertex_color;\n"
> +       "\n"
> +       "%s out vec3 %s;\n"
> +       "\n"
> +       "const vec4 offset = vec4(%d, 0, 0, 0);\n"
> +       "\n"
> +       "uniform mat4 transform;\n"
> +       "\n"
> +       "void main()\n"
> +       "{\n"
> +       "    gl_Position = transform * (piglit_vertex + offset);\n"
> +       "    %s = vertex_color;\n"
> +       "}\n"
> +       ;
> +
> +static const char *fs_code =
> +       "#version %d\n"
> +       "#extension GL_ARB_separate_shader_objects: require\n"
> +       "#extension GL_ARB_explicit_attrib_location: enable\n"
> +       "\n"
> +       "#if __VERSION__ >= 130\n"
> +       "layout(location = 0) out vec4 out_color;\n"
> +       "#else\n"
> +       "#define out_color gl_FragColor\n"
> +       "#endif\n"
> +       "\n"
> +       "%s in vec3 %s;\n"
> +       "\n"
> +       "const vec3 color_offset = vec3(%d, %d, %d);\n"
> +       "\n"
> +       "void main()\n"
> +       "{\n"
> +       "    out_color = vec4(%s + color_offset, 1.);\n"
> +       "}\n"
> +       ;
> +
> +enum piglit_result
> +piglit_display(void)
> +{
> +       unsigned i;
> +       unsigned j;
> +
> +       static const float expected[] = {
> +               0.0f, 1.0f, 0.0f, 1.0f
> +       };
> +
> +       /* This is stored in row-major order.  Note the GL_TRUE parameter
> to
> +        * the glProgramUniformMatrix4fv call below.
> +        */
> +       const float transform[16] = {
> +               2.f / piglit_width, 0.0f, 0.0f, -1.0f,
> +               0.0f, 2.f / piglit_height, 0.0f, -1.0f,
> +               0.0f, 0.0f, 0.0f,  0.0f,
> +               0.0f, 0.0f, 0.0f, 1.0f,
> +       };
> +
> +       bool pass = true;
> +
> +       glClearColor(.5f, .5f, .5f, 1.f);
> +       glClear(GL_COLOR_BUFFER_BIT);
> +
> +       for (i = 0; i < ARRAY_SIZE(vs_programs); i++) {
> +               const GLint loc =
> +                       glGetUniformLocation(vs_programs[i], "transform");
> +
> +               glProgramUniformMatrix4fv(vs_programs[i], loc, 1, GL_TRUE,
> +                                         transform);
> +       }
> +
> +       glBindProgramPipeline(pipe);
> +
> +       for (i = 0; i < ARRAY_SIZE(combinations); i++) {
> +               const unsigned row = combinations[i].row;
> +               const unsigned col = combinations[i].col;
> +
> +               glUseProgramStages(pipe, GL_VERTEX_SHADER_BIT,
> +                                  vs_programs[col]);
> +               glUseProgramStages(pipe, GL_FRAGMENT_SHADER_BIT,
> +                                  fs_programs[row]);
> +               glDrawArrays(GL_TRIANGLE_FAN, row * 4, 4);
> +       }
> +
> +       glBindProgramPipeline(0);
> +
> +       for (i = 0; i < ARRAY_SIZE(vs_programs); i++) {
> +               for (j = 0; j < ARRAY_SIZE(fs_programs); j++) {
> +                       const unsigned x = (i * tile_size)
> +                               + ((i + 1) * border_size);
> +                       const unsigned y = (j * tile_size)
> +                               + ((j + 1) * border_size);
> +
> +                       pass = piglit_probe_rect_rgba(x, y,
> +                                                     tile_size, tile_size,
> +                                                     expected)
> +                               && pass;
> +               }
> +       }
> +
> +       piglit_present_results();
> +       return pass ? PIGLIT_PASS : PIGLIT_FAIL;
> +}
> +
> +#define RED(x)    ((int) (x / 2))
> +#define GREEN(x)  (-(int) x)
> +#define BLUE(x)   ((int) (x * 7))
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +       unsigned glsl_version;
> +       unsigned i;
> +       unsigned j;
> +       unsigned idx;
> +       bool es;
> +       int glsl_major;
> +       int glsl_minor;
> +       const char *location;
> +       const char *vertex_name;
> +       const char *fragment_name;
> +
> +       struct vertex {
> +               float x;
> +               float y;
> +               float r;
> +               float g;
> +               float b;
> +       } *vert;
> +
> +       piglit_require_extension("GL_ARB_separate_shader_objects");
> +       piglit_require_extension("GL_ARB_explicit_attrib_location");
> +
> +       if (argc > 1 && strcmp(argv[1], "--by-location") == 0) {
> +               location = "layout(location = 3)";
> +               vertex_name = "a";
> +               fragment_name = "b";
> +       } else {
> +               location = "";
> +               vertex_name = "in_color";
> +               fragment_name = "in_color";
> +       }
> +
> +       /* Some NVIDIA drivers have issues with layout qualifiers, 'in'
> +        * keywords, and 'out' keywords in "lower" GLSL versions.  If the
> +        * driver supports GLSL >= 1.40, use 1.40.  Otherwise, pick the
> +        * highest version that the driver supports.
> +        */
> +       piglit_get_glsl_version(&es, &glsl_major, &glsl_minor);
> +       glsl_version = ((glsl_major * 100) + glsl_minor) >= 140
> +               ? 140 : ((glsl_major * 100) + glsl_minor);
> +
> +       /* Generate the vertex shader programs.  Each vertex shader is
> +        * hardcoded to select a specific column on the display.
> +        */
> +       printf("Generating vertex shaders...\n");
> +       for (i = 0; i < ARRAY_SIZE(vs_programs); i++) {
> +               const unsigned base_x = (i * tile_size)
> +                       + ((i + 1) * border_size);
> +
> +               char *source = NULL;
> +
> +               asprintf(&source, vs_code,
> +                        glsl_version,
> +                        location,
> +                        vertex_name,
> +                        base_x,
> +                        vertex_name);
> +
> +               vs_programs[i] =
> +                       glCreateShaderProgramv(GL_VERTEX_SHADER, 1,
> +                                              (const GLchar *const *)
> &source);
> +               piglit_link_check_status(vs_programs[i]);
> +
> +               if (i == 0)
> +                       puts(source);
> +
> +               free(source);
> +       }
> +
> +       printf("Generating fragment shaders...\n");
> +       for (i = 0; i < ARRAY_SIZE(fs_programs); i++) {
> +               char *source = NULL;
> +
> +               asprintf(&source, fs_code,
> +                        glsl_version,
> +                        location,
> +                        fragment_name,
> +                        RED(i), GREEN(i), BLUE(i),
> +                        fragment_name);
> +
> +               fs_programs[i] =
> +                       glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1,
> +                                              (const GLchar *const *)
> &source);
> +               piglit_link_check_status(fs_programs[i]);
> +
> +               if (i == 3)
> +                       puts(source);
> +
> +               free(source);
> +       }
> +
> +       glGenProgramPipelines(1, &pipe);
> +
> +       /* Generate vertex data for the tests.  The row of each block is
> +        * determined by the vertex data.  The color data for the block
> comes
> +        * from the vertex data and the data baked into the fragment
> shader.
> +        */
> +       if (piglit_get_gl_version() >= 30
> +           ||
> piglit_is_extension_supported("GL_ARB_vertex_array_object")) {
> +               glGenVertexArrays(1, &vao);
> +               glBindVertexArray(vao);
> +       }
> +
> +       glGenBuffers(1, &bo);
> +       glBindBuffer(GL_ARRAY_BUFFER, bo);
> +       glBufferData(GL_ARRAY_BUFFER,
> +                    sizeof(vert[0]) * 4 * ARRAY_SIZE(fs_programs),
> +                    NULL, GL_STATIC_DRAW);
> +
> +       vert = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
> +
> +       for (i = 0; i < ARRAY_SIZE(fs_programs); i++) {
> +               const unsigned base_y = (i * tile_size)
> +                       + ((i + 1) * border_size);
> +
> +               vert[(i * 4) + 0].x = 0.f;
> +               vert[(i * 4) + 0].y = (float) base_y;
> +               vert[(i * 4) + 0].r = (float) -RED(i);
> +               vert[(i * 4) + 0].g = (float) 1 - GREEN(i);
> +               vert[(i * 4) + 0].b = (float) -BLUE(i);
> +
> +               vert[(i * 4) + 1].x = (float) tile_size;
> +               vert[(i * 4) + 1].y = (float) base_y;
> +               vert[(i * 4) + 1].r = (float) -RED(i);
> +               vert[(i * 4) + 1].g = (float) 1 - GREEN(i);
> +               vert[(i * 4) + 1].b = (float) -BLUE(i);
> +
> +               vert[(i * 4) + 2].x = (float) tile_size;
> +               vert[(i * 4) + 2].y = (float) (base_y + tile_size);
> +               vert[(i * 4) + 2].r = (float) -RED(i);
> +               vert[(i * 4) + 2].g = (float) 1 - GREEN(i);
> +               vert[(i * 4) + 2].b = (float) -BLUE(i);
> +
> +               vert[(i * 4) + 3].x = 0.f;
> +               vert[(i * 4) + 3].y = (float) (base_y + tile_size);
> +               vert[(i * 4) + 3].r = (float) -RED(i);
> +               vert[(i * 4) + 3].g = (float) 1 - GREEN(i);
> +               vert[(i * 4) + 3].b = (float) -BLUE(i);
> +       }
> +
> +       glUnmapBuffer(GL_ARRAY_BUFFER);
> +
> +       glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vert[0]),
> +                             (void *)(intptr_t) offsetof(struct vertex,
> x));
> +       glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vert[0]),
> +                             (void *)(intptr_t) offsetof(struct vertex,
> r));
> +       glEnableVertexAttribArray(0);
> +       glEnableVertexAttribArray(1);
> +
> +       /* Generate the set of combinations of vertex shader programs and
> +        * fragment shader programs that will be used together.  This is
> all
> +        * the possible combinations.  The next step is to shuffle list so
> +        * that there's (hopefully) no pattern to the access
> combination... to
> +        * uncover driver bugs.
> +        */
> +       idx = 0;
> +       for (i = 0; i < ARRAY_SIZE(vs_programs); i++) {
> +               for (j = 0; j < ARRAY_SIZE(fs_programs); j++) {
> +                       combinations[idx].row = j;
> +                       combinations[idx].col = i;
> +                       idx++;
> +               }
> +       }
> +
> +       for (i = 0; i < (5 * ARRAY_SIZE(combinations)); i++) {
> +               /* Pick a random element from the array.
> +                */
> +               const unsigned src = rand() % ARRAY_SIZE(combinations);
> +
> +               /* Pick a random element from the array that is not the
> same
> +                * as the previous element.  This is done by picking a
> second
> +                * number on the range [1, ARRAY_SIZE(combinations) - 2]
> and
> +                * adding it (using modular addition) to the first.
> +                */
> +               const unsigned delta =
> +                       (rand() % (ARRAY_SIZE(combinations) - 1)) + 1;
> +               const unsigned dst = (src + delta) %
> ARRAY_SIZE(combinations);
> +
> +               /* Exchange the two selected elements.
> +                */
> +               const struct combination temp = combinations[dst];
> +               combinations[dst] = combinations[src];
> +               combinations[src] = temp;
> +       }
>

A less ad-hoc algorithm for shuffling an array is:

for (i = ARRAY_SIZE(combinations); i > 1; i--) {
   j = rand() % i;
   if (j != i - 1)
      swap elements j and i - 1
}

Neglecting deficiencies in rand(), this algorithm produces all possible
permutations with equal probability.


With the above two changes, this patch is:

Reviewed-by: Paul Berry <stereotype441 at gmail.com>


> +}
> diff --git a/tests/spec/arb_separate_shader_objects/CMakeLists.gl.txt
> b/tests/spec/arb_separate_shader_objects/CMakeLists.gl.txt
> index 32a28ba..2e2e1b8 100644
> --- a/tests/spec/arb_separate_shader_objects/CMakeLists.gl.txt
> +++ b/tests/spec/arb_separate_shader_objects/CMakeLists.gl.txt
> @@ -9,6 +9,7 @@ link_libraries (
>         ${OPENGL_glu_LIBRARY}
>  )
>
> +piglit_add_executable (arb_separate_shader_object-400-combinations
> 400-combinations.c)
>  piglit_add_executable (arb_separate_shader_object-GetProgramPipelineiv
> GetProgramPipelineiv.c)
>  piglit_add_executable (arb_separate_shader_object-IsProgramPipeline
> IsProgramPipeline.c)
>  piglit_add_executable (arb_separate_shader_object-mix_pipeline_useprogram
> mix_pipeline_useprogram.c)
> --
> 1.8.1.4
>
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/piglit
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/piglit/attachments/20131014/e13d163c/attachment-0001.html>


More information about the Piglit mailing list