[Piglit] [PATCH 07/23] arb_shader_image_load_store: Import memory coherency test.

Jordan Justen jordan.l.justen at intel.com
Sun Feb 1 14:23:13 PST 2015


On 2015-01-31 07:41:29, Francisco Jerez wrote:
> Test the cache coherency of images declared as "coherent" or
> "volatile" when accessed from different combinations of dependent
> shader stages.
> ---
>  tests/all.py                                       |   1 +
>  tests/quick.py                                     |   2 +
>  .../arb_shader_image_load_store/CMakeLists.gl.txt  |   1 +
>  tests/spec/arb_shader_image_load_store/coherency.c | 228 +++++++++++++++++++++
>  4 files changed, 232 insertions(+)
>  create mode 100644 tests/spec/arb_shader_image_load_store/coherency.c
> 
> diff --git a/tests/all.py b/tests/all.py
> index d045e0e..e82c7fd 100644
> --- a/tests/all.py
> +++ b/tests/all.py
> @@ -4428,6 +4428,7 @@ import_glsl_parser_tests(spec['ARB_shader_image_load_store'],
>                           [''])
>  arb_shader_image_load_store['atomicity'] = PiglitGLTest('arb_shader_image_load_store-atomicity', run_concurrent=True)
>  arb_shader_image_load_store['bitcast'] = PiglitGLTest('arb_shader_image_load_store-bitcast', run_concurrent=True)
> +arb_shader_image_load_store['coherency'] = PiglitGLTest('arb_shader_image_load_store-coherency', run_concurrent=True)
>  
>  profile.tests['hiz'] = hiz
>  profile.tests['fast_color_clear'] = fast_color_clear
> diff --git a/tests/quick.py b/tests/quick.py
> index 8762d7d..2f0d690 100644
> --- a/tests/quick.py
> +++ b/tests/quick.py
> @@ -12,3 +12,5 @@ del profile.tests['shaders']['glsl-fs-inline-explosion']
>  del profile.tests['shaders']['glsl-fs-unroll-explosion']
>  del profile.tests['shaders']['glsl-vs-inline-explosion']
>  del profile.tests['shaders']['glsl-vs-unroll-explosion']
> +
> +profile.tests['spec']['ARB_shader_image_load_store']['coherency'].command += ["--quick"]
> diff --git a/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt b/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt
> index 6b53370..6a6aa25 100644
> --- a/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt
> +++ b/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt
> @@ -14,5 +14,6 @@ set(depends image.c grid.c common.c)
>  
>  piglit_add_executable(arb_shader_image_load_store-atomicity atomicity.c ${depends})
>  piglit_add_executable(arb_shader_image_load_store-bitcast bitcast.c ${depends})
> +piglit_add_executable(arb_shader_image_load_store-coherency coherency.c ${depends})
>  
>  # vim: ft=cmake:
> diff --git a/tests/spec/arb_shader_image_load_store/coherency.c b/tests/spec/arb_shader_image_load_store/coherency.c
> new file mode 100644
> index 0000000..e8484a7
> --- /dev/null
> +++ b/tests/spec/arb_shader_image_load_store/coherency.c
> @@ -0,0 +1,228 @@
> +/*
> + * Copyright (C) 2014 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 coherency.c
> + *
> + * Images declared as "coherent" or "volatile" give certain guarantees
> + * regarding the visibility of memory writes to other shader invocations
> + * in the pipeline.  This test checks the following assertion of the
> + * spec:
> + * "When reading a variable declared as 'coherent', the values returned
> + *  will reflect the results of previously completed writes performed by
> + *  other shader invocations.  When writing a variable declared as
> + *  'coherent', the values written will be reflected in subsequent
> + *  coherent reads performed by other shader invocations."
> + *
> + * Together with:
> + * "When executing a shader whose inputs are generated from a previous
> + *  programmable stage, the shader invocations from the previous stage
> + *  are guaranteed to have executed far enough to generate final values
> + *  for all next-stage inputs."
> + *
> + * In order to test this we bind two shader programs at different
> + * execution stages of the pipeline and check that the values written to
> + * an image from the first stage are visible when the same primitive is
> + * dispatched at the second stage.  This is repeated for all combinations
> + * of dependent shader stages (what necessarily excludes the compute
> + * shader), for the "coherent" and "volatile" qualifiers (the latter is
> + * supposed to give stricter ordering guarantees), and for different
> + * execution sizes between 4x4 and 1024x1024 to account for
> + * implementations with varying levels of parallelism and with caches of
> + * different sizes.
> + *
> + * Unless running in "quick" mode a series of control tests is
> + * executed repeating the same process without any memory qualifiers.
> + * This is useful to see if the cache is being hit since otherwise the
> + * main test is not meaningful.  The control test always passes as it
> + * is expected to misrender.
> + */
> +
> +#include "common.h"
> +
> +/** Maximum image width. */
> +#define L 1024
> +
> +/** Maximum number of pixels. */
> +#define N (L * L)
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +
> +config.supports_gl_core_version = 32;
> +
> +config.window_width = L;
> +config.window_height = L;
> +config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
> +
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +struct image_qualifier_info {
> +        /** Test name. */
> +        const char *name;
> +
> +        /** Image qualifier keyword. */
> +        const char *qualifier;
> +
> +        /** Informative "control" test with no memory qualifiers whose
> +         * result is ignored. */
> +        bool control_test;
> +};
> +
> +const struct image_qualifier_info image_qualifiers[] = {
> +        { "control", "", true },
> +        { "'coherent' qualifier", "coherent", false },
> +        { "'volatile' qualifier", "volatile", false },
> +        { 0 }
> +};
> +
> +char *
> +qualifier_hunk(const struct image_qualifier_info *qual)
> +{
> +        char *s = NULL;
> +
> +        asprintf(&s, "#define IMAGE_Q %s\n", qual->qualifier);
> +        return s;
> +}
> +
> +static bool
> +init_image(const struct image_info img)
> +{
> +        static uint32_t pixels[N][4];
> +
> +        return init_pixels(img, pixels[0], 99, 99, 99, 99) &&
> +                upload_image(img, 0, pixels[0]);
> +}
> +
> +static bool
> +check(const struct grid_info grid, const struct image_info img)
> +{
> +        static uint32_t pixels[N][4];
> +
> +        return download_result(grid, pixels[0]) &&
> +                check_pixels(img, pixels[0], 33, 33, 33, 33);
> +}
> +
> +static bool
> +run_test(const struct image_qualifier_info *qual,
> +         const struct image_stage_info *stage_w,
> +         const struct image_stage_info *stage_r,
> +         unsigned l)
> +{
> +        const struct grid_info grid = {
> +                stage_w->bit | stage_r->bit,
> +                get_image_format(GL_RGBA32UI),
> +                { l, l, 1, 1 }
> +        };
> +        const struct image_info img = image_info_for_grid(grid);
> +        GLuint prog = generate_program(
> +                grid,
> +                /*
> +                 * Write (11, 22, 33, 44) to some location on the
> +                 * image from the write stage.
> +                 */
> +                stage_w->stage,
> +                concat(qualifier_hunk(qual),
> +                       image_hunk(img, ""),
> +                       hunk("IMAGE_Q uniform IMAGE_T img;\n"
> +                            "\n"
> +                            "GRID_T op(ivec2 idx, GRID_T x) {\n"
> +                            "       imageStore(img, idx, DATA_T(11, 22, 33, 44));"
> +                            "       return x;"
> +                            "}\n"), NULL),
> +                /*
> +                 * The same location will read back the expected value
> +                 * if image access is coherent, as the shader inputs
> +                 * of the read stage are dependent on the outputs of
> +                 * the write stage and consequently they are
> +                 * guaranteed to be executed sequentially.
> +                 */
> +                stage_r->stage,
> +                concat(qualifier_hunk(qual),
> +                       image_hunk(img, ""),
> +                       hunk("IMAGE_Q uniform IMAGE_T img;\n"
> +                            "\n"
> +                            "GRID_T op(ivec2 idx, GRID_T x) {\n"
> +                            "       DATA_T v = imageLoad(img, idx);"
> +                            "       if (v == DATA_T(11, 22, 33, 44))"
> +                            "             return GRID_T(33, 33, 33, 33);"
> +                            "       else"
> +                            "             return GRID_T(77, 77, 77, 77);"
> +                            "}\n"), NULL));
> +        bool ret = prog &&
> +                init_fb(grid) &&
> +                init_image(img) &&
> +                set_uniform_int(prog, "img", 0) &&
> +                draw_grid(grid, prog) &&
> +                (check(grid, img) || qual->control_test);
> +
> +        glDeleteProgram(prog);
> +        return ret;
> +}
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +        const bool quick = (argc >= 2 && !strcmp(argv[1], "--quick"));
> +        const struct image_qualifier_info *qual;
> +        const struct image_stage_info *stage_w;
> +        const struct image_stage_info *stage_r;
> +        enum piglit_result status = PIGLIT_PASS;
> +        unsigned l;
> +
> +        piglit_require_extension("GL_ARB_shader_image_load_store");
> +
> +        for (l = 4; l <= L; l *= (quick ? 8 : 2)) {
> +                for (qual = image_qualifiers; qual->name; ++qual) {
> +                        if (quick && qual->control_test)
> +                                continue;
> +
> +                        /*
> +                         * Loop for each pair of shader stages
> +                         * skipping the compute shader: "coherent"
> +                         * gives no useful guarantees in that case
> +                         * since its execution ordering is undefined
> +                         * with respect to the other shader stages.
> +                         */
> +                        for (stage_w = image_stages();
> +                             stage_w->stage && stage_w->stage != GL_COMPUTE_SHADER;
> +                             ++stage_w) {
> +                                for (stage_r = stage_w + 1;
> +                                     stage_r->stage && stage_r->stage != GL_COMPUTE_SHADER;

I guess compute will be the last in the list, so this code works as
expected.

It still seems like it would be better to add if(compute) continue
inside the two loops rather than using that as a loop terminating
condition.

Patches 3-7 Reviewed-by: Jordan Justen <jordan.l.justen at intel.com>

> +                                     ++stage_r) {
> +                                        subtest(&status, true,
> +                                                run_test(qual, stage_w, stage_r, l),
> +                                                "%s-%s shader/%s coherency test/%dx%d",
> +                                                stage_w->name, stage_r->name,
> +                                                qual->name, l, l);
> +                                }
> +                        }
> +                }
> +        }
> +
> +        piglit_report_result(status);
> +}
> +
> +enum piglit_result
> +piglit_display(void)
> +{
> +        return PIGLIT_FAIL;
> +}
> -- 
> 2.1.3
> 
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/piglit


More information about the Piglit mailing list