[Piglit] [PATCH] tests/image_load_store/atomic: use piglit subtest framework

Rafael Antognolli rafael.antognolli at intel.com
Wed Nov 21 01:01:11 UTC 2018


Awesome, thanks for doing this.

Reviewed-by: Rafael Antognolli <rafael.antognolli at intel.com>

Also, it fixes the issue I had, but apparently it's not the only test
with that problem. Another test with the same issue:

spec at arb_shader_image_size@builtin

I would guess there are other tests in the same situation, it just
happens that I didn't have a GPU hang with them, and so they didn't
incorrectly report pass when they actually hung.

Thanks anyway.
Rafael

On Mon, Nov 19, 2018 at 03:12:27PM -0800, Dylan Baker wrote:
> cc: Rafael Antognolli <rafael.antognolli at intel.com>
> ---
>  .../arb_shader_image_load_store/atomicity.c   | 403 +++++++++++-------
>  1 file changed, 239 insertions(+), 164 deletions(-)
> 
> diff --git a/tests/spec/arb_shader_image_load_store/atomicity.c b/tests/spec/arb_shader_image_load_store/atomicity.c
> index f53dddaa2..88d15d65d 100644
> --- a/tests/spec/arb_shader_image_load_store/atomicity.c
> +++ b/tests/spec/arb_shader_image_load_store/atomicity.c
> @@ -1,5 +1,6 @@
>  /*
>   * Copyright (C) 2014 Intel Corporation
> + * Copyright © 2018 Intel Corporation
>   *
>   * Permission is hereby granted, free of charge, to any person obtaining a
>   * copy of this software and associated documentation files (the "Software"),
> @@ -58,16 +59,7 @@
>  /** Total number of pixels in the window and image. */
>  #define N (W * H)
>  
> -PIGLIT_GL_TEST_CONFIG_BEGIN
> -
> -config.supports_gl_core_version = 32;
> -
> -config.window_width = W;
> -config.window_height = H;
> -config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
> -config.khr_no_error_support = PIGLIT_NO_ERRORS;
> -
> -PIGLIT_GL_TEST_CONFIG_END
> +static struct piglit_gl_test_config *piglit_config;
>  
>  static bool
>  init_image(const struct image_info img, uint32_t v)
> @@ -112,56 +104,28 @@ check_image_const(const struct image_info img, unsigned n, uint32_t v)
>                               pixels, v, 0, 0, 0);
>  }
>  
> -/**
> - * Test skeleton: Init image to \a init_value, run the provided shader
> - * \a op, check that the first \a check_sz pixels of the image equal
> - * \a check_value and optionally check that the resulting fragment
> - * values on the framebuffer are unique.
> - */
> -static bool
> -run_test(uint32_t init_value, unsigned check_sz, uint32_t check_value,
> -         bool check_unique, const char *op)
> -{
> -        const struct grid_info grid =
> -                grid_info(GL_FRAGMENT_SHADER, GL_R32UI, W, H);
> -        const struct image_info img =
> -                image_info(GL_TEXTURE_1D, GL_R32UI, W, H);
> -        GLuint prog = generate_program(
> -                grid, GL_FRAGMENT_SHADER,
> -                concat(image_hunk(img, ""),
> -                       hunk("volatile IMAGE_UNIFORM_T img;\n"),
> -                       hunk(op), NULL));
> -        bool ret = prog &&
> -                init_fb(grid) &&
> -                init_image(img, init_value) &&
> -                set_uniform_int(prog, "img", 0) &&
> -                draw_grid(grid, prog) &&
> -                check_image_const(img, check_sz, check_value) &&
> -                (!check_unique || check_fb_unique(grid));
> -
> -        glDeleteProgram(prog);
> -        return ret;
> -}
> -
> -void
> -piglit_init(int argc, char **argv)
> +struct testcase
>  {
> -        enum piglit_result status = PIGLIT_PASS;
> -
> -        piglit_require_extension("GL_ARB_shader_image_load_store");
> -
> +	uint32_t init_value;
> +	unsigned check_sz;
> +	uint32_t check_value;
> +	bool check_unique;
> +	const char * op;
> +};
> +
> +static struct testcase testdata[] = {
>          /*
>           * If imageAtomicAdd() is atomic the return values obtained
>           * from each call are guaranteed to be unique.
>           */
> -        subtest(&status, true,
> -                run_test(0, 1, N, true,
> -                         "GRID_T op(ivec2 idx, GRID_T x) {\n"
> -                         "       return GRID_T("
> -                         "          imageAtomicAdd(img, IMAGE_ADDR(ivec2(0)), 1u),"
> -                         "          0, 0, 1);\n"
> -                         "}\n"),
> -                "imageAtomicAdd");
> +	{
> +		0, 1, N, true,
> +		"GRID_T op(ivec2 idx, GRID_T x) {\n"
> +		"       return GRID_T("
> +		"          imageAtomicAdd(img, IMAGE_ADDR(ivec2(0)), 1u),"
> +		"          0, 0, 1);\n"
> +		"}\n",
> +	},
>  
>          /*
>           * Call imageAtomicMin() on a fixed location from within a
> @@ -175,20 +139,20 @@ piglit_init(int argc, char **argv)
>           * repeat.  In the end we obtain a unique counter value for
>           * each fragment if the read-modify-write operation is atomic.
>           */
> -        subtest(&status, true,
> -                run_test(0xffffffff, 1, 0xffffffff - N, true,
> -                        "GRID_T op(ivec2 idx, GRID_T x) {\n"
> -                        "       uint old, v = 0xffffffffu;"
> -                        "\n"
> -                        "       do {\n"
> -                        "               old = v;\n"
> -                        "               v = imageAtomicMin(img, IMAGE_ADDR(ivec2(0)),"
> -                        "                                  v - 1u);\n"
> -                        "       } while (v != old);\n"
> -                        "\n"
> -                        "       return GRID_T(v, 0, 0, 1);\n"
> -                        "}\n"),
> -                "imageAtomicMin");
> +	{
> +                0xffffffff, 1, 0xffffffff - N, true,
> +                "GRID_T op(ivec2 idx, GRID_T x) {\n"
> +                "       uint old, v = 0xffffffffu;"
> +                "\n"
> +                "       do {\n"
> +                "               old = v;\n"
> +                "               v = imageAtomicMin(img, IMAGE_ADDR(ivec2(0)),"
> +                "                                  v - 1u);\n"
> +                "       } while (v != old);\n"
> +                "\n"
> +                "       return GRID_T(v, 0, 0, 1);\n"
> +                "}\n",
> +	},
>  
>          /*
>           * Use imageAtomicMax() on a fixed location to increment a
> @@ -196,94 +160,93 @@ piglit_init(int argc, char **argv)
>           * atomicity of the built-in guarantees that the obtained
>           * values will be unique for each fragment.
>           */
> -        subtest(&status, true,
> -                run_test(0, 1, N, true,
> -                        "GRID_T op(ivec2 idx, GRID_T x) {\n"
> -                        "       uint old, v = 0u;"
> -                        "\n"
> -                        "       do {\n"
> -                        "               old = v;\n"
> -                        "               v = imageAtomicMax(img, IMAGE_ADDR(ivec2(0)),"
> -                        "                                  v + 1u);\n"
> -                        "       } while (v != old);\n"
> -                        "\n"
> -                        "       return GRID_T(v, 0, 0, 1);\n"
> -                        "}\n"),
> -                "imageAtomicMax");
> +	{
> +                0, 1, N, true,
> +                "GRID_T op(ivec2 idx, GRID_T x) {\n"
> +                "       uint old, v = 0u;"
> +                "\n"
> +                "       do {\n"
> +                "               old = v;\n"
> +                "               v = imageAtomicMax(img, IMAGE_ADDR(ivec2(0)),"
> +                "                                  v + 1u);\n"
> +                "       } while (v != old);\n"
> +                "\n"
> +                "       return GRID_T(v, 0, 0, 1);\n"
> +                "}\n",
> +	},
>  
>          /*
>           * Use imageAtomicAnd() to flip individual bits of a bitmap
>           * atomically.  The atomicity of the built-in guarantees that
>           * all bits will be clear on termination.
>           */
> -        subtest(&status, true,
> -                run_test(0xffffffff, N / 32, 0, false,
> -                        "GRID_T op(ivec2 idx, GRID_T x) {\n"
> -                        "       int i = IMAGE_ADDR(idx);\n"
> -                        "       uint m = ~(1u << (i % 32));\n"
> -                        "\n"
> -                        "       imageAtomicAnd(img, i / 32, m);\n"
> -                        "\n"
> -                        "       return GRID_T(0, 0, 0, 1);\n"
> -                        "}\n"),
> -                "imageAtomicAnd");
> +	{
> +                0xffffffff, N / 32, 0, false,
> +                "GRID_T op(ivec2 idx, GRID_T x) {\n"
> +                "       int i = IMAGE_ADDR(idx);\n"
> +                "       uint m = ~(1u << (i % 32));\n"
> +                "\n"
> +                "       imageAtomicAnd(img, i / 32, m);\n"
> +                "\n"
> +                "       return GRID_T(0, 0, 0, 1);\n"
> +                "}\n",
> +	},
>  
>          /*
>           * Use imageAtomicOr() to flip individual bits of a bitmap
>           * atomically.  The atomicity of the built-in guarantees that
>           * all bits will be set on termination.
>           */
> -        subtest(&status, true,
> -                run_test(0, N / 32, 0xffffffff, false,
> -                        "GRID_T op(ivec2 idx, GRID_T x) {\n"
> -                        "       int i = IMAGE_ADDR(idx);\n"
> -                        "       uint m = (1u << (i % 32));\n"
> -                        "\n"
> -                        "       imageAtomicOr(img, i / 32, m);\n"
> -                        "\n"
> -                        "       return GRID_T(0, 0, 0, 1);\n"
> -                        "}\n"),
> -                "imageAtomicOr");
> +	{
> +                0, N / 32, 0xffffffff, false,
> +                "GRID_T op(ivec2 idx, GRID_T x) {\n"
> +                "       int i = IMAGE_ADDR(idx);\n"
> +                "       uint m = (1u << (i % 32));\n"
> +                "\n"
> +                "       imageAtomicOr(img, i / 32, m);\n"
> +                "\n"
> +                "       return GRID_T(0, 0, 0, 1);\n"
> +                "}\n",
> +	},
>  
>          /*
>           * Use imageAtomicXor() to flip individual bits of a bitmap
>           * atomically.  The atomicity of the built-in guarantees that
>           * all bits will have been inverted on termination.
>           */
> -        subtest(&status, true,
> -                run_test(0x55555555, N / 32, 0xaaaaaaaa, false,
> -                        "GRID_T op(ivec2 idx, GRID_T x) {\n"
> -                        "       int i = IMAGE_ADDR(idx);\n"
> -                        "       uint m = (1u << (i % 32));\n"
> -                        "\n"
> -                        "       imageAtomicXor(img, i / 32, m);\n"
> -                        "\n"
> -                        "       return GRID_T(0, 0, 0, 1);\n"
> -                        "}\n"),
> -                "imageAtomicXor");
> +	{
> +                0x55555555, N / 32, 0xaaaaaaaa, false,
> +                "GRID_T op(ivec2 idx, GRID_T x) {\n"
> +                "       int i = IMAGE_ADDR(idx);\n"
> +                "       uint m = (1u << (i % 32));\n"
> +                "\n"
> +                "       imageAtomicXor(img, i / 32, m);\n"
> +                "\n"
> +                "       return GRID_T(0, 0, 0, 1);\n"
> +                "}\n",
> +	},
>  
>          /*
>           * Use imageAtomicExchange() to flip individual bits of a
>           * bitmap atomically.  The atomicity of the built-in
>           * guarantees that all bits will be set on termination.
>           */
> -        subtest(&status, true,
> -                run_test(0, N / 32, 0xffffffff, false,
> -                        "GRID_T op(ivec2 idx, GRID_T x) {\n"
> -                        "       int i = IMAGE_ADDR(idx);\n"
> -                        "       uint m = (1u << (i % 32));\n"
> -                        "       uint old = 0u;\n"
> -                        "\n"
> -                        "       do {\n"
> -                        "               m |= old;\n"
> -                        "               old = imageAtomicExchange("
> -                        "                       img, i / 32, m);\n"
> -                        "       } while ((old & ~m) != 0u);\n"
> -                        "\n"
> -                        "       return GRID_T(0, 0, 0, 1);\n"
> -                        "}\n"),
> -                "imageAtomicExchange");
> -
> +	{
> +                0, N / 32, 0xffffffff, false,
> +                "GRID_T op(ivec2 idx, GRID_T x) {\n"
> +                "       int i = IMAGE_ADDR(idx);\n"
> +                "       uint m = (1u << (i % 32));\n"
> +                "       uint old = 0u;\n"
> +                "\n"
> +                "       do {\n"
> +                "               m |= old;\n"
> +                "               old = imageAtomicExchange("
> +                "                       img, i / 32, m);\n"
> +                "       } while ((old & ~m) != 0u);\n"
> +                "\n"
> +                "       return GRID_T(0, 0, 0, 1);\n"
> +                "}\n",
> +	},
>  #if 0
>          /*
>           * Use imageAtomicExchange() on a fixed location to increment
> @@ -318,21 +281,22 @@ piglit_init(int argc, char **argv)
>           * hang.  It seems to work fine on nVidia though, it would be
>           * interesting to see if it works on other platforms.
>           */
> -        subtest(&status, true,
> -                run_test(0, 1, N, true,
> -                        "GRID_T op(ivec2 idx, GRID_T x) {\n"
> -                        "       uint p = 0xffffffffu, v = 0xffffffffu;\n"
> -                        "\n"
> -                        "       do {\n"
> -                        "               if (p != 0xffffffffu)\n"
> -                        "                       v = p++;\n"
> -                        "               p = imageAtomicExchange("
> -                        "                  img, IMAGE_ADDR(ivec2(0)), p);\n"
> -                        "       } while (v == 0xffffffffu);\n"
> -                        "\n"
> -                        "       return GRID_T(v, 0, 0, 1);\n"
> -                        "}\n"),
> -                "imageAtomicExchange (locking)");
> +	{
> +                0, 1, N, true,
> +                "GRID_T op(ivec2 idx, GRID_T x) {\n"
> +                "       uint p = 0xffffffffu, v = 0xffffffffu;\n"
> +                "\n"
> +                "       do {\n"
> +                "               if (p != 0xffffffffu)\n"
> +                "                       v = p++;\n"
> +                "               p = imageAtomicExchange("
> +                "                  img, IMAGE_ADDR(ivec2(0)), p);\n"
> +                "       } while (v == 0xffffffffu);\n"
> +                "\n"
> +                "       return GRID_T(v, 0, 0, 1);\n"
> +                "}\n",
> +                "imageAtomicExchange (locking)",
> +	},
>  #endif
>  
>          /*
> @@ -342,22 +306,133 @@ piglit_init(int argc, char **argv)
>           * argument.  The atomicity of the built-in guarantees that
>           * the obtained values will be unique for each fragment.
>           */
> -        subtest(&status, true,
> -                run_test(0, 1, N, true,
> -                        "GRID_T op(ivec2 idx, GRID_T x) {\n"
> -                        "       uint old, v = 0u;"
> -                        "\n"
> -                        "       do {\n"
> -                        "               old = v;\n"
> -                        "               v = imageAtomicCompSwap("
> -                        "                  img, IMAGE_ADDR(ivec2(0)), v, v + 1u);\n"
> -                        "       } while (v != old);\n"
> -                        "\n"
> -                        "       return GRID_T(v, 0, 0, 1);\n"
> -                        "}\n"),
> -                "imageAtomicCompSwap");
> -
> -        piglit_report_result(status);
> +	{
> +                0, 1, N, true,
> +                "GRID_T op(ivec2 idx, GRID_T x) {\n"
> +                "       uint old, v = 0u;"
> +                "\n"
> +                "       do {\n"
> +                "               old = v;\n"
> +                "               v = imageAtomicCompSwap("
> +                "                  img, IMAGE_ADDR(ivec2(0)), v, v + 1u);\n"
> +                "       } while (v != old);\n"
> +                "\n"
> +                "       return GRID_T(v, 0, 0, 1);\n"
> +                "}\n",
> +	},
> +};
> +
> +/**
> + * Test skeleton: Init image to \a init_value, run the provided shader
> + * \a op, check that the first \a check_sz pixels of the image equal
> + * \a check_value and optionally check that the resulting fragment
> + * values on the framebuffer are unique.
> + */
> +static enum piglit_result
> +run_test(void * data)
> +{
> +	const struct testcase * test = (const struct testcase *)data;
> +
> +        const struct grid_info grid =
> +                grid_info(GL_FRAGMENT_SHADER, GL_R32UI, W, H);
> +        const struct image_info img =
> +                image_info(GL_TEXTURE_1D, GL_R32UI, W, H);
> +        GLuint prog = generate_program(
> +                grid, GL_FRAGMENT_SHADER,
> +                concat(image_hunk(img, ""),
> +                       hunk("volatile IMAGE_UNIFORM_T img;\n"),
> +                       hunk(test->op), NULL));
> +        bool ret = prog &&
> +                init_fb(grid) &&
> +                init_image(img, test->init_value) &&
> +                set_uniform_int(prog, "img", 0) &&
> +                draw_grid(grid, prog) &&
> +                check_image_const(img, test->check_sz, test->check_value) &&
> +                (!test->check_unique || check_fb_unique(grid));
> +
> +        glDeleteProgram(prog);
> +        return ret ? PIGLIT_PASS : PIGLIT_FAIL;
> +}
> +
> +static struct piglit_subtest tests[] = {
> +	{
> +		"imageAtomicAdd",
> +		"add",
> +		run_test,
> +		(void *)&testdata[0],
> +	},
> +	{
> +		"imageAtomicMin",
> +		"min",
> +		run_test,
> +		(void *)&testdata[1],
> +	},
> +	{
> +                "imageAtomicMax",
> +		"max",
> +		run_test,
> +		(void *)&testdata[2],
> +	},
> +	{
> +                "imageAtomicAnd",
> +		"and",
> +		run_test,
> +		(void *)&testdata[3],
> +	},
> +	{
> +                "imageAtomicOr",
> +		"or",
> +		run_test,
> +		(void *)&testdata[4],
> +	},
> +	{
> +                "imageAtomicXor",
> +		"xor",
> +		run_test,
> +		(void *)&testdata[5],
> +	},
> +	{
> +                "imageAtomicExchange",
> +		"exchange",
> +		run_test,
> +		(void *)&testdata[6],
> +	},
> +	{
> +                "imageAtomicCompSwap",
> +		"comp_swap",
> +		run_test,
> +		(void *)&testdata[7],
> +	},
> +	{0},
> +};
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +
> +piglit_config = &config;
> +config.subtests = tests;
> +config.supports_gl_core_version = 32;
> +
> +config.window_width = W;
> +config.window_height = H;
> +config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
> +config.khr_no_error_support = PIGLIT_NO_ERRORS;
> +
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +        piglit_require_extension("GL_ARB_shader_image_load_store");
> +
> +        enum piglit_result result = PIGLIT_PASS;
> +
> +	result = piglit_run_selected_subtests(
> +		tests,
> +		piglit_config->selected_subtests,
> +		piglit_config->num_selected_subtests,
> +		result);
> +
> +	piglit_report_result(result);
>  }
>  
>  enum piglit_result
> -- 
> 2.19.1
> 


More information about the Piglit mailing list