[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:53:44 PDT 2013


On 14 October 2013 11:33, Ian Romanick <idr at freedesktop.org> wrote:

> On 10/14/2013 11:20 AM, Paul Berry wrote:
> > On 1 October 2013 18:22, Ian Romanick <idr at freedesktop.org
> > <mailto:idr at freedesktop.org>> wrote:
> >
> >     From: Ian Romanick <ian.d.romanick at intel.com
> >     <mailto: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
> >     <mailto: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.
>
> Good call!  I like that.  I feel like we should collect some of these
> tricks into an "Effective piglit" wiki or something....
>
> >     +
> >     +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.
>
> Okay... I like not having to rand() twice.
>
> I understand (and empathize) your reservations about using rand.  I
> think we can cope with them in a couple ways.
>
> 1. Implement a piglit_rand.  This guarantees that we'll have the same
> generator on all platforms, compilers, etc.  This doesn't even have to
> be a great generator... a dumb LFSR should do it.  Most tests that want
> random numbers just want a shuffled sequence or some non-sequential data
> values.
>
> 2. Implement some standard piglit options for controlling the generator.
>  These options would be parsed by the piglit framework code.  I'm
> thinking --random-seed-clock and --random-seed=<some value>.
>
> 3. Make the random number generator log the seed used when it is first
> called.
>
> 4. Have a default seed that can be overridden with one of the previously
> mentioned command line options.
>
> Thoughts?
>

Personally, I'd vote for a combination of options 1 and 4.  That would
ensure that vanilla piglit runs are repeatable (even across
implementations, which is a nice bonus).  Options 2 and 3 would be nice,
but I don't think they're strictly necessary--I bet if we didn't do them no
one would notice/care.

Incidentally, in case it wasn't clear from my previous email, I think it's
just fine to go ahead with this patch before we've resolved what to do
about rand().


>
> > With the above two changes, this patch is:
> >
> > Reviewed-by: Paul Berry <stereotype441 at gmail.com
> > <mailto: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 <mailto: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/e24cca30/attachment-0001.html>


More information about the Piglit mailing list