2 * Copyright (C) 2014 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 /** @file shader-mem-barrier.c
26 * Test that the memoryBarrier() GLSL built-in effectively serializes
27 * memory transactions initiated after and before the call. This is
28 * done by having a number of threads write to separate locations in a
29 * loop serializing each pair of writes with memoryBarrier() while the
30 * remaining threads monitor the evolution of the same memory
31 * locations until an inconsistency is observed or the test runs to
34 * The test is repeated for the "volatile" qualifier, for all
35 * execution stages and for different relative arrangements of
36 * producer and monitor threads to account for implementations with
37 * varying levels of parallelism and with caches of different sizes.
39 * Unless running in "quick" mode a series of control tests is
40 * executed which disables memory barriers in order to make sure that
41 * the test is meaningful. The control test always passes as it is
42 * expected to misrender.
53 /** Total number of pixels in the image. */
56 /** Maximum modulus. */
59 PIGLIT_GL_TEST_CONFIG_BEGIN
61 config
.supports_gl_core_version
= 32;
63 config
.window_width
= W
;
64 config
.window_height
= H
;
65 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
66 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
68 PIGLIT_GL_TEST_CONFIG_END
70 struct image_test_info
{
74 /** Image qualifier keyword. */
75 const char *qualifier
;
77 /** Memory barrier built-in call. */
80 /** Informative "control" test likely to fail whose result is
85 const struct image_test_info image_tests
[] = {
86 { "control", "", "", true },
87 { "'coherent' qualifier", "coherent", "memoryBarrier()", false },
88 { "'volatile' qualifier", "volatile", "memoryBarrier()", false },
93 test_hunk(const struct image_test_info
*test
, unsigned k
)
97 (void)!asprintf(&s
, "#define IMAGE_Q %s\n"
98 "#define MEMORY_BARRIER() %s\n"
100 test
->qualifier
, test
->barrier
, k
);
105 init_image(const struct image_info img
)
107 uint32_t pixels
[N
] = { 0 };
109 return upload_image(img
, 0, pixels
);
113 check(const struct grid_info grid
)
117 return download_result(grid
, pixels
) &&
118 check_pixels(image_info_for_grid(grid
), pixels
, 33, 0, 0, 0);
122 run_test(const struct image_test_info
*test
,
123 const struct image_stage_info
*stage
,
126 const struct grid_info grid
=
127 grid_info(stage
->stage
, GL_R32UI
, W
, H
);
128 const struct image_info img
= image_info_for_grid(grid
);
129 GLuint prog
= generate_program(
131 concat(test_hunk(test
, k
),
133 hunk("IMAGE_Q IMAGE_UNIFORM_T img;\n"
135 "GRID_T op(ivec2 idx, GRID_T arg) {\n"
137 " * Shader invocations are classified into producers\n"
138 " * (check==false) and consumers (check==true), each\n"
139 " * producer being paired with a consumer K threads to\n"
142 " bool check = ((idx.x / K) % 2 == 1);\n"
143 " int x = (idx.x % K) + (idx.x / (2 * K)) * (2 * K);\n"
144 " int i, n = 1000;\n"
146 " for (i = 0; i < n; ++i) {\n"
151 " * Consumer: Monitor the evolution of a pair of\n"
152 " * image locations until the test runs to\n"
153 " * completion or an inconsistency is observed.\n"
155 " v = imageLoad(img, ivec2(x, idx.y)).x;\n"
156 " MEMORY_BARRIER();\n"
157 " u = imageLoad(img, ivec2(x + K, idx.y)).x;\n"
161 " return GRID_T(v << 16 | u, 0, 0, 1);\n"
164 " * Producer: Update the same pair of image locations\n"
165 " * sequentially with increasing values ordering the\n"
166 " * stores with a barrier.\n"
168 " imageStore(img, ivec2(x + K, idx.y), DATA_T(i));\n"
169 " MEMORY_BARRIER();\n"
170 " imageStore(img, ivec2(x, idx.y), DATA_T(i));\n"
175 " return GRID_T(33, 0, 0, 1);\n"
180 set_uniform_int(prog
, "img", 0) &&
181 draw_grid(grid
, prog
) &&
182 (check(grid
) || test
->control_test
);
184 glDeleteProgram(prog
);
189 piglit_init(int argc
, char **argv
)
191 const bool quick
= (argc
>= 2 && !strcmp(argv
[1], "--quick"));
192 const struct image_test_info
*test
;
193 const struct image_stage_info
*stage
;
194 enum piglit_result status
= PIGLIT_PASS
;
197 piglit_require_extension("GL_ARB_shader_image_load_store");
199 for (k
= 1; k
<= K
; k
*= (quick
? 4 : 2)) {
200 for (test
= image_tests
; test
->name
; ++test
) {
201 if (quick
&& test
->control_test
)
204 for (stage
= image_stages(); stage
->name
; ++stage
) {
205 subtest(&status
, true,
206 run_test(test
, stage
, k
),
207 "%s shader/%s memory barrier test"
209 stage
->name
, test
->name
, k
);
214 piglit_report_result(status
);