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 host-mem-barrier.c
26 * Unlike other GL API objects, images are not implicitly synchronized
27 * with subsequent GL operations. The glMemoryBarrier() API is provided
28 * to serialize shader memory transactions issued by previous drawing
29 * commands with respect to a given set of subsequent GL commands
30 * specified as a bit set.
32 * This test should cause several kinds of data hazard situations
33 * deliberately (RaW, WaR, WaW) between image loads and stores and other
34 * parts of the pipeline including vertex, element and indirect command
35 * fetch, shader uniform buffer, image and atomic counter access, texture
36 * sampling, pixel transfer operations, texture and buffer update
37 * commands, framebuffer writes and reads and transform feedback output.
39 * The test is repeated for different execution sizes to account for
40 * implementations with varying levels of parallelism and with caches
41 * of different sizes. Unless running in "quick" mode a series of
42 * control tests is executed which inhibits all glMemoryBarrier()
43 * calls in order to make sure that the test is leading to data
44 * hazards, since otherwise the main test is not meaningful. The
45 * control test always passes as it is expected to misrender.
50 /** Maximum image width. */
53 /** Maximum number of pixels. */
56 PIGLIT_GL_TEST_CONFIG_BEGIN
58 config
.supports_gl_core_version
= 32;
60 config
.window_width
= L
;
61 config
.window_height
= L
;
62 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
63 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
65 PIGLIT_GL_TEST_CONFIG_END
68 common_hunk(const struct image_info img
)
70 return concat(hunk("#extension GL_ARB_shader_atomic_counters : enable\n"),
72 hunk("#define RED DATA_T(1, 0, 0, 1)\n"
73 "#define GREEN DATA_T(0, 1, 0, 1)\n"
75 "IMAGE_UNIFORM_T src_img;\n"
76 "IMAGE_UNIFORM_T dst_img;\n"
77 "uniform int pass;\n"), NULL
);
80 struct image_barrier_info
{
84 /** Invoke a memory barrier affecting the specified units. */
85 bool (*run_barrier
)(GLbitfield barriers
);
87 /** Informative "control" test with no barriers whose result
93 run_barrier_none(GLbitfield barriers
)
99 run_barrier_one(GLbitfield barriers
)
101 glMemoryBarrier(barriers
);
102 return piglit_check_gl_error(GL_NO_ERROR
);
106 run_barrier_full(GLbitfield barriers
)
108 glMemoryBarrier(GL_ALL_BARRIER_BITS
);
109 return piglit_check_gl_error(GL_NO_ERROR
);
112 const struct image_barrier_info image_barriers
[] = {
113 { "control", run_barrier_none
, true },
114 { "one bit", run_barrier_one
, false },
115 { "full", run_barrier_full
, false },
120 check_fb_green(const struct grid_info grid
)
122 uint32_t pixels
[N
][4];
124 return download_result(grid
, pixels
[0]) &&
125 check_pixels(image_info_for_grid(grid
),
126 pixels
[0], 0, 1, 0, 1);
130 check_img_green(const struct image_info img
)
132 uint32_t pixels
[N
][4];
134 return download_image(img
, 1, pixels
[0]) &&
135 check_pixels(img
, pixels
[0], 0, 1, 0, 1);
139 init_common(const struct grid_info grid
, const struct image_info img
,
142 uint32_t pixels
[N
][4];
144 if (!init_pixels(img
, pixels
[0], 0, 1, 0, 1) ||
145 !upload_image(img
, 0, pixels
[0]) ||
146 !init_pixels(img
, pixels
[0], 66, 66, 66, 66) ||
147 !upload_image(img
, 1, pixels
[0]))
150 set_uniform_int(prog
, "src_img", 0);
151 set_uniform_int(prog
, "dst_img", 1);
152 set_uniform_int(prog
, "pass", 0);
154 return init_fb(grid
);
158 run_test_vertex_array_raw(const struct image_barrier_info
*bar
, unsigned l
)
160 const struct grid_info grid
=
161 grid_info(GL_VERTEX_SHADER
, GL_RGBA32F
, l
, l
);
162 const struct image_info img
=
163 image_info(GL_TEXTURE_BUFFER
, GL_RGBA32F
, l
, l
);
164 static GLuint vao
, vbo
;
165 GLuint prog
= generate_program(
166 grid
, GL_VERTEX_SHADER
,
167 concat(common_hunk(img
),
168 hunk("in vec4 piglit_texcoord;\n"
170 "GRID_T op(ivec2 idx, GRID_T x) {\n"
171 " if (pass == 1) {\n"
172 " return piglit_texcoord;\n"
174 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
178 bool ret
= prog
&& init_common(grid
, img
, prog
) &&
179 generate_grid_arrays(&vao
, &vbo
,
180 1.0 / l
- 1.0, 1.0 / l
- 1.0,
181 2.0 / l
, 2.0 / l
, l
, l
);
183 /* Bind the image as texcoord vbo simultaneously. */
184 glBindBuffer(GL_ARRAY_BUFFER
, get_buffer(1));
185 glVertexAttribPointer(PIGLIT_ATTRIB_TEX
, 4, GL_FLOAT
, GL_FALSE
,
187 glEnableVertexAttribArray(PIGLIT_ATTRIB_TEX
);
189 /* First pass: render green to the vbo. */
190 glDrawArrays(GL_POINTS
, 0, l
* l
);
193 bar
->run_barrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT
);
195 /* Second pass: check that the texcoords are all green
196 * (read-after-write). */
197 set_uniform_int(prog
, "pass", 1);
198 glDrawArrays(GL_POINTS
, 0, l
* l
);
200 ret
&= piglit_check_gl_error(GL_NO_ERROR
) &&
201 check_fb_green(grid
);
203 glDeleteProgram(prog
);
208 run_test_element_array_raw(const struct image_barrier_info
*bar
, unsigned l
)
210 const struct grid_info grid
=
211 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
212 const struct image_info img
=
213 image_info(GL_TEXTURE_BUFFER
, GL_R32UI
, l
, l
);
214 static GLuint vao
, vbo
;
215 GLuint prog
= generate_program(
216 grid
, GL_FRAGMENT_SHADER
,
217 concat(common_hunk(img
),
218 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
219 " if (pass == 1) {\n"
220 " return GRID_T(GREEN);\n"
222 " imageStore(dst_img, IMAGE_ADDR(idx),"
223 " DATA_T(IMAGE_ADDR(idx)));\n"
227 bool ret
= prog
&& init_common(grid
, img
, prog
) &&
228 generate_grid_arrays(&vao
, &vbo
,
229 1.0 / l
- 1.0, 1.0 / l
- 1.0,
230 2.0 / l
, 2.0 / l
, l
, l
);
232 /* Bind the image as element buffer simultaneously. */
233 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, get_buffer(1));
235 /* First pass: write sequential indices to the element buffer. */
236 glDrawArrays(GL_POINTS
, 0, l
* l
);
239 bar
->run_barrier(GL_ELEMENT_ARRAY_BARRIER_BIT
);
241 /* Second pass: render the generated element buffer
242 * (read-after-write). */
243 set_uniform_int(prog
, "pass", 1);
244 glDrawElements(GL_POINTS
, l
* l
, GL_UNSIGNED_INT
, 0);
246 ret
&= piglit_check_gl_error(GL_NO_ERROR
) &&
247 check_fb_green(grid
);
249 glDeleteProgram(prog
);
254 can_test_ubo_raw(void)
257 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE
, &size
);
258 return size
>= 16 * N
;
262 run_test_ubo_raw(const struct image_barrier_info
*bar
, unsigned l
)
264 const struct grid_info grid
=
265 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
266 const struct image_info img
=
267 image_info(GL_TEXTURE_BUFFER
, GL_RGBA32F
, l
, l
);
268 GLuint prog
= generate_program(
269 grid
, GL_FRAGMENT_SHADER
,
270 concat(common_hunk(img
),
271 hunk("layout(std140) uniform u {\n"
275 "GRID_T op(ivec2 idx, GRID_T x) {\n"
276 " if (pass == 1) {\n"
277 " return xs[IMAGE_ADDR(idx)];\n"
279 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
283 bool ret
= prog
&& init_common(grid
, img
, prog
);
285 /* Bind the image as uniform buffer simultaneously. */
286 glBindBufferBase(GL_UNIFORM_BUFFER
, 0, get_buffer(1));
288 /* First pass: render green to the uniform buffer. */
289 ret
&= draw_grid(grid
, prog
) &&
292 bar
->run_barrier(GL_UNIFORM_BARRIER_BIT
) &&
294 /* Second pass: check that the uniforms are all green
295 * (read-after-write). */
296 set_uniform_int(prog
, "pass", 1) &&
297 draw_grid(grid
, prog
) &&
298 check_fb_green(grid
);
300 glDeleteProgram(prog
);
305 run_test_tex_fetch_raw(const struct image_barrier_info
*bar
, unsigned l
)
307 const struct grid_info grid
=
308 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
309 const struct image_info img
=
310 image_info(GL_TEXTURE_2D
, GL_RGBA32F
, l
, l
);
311 GLuint prog
= generate_program(
312 grid
, GL_FRAGMENT_SHADER
,
313 concat(common_hunk(img
),
314 hunk("uniform sampler2D tex;\n"
316 "GRID_T op(ivec2 idx, GRID_T x) {\n"
317 " if (pass == 1) {\n"
318 " return texelFetch(tex, idx, 0);\n"
320 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
324 bool ret
= prog
&& init_common(grid
, img
, prog
);
326 /* Bind the image as texture simultaneously. */
327 glActiveTexture(GL_TEXTURE0
);
328 glBindTexture(GL_TEXTURE_2D
, get_texture(1));
329 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
330 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
332 /* First pass: render green to the texture. */
333 ret
&= draw_grid(grid
, prog
) &&
336 bar
->run_barrier(GL_TEXTURE_FETCH_BARRIER_BIT
) &&
337 set_uniform_int(prog
, "pass", 1) &&
339 /* Second pass: check that the texture is green
340 * (read-after-write). */
341 draw_grid(grid
, prog
) &&
342 check_fb_green(grid
);
344 glDeleteProgram(prog
);
349 run_test_image_raw(const struct image_barrier_info
*bar
, unsigned l
)
351 const struct grid_info grid
=
352 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
353 const struct image_info img
=
354 image_info(GL_TEXTURE_2D
, GL_RGBA32F
, l
, l
);
355 GLuint prog
= generate_program(
356 grid
, GL_FRAGMENT_SHADER
,
357 concat(common_hunk(img
),
358 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
359 " if (pass == 1) {\n"
360 " return imageLoad(dst_img, IMAGE_ADDR(idx));\n"
362 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
366 bool ret
= prog
&& init_common(grid
, img
, prog
) &&
368 /* First pass: render green to the image. */
369 draw_grid(grid
, prog
) &&
372 bar
->run_barrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
) &&
374 /* Second pass: check that the image is green
375 * (read-after-write). */
376 set_uniform_int(prog
, "pass", 1) &&
377 draw_grid(grid
, prog
) &&
378 check_fb_green(grid
);
380 glDeleteProgram(prog
);
385 run_test_image_war(const struct image_barrier_info
*bar
, unsigned l
)
387 const struct grid_info grid
=
388 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
389 const struct image_info img
=
390 image_info(GL_TEXTURE_2D
, GL_RGBA32F
, l
, l
);
391 GLuint prog
= generate_program(
392 grid
, GL_FRAGMENT_SHADER
,
393 concat(common_hunk(img
),
394 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
395 " if (pass == 1) {\n"
396 " imageStore(src_img, IMAGE_ADDR(idx), RED);\n"
398 " imageStore(dst_img, IMAGE_ADDR(idx),"
399 " imageLoad(src_img, IMAGE_ADDR(idx)));\n"
403 bool ret
= prog
&& init_common(grid
, img
, prog
) &&
405 /* First pass: read back the source image. */
406 draw_grid(grid
, prog
) &&
409 bar
->run_barrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
) &&
411 /* Second pass: render red to the source image
412 * (write-after-read). */
413 set_uniform_int(prog
, "pass", 1) &&
414 draw_grid(grid
, prog
) &&
416 /* Check that the read-back results from the first
418 check_img_green(img
);
420 glDeleteProgram(prog
);
425 run_test_indirect_raw(const struct image_barrier_info
*bar
, unsigned l
)
427 const struct grid_info grid
=
428 grid_info(GL_VERTEX_SHADER
, GL_RGBA32F
, l
, l
);
429 const struct image_info img
=
430 image_info(GL_TEXTURE_BUFFER
, GL_RGBA32UI
, l
, l
);
431 static GLuint vao
, vbo
;
432 GLuint prog
= generate_program(
433 grid
, GL_VERTEX_SHADER
,
434 concat(common_hunk(img
),
435 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
436 " if (pass == 1) {\n"
437 " return GRID_T(gl_InstanceID == 2 ? GREEN : RED);\n"
439 " imageStore(dst_img, IMAGE_ADDR(idx),"
440 " DATA_T(1, 3, IMAGE_ADDR(idx), 0));\n"
444 bool ret
= prog
&& init_common(grid
, img
, prog
) &&
445 generate_grid_arrays(&vao
, &vbo
,
446 1.0 / l
- 1.0, 1.0 / l
- 1.0,
447 2.0 / l
, 2.0 / l
, l
, l
);
449 /* Bind the image as indirect command buffer
451 glBindBuffer(GL_DRAW_INDIRECT_BUFFER
, get_buffer(1));
453 /* First pass: Render instanced draw commands to the indirect
455 glDrawArrays(GL_POINTS
, 0, l
* l
);
458 bar
->run_barrier(GL_COMMAND_BARRIER_BIT
);
460 /* Second pass: render the generated indirect buffer
461 * (read-after-write). */
462 set_uniform_int(prog
, "pass", 1);
463 glMultiDrawArraysIndirect(GL_POINTS
, 0, l
* l
, 0);
465 ret
&= piglit_check_gl_error(GL_NO_ERROR
) &&
466 check_fb_green(grid
);
468 glDeleteProgram(prog
);
473 run_test_pixel_raw(const struct image_barrier_info
*bar
, unsigned l
)
475 const struct grid_info grid
=
476 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
477 const struct image_info img
=
478 image_info(GL_TEXTURE_BUFFER
, GL_RGBA32F
, l
, l
);
479 GLuint prog
= generate_program(
480 grid
, GL_FRAGMENT_SHADER
,
481 concat(common_hunk(img
),
482 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
483 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
486 bool ret
= prog
&& init_common(grid
, img
, prog
);
487 uint32_t pixels
[N
][4];
490 /* Bind the image as pixel unpack buffer simultaneously. */
491 glGenTextures(1, &tex
);
492 glBindTexture(GL_TEXTURE_2D
, tex
);
493 glBindBuffer(GL_PIXEL_UNPACK_BUFFER
, get_buffer(1));
495 /* First pass: render green to the image. */
496 draw_grid(grid
, prog
);
499 bar
->run_barrier(GL_PIXEL_BUFFER_BARRIER_BIT
);
501 /* Second pass: use the result as pixel source
502 * (read-after-write). */
503 glTexImage2D(GL_TEXTURE_2D
, 0, img
.format
->format
,
504 l
, l
, 0, img
.format
->pixel_format
,
505 img
.format
->pixel_type
, 0);
506 glBindBuffer(GL_PIXEL_UNPACK_BUFFER
, 0);
508 /* Check that the resulting texture is green. */
509 glGetTexImage(GL_TEXTURE_2D
, 0, img
.format
->pixel_format
,
510 image_base_type(img
.format
), pixels
);
512 ret
&= piglit_check_gl_error(GL_NO_ERROR
) &&
513 check_pixels(img
, pixels
[0], 0, 1, 0, 1);
515 glDeleteTextures(1, &tex
);
516 glDeleteProgram(prog
);
521 run_test_pixel_waw(const struct image_barrier_info
*bar
, unsigned l
)
523 const struct grid_info grid
=
524 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
525 const struct image_info img
=
526 image_info(GL_TEXTURE_BUFFER
, GL_RGBA32F
, l
, l
);
527 GLuint prog
= generate_program(
528 grid
, GL_FRAGMENT_SHADER
,
529 concat(common_hunk(img
),
530 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
531 " imageStore(dst_img, IMAGE_ADDR(idx), RED);\n"
534 bool ret
= prog
&& init_common(grid
, img
, prog
);
535 uint32_t pixels
[N
][4];
538 init_pixels(img
, pixels
[0], 0, 1, 0, 1);
540 glGenTextures(1, &tex
);
541 glBindTexture(GL_TEXTURE_2D
, tex
);
542 glTexImage2D(GL_TEXTURE_2D
, 0, img
.format
->format
,
543 l
, l
, 0, img
.format
->pixel_format
,
544 image_base_type(img
.format
), pixels
);
546 /* Bind the image as pixel pack buffer simultaneously. */
547 glBindBuffer(GL_PIXEL_PACK_BUFFER
, get_buffer(1));
549 /* First pass: render red to the image. */
550 draw_grid(grid
, prog
);
553 bar
->run_barrier(GL_PIXEL_BUFFER_BARRIER_BIT
);
555 /* Second pass: use the image as pixel destination filling it
556 * with green (write-after-write). */
557 glGetTexImage(GL_TEXTURE_2D
, 0, img
.format
->pixel_format
,
558 img
.format
->pixel_type
, 0);
559 glBindBuffer(GL_PIXEL_PACK_BUFFER
, 0);
561 /* Check that the resulting image is green. */
562 ret
&= piglit_check_gl_error(GL_NO_ERROR
) &&
563 check_img_green(img
);
565 glDeleteTextures(1, &tex
);
566 glDeleteProgram(prog
);
571 run_test_tex_update_raw(const struct image_barrier_info
*bar
, unsigned l
)
573 const struct grid_info grid
=
574 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
575 const struct image_info img
=
576 image_info(GL_TEXTURE_2D
, GL_RGBA32F
, l
, l
);
577 GLuint prog
= generate_program(
578 grid
, GL_FRAGMENT_SHADER
,
579 concat(common_hunk(img
),
580 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
581 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
584 bool ret
= prog
&& init_common(grid
, img
, prog
);
585 uint32_t pixels
[N
][4];
587 glBindTexture(GL_TEXTURE_2D
, get_texture(1));
589 /* First pass: render green to the image. */
590 draw_grid(grid
, prog
);
593 bar
->run_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT
);
595 /* Read back the result (read-after-write). */
596 glGetTexImage(GL_TEXTURE_2D
, 0, img
.format
->pixel_format
,
597 image_base_type(img
.format
), pixels
);
599 ret
&= piglit_check_gl_error(GL_NO_ERROR
) &&
600 check_pixels(img
, pixels
[0], 0, 1, 0, 1);
602 glDeleteProgram(prog
);
607 run_test_tex_update_waw(const struct image_barrier_info
*bar
, unsigned l
)
609 const struct grid_info grid
=
610 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
611 const struct image_info img
=
612 image_info(GL_TEXTURE_2D
, GL_RGBA32F
, l
, l
);
613 GLuint prog
= generate_program(
614 grid
, GL_FRAGMENT_SHADER
,
615 concat(common_hunk(img
),
616 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
617 " imageStore(dst_img, IMAGE_ADDR(idx),"
618 " (idx.y >= H / 2 ? GREEN : RED));\n"
621 bool ret
= prog
&& init_common(grid
, img
, prog
);
622 uint32_t pixels
[N
][4];
624 init_pixels(set_image_size(img
, l
, l
/ 2, 1, 1),
625 pixels
[0], 0, 1, 0, 1);
627 glBindTexture(GL_TEXTURE_2D
, get_texture(1));
629 /* First pass: render red to the first half of the image,
630 * green to the second half. */
631 draw_grid(grid
, prog
);
634 bar
->run_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT
);
636 /* Fill the first half with green (write-after-write). */
637 glTexSubImage2D(GL_TEXTURE_2D
, 0, 0, 0, l
, l
/ 2,
638 img
.format
->pixel_format
, image_base_type(img
.format
),
641 /* Check that the resulting image is green. */
642 ret
&= piglit_check_gl_error(GL_NO_ERROR
) &&
643 check_img_green(img
);
645 glDeleteProgram(prog
);
650 run_test_buf_update_raw(const struct image_barrier_info
*bar
, unsigned l
)
652 const struct grid_info grid
=
653 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
654 const struct image_info img
=
655 image_info(GL_TEXTURE_BUFFER
, GL_RGBA32F
, l
, l
);
656 GLuint prog
= generate_program(
657 grid
, GL_FRAGMENT_SHADER
,
658 concat(common_hunk(img
),
659 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
660 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
663 bool ret
= prog
&& init_common(grid
, img
, prog
);
664 uint32_t pixels
[N
][4];
666 glBindBuffer(GL_TEXTURE_BUFFER
, get_buffer(1));
668 /* First pass: render green to the image. */
669 draw_grid(grid
, prog
);
672 bar
->run_barrier(GL_BUFFER_UPDATE_BARRIER_BIT
);
674 /* Read back the result (read-after-write). */
675 glGetBufferSubData(GL_TEXTURE_BUFFER
, 0,
676 4 * l
* l
* sizeof(uint32_t), pixels
[0]);
678 ret
&= piglit_check_gl_error(GL_NO_ERROR
) &&
679 check_pixels(img
, pixels
[0], 0, 1, 0, 1);
681 glDeleteProgram(prog
);
686 run_test_buf_update_waw(const struct image_barrier_info
*bar
, unsigned l
)
688 const struct grid_info grid
=
689 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
690 const struct image_info img
=
691 image_info(GL_TEXTURE_BUFFER
, GL_RGBA32F
, l
, l
);
692 GLuint prog
= generate_program(
693 grid
, GL_FRAGMENT_SHADER
,
694 concat(common_hunk(img
),
695 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
696 " imageStore(dst_img, IMAGE_ADDR(idx),"
697 " (idx.y >= H / 2 ? GREEN : RED));\n"
700 bool ret
= prog
&& init_common(grid
, img
, prog
);
701 uint32_t pixels
[N
][4];
703 init_pixels(set_image_size(img
, l
* l
/ 2, 1, 1, 1),
704 pixels
[0], 0, 1, 0, 1);
705 glBindBuffer(GL_TEXTURE_BUFFER
, get_buffer(1));
707 /* First pass: render red to the first half of the image,
708 * green to the second half. */
709 draw_grid(grid
, prog
);
712 bar
->run_barrier(GL_BUFFER_UPDATE_BARRIER_BIT
);
714 /* Fill the first half with green (write-after-write). */
715 glBufferSubData(GL_TEXTURE_BUFFER
, 0, 4 * l
* l
/ 2 * sizeof(uint32_t),
718 /* Check that the resulting image is green. */
719 ret
&= piglit_check_gl_error(GL_NO_ERROR
) &&
720 check_img_green(img
);
722 glDeleteProgram(prog
);
727 run_test_fb_raw(const struct image_barrier_info
*bar
, unsigned l
)
729 const struct grid_info grid
=
730 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
731 const struct image_info img
=
732 image_info(GL_TEXTURE_2D
, GL_RGBA32F
, l
, l
);
733 GLuint prog
= generate_program(
734 grid
, GL_FRAGMENT_SHADER
,
735 concat(common_hunk(img
),
736 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
737 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
740 bool ret
= prog
&& init_common(grid
, img
, prog
);
741 uint32_t pixels
[N
][4];
744 glGenFramebuffers(1, &fb
);
745 glBindFramebuffer(GL_READ_FRAMEBUFFER
, fb
);
747 /* Bind the image as color attachment of the read framebuffer
749 glFramebufferTexture(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
752 /* First pass: render green to the image. */
753 draw_grid(grid
, prog
);
756 bar
->run_barrier(GL_FRAMEBUFFER_BARRIER_BIT
);
758 /* Read back and check the result from the read
759 * framebuffer (read-after-write). */
760 glReadPixels(0, 0, l
, l
, img
.format
->pixel_format
,
761 image_base_type(img
.format
), pixels
);
763 ret
&= piglit_check_gl_error(GL_NO_ERROR
) &&
764 check_pixels(img
, pixels
[0], 0, 1, 0, 1);
766 glDeleteFramebuffers(1, &fb
);
767 glDeleteProgram(prog
);
772 run_test_fb_waw(const struct image_barrier_info
*bar
, unsigned l
)
774 const struct grid_info grid
=
775 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
776 const struct image_info img
=
777 image_info(GL_TEXTURE_2D
, GL_RGBA32F
, l
, l
);
778 GLuint prog
= generate_program(
779 grid
, GL_FRAGMENT_SHADER
,
780 concat(common_hunk(img
),
781 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
782 " if (pass == 1) {\n"
785 " imageStore(dst_img, IMAGE_ADDR(idx), RED);\n"
789 bool ret
= prog
&& init_common(grid
, img
, prog
);
792 glGenFramebuffers(1, &fb
);
793 glBindFramebuffer(GL_DRAW_FRAMEBUFFER
, fb
);
795 /* Bind the image as color attachment of the framebuffer
797 glFramebufferTexture(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
800 /* First pass: render red to the image. */
801 ret
&= draw_grid(grid
, prog
) &&
804 bar
->run_barrier(GL_FRAMEBUFFER_BARRIER_BIT
) &&
806 /* Second pass: render green to the framebuffer
807 * (write-after-write). */
808 set_uniform_int(prog
, "pass", 1) &&
809 draw_grid(grid
, prog
) &&
811 /* Check that the resulting image is green. */
812 check_img_green(img
);
814 glDeleteFramebuffers(1, &fb
);
815 glDeleteProgram(prog
);
820 setup_xfb_varying(GLuint prog
, const char *varying
)
822 glTransformFeedbackVaryings(prog
, 1, &varying
, GL_INTERLEAVED_ATTRIBS
);
825 return piglit_check_gl_error(GL_NO_ERROR
);
829 run_test_xfb_waw(const struct image_barrier_info
*bar
, unsigned l
)
831 const struct grid_info grid
=
832 grid_info(GL_VERTEX_SHADER
, GL_RGBA32F
, l
, l
);
833 const struct image_info img
=
834 image_info(GL_TEXTURE_BUFFER
, GL_RGBA32F
, l
, l
);
835 GLuint prog
= generate_program(
836 grid
, GL_VERTEX_SHADER
,
837 concat(common_hunk(img
),
838 hunk("GRID_T op(ivec2 idx, GRID_T x) {\n"
839 " if (pass == 1) {\n"
842 " imageStore(dst_img, IMAGE_ADDR(idx), RED);\n"
846 bool ret
= prog
&& setup_xfb_varying(prog
, "vcolor") &&
847 init_common(grid
, img
, prog
);
850 glGenTransformFeedbacks(1, &xfb
);
851 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK
, xfb
);
853 /* Bind the image as transform feedback buffer
855 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER
, 0, get_buffer(1));
856 glBeginTransformFeedback(GL_POINTS
);
857 glPauseTransformFeedback();
859 /* First pass: render red to the image. */
860 draw_grid(grid
, prog
);
863 bar
->run_barrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT
);
865 /* Second pass: Write out the vcolor output to the transform
866 * feedback buffer (write-after-write). */
867 set_uniform_int(prog
, "pass", 1);
868 glResumeTransformFeedback();
869 draw_grid(grid
, prog
);
870 glEndTransformFeedback();
872 /* Check that the resulting image is green. */
873 ret
&= piglit_check_gl_error(GL_NO_ERROR
) &&
874 check_img_green(img
);
876 glDeleteTransformFeedbacks(1, &xfb
);
877 glDeleteProgram(prog
);
882 run_test_atom_raw(const struct image_barrier_info
*bar
, unsigned l
)
884 const struct grid_info grid
=
885 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
886 const struct image_info img
=
887 image_info(GL_TEXTURE_BUFFER
, GL_RGBA32UI
, l
, l
);
888 GLuint prog
= generate_program(
889 grid
, GL_FRAGMENT_SHADER
,
890 concat(common_hunk(img
),
891 hunk("layout(binding=0, offset=0) uniform atomic_uint c[4];\n"
893 "GRID_T op(ivec2 idx, GRID_T x) {\n"
894 " if (pass == 1) {\n"
895 " return GRID_T(atomicCounter(c[0]),"
896 " atomicCounter(c[1]),"
897 " atomicCounter(c[2]),"
898 " atomicCounter(c[3]));\n"
900 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
904 bool ret
= prog
&& init_common(grid
, img
, prog
);
906 /* Bind the image as atomic counter buffer simultaneously. */
907 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER
, 0, get_buffer(1));
909 /* First pass: render green to the image. */
910 ret
&= draw_grid(grid
, prog
) &&
913 bar
->run_barrier(GL_ATOMIC_COUNTER_BARRIER_BIT
) &&
915 /* Second pass: Check that the atomic counters read
916 * back green (read-after-write). */
917 set_uniform_int(prog
, "pass", 1) &&
918 draw_grid(grid
, prog
) &&
919 check_fb_green(grid
);
921 glDeleteProgram(prog
);
926 run_test_atom_war(const struct image_barrier_info
*bar
, unsigned l
)
928 const struct grid_info grid
=
929 grid_info(GL_FRAGMENT_SHADER
, GL_RGBA32F
, l
, l
);
930 const struct image_info img
=
931 image_info(GL_TEXTURE_BUFFER
, GL_RGBA32UI
, l
, l
);
932 GLuint prog
= generate_program(
933 grid
, GL_FRAGMENT_SHADER
,
934 concat(common_hunk(img
),
935 hunk("layout(binding=0, offset=0) uniform atomic_uint c[4];\n"
937 "GRID_T op(ivec2 idx, GRID_T x) {\n"
938 " if (pass == 1) {\n"
939 " atomicCounterIncrement(c[0]);"
940 " atomicCounterIncrement(c[1]);"
941 " atomicCounterIncrement(c[2]);"
942 " atomicCounterIncrement(c[3]);\n"
944 " imageStore(dst_img, IMAGE_ADDR(idx),"
945 " imageLoad(src_img, IMAGE_ADDR(idx)));\n"
949 bool ret
= prog
&& init_common(grid
, img
, prog
);
951 /* Bind the image as atomic counter buffer simultaneously. */
952 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER
, 0, get_buffer(0));
954 /* First pass: read back the source image. */
955 ret
&= draw_grid(grid
, prog
) &&
958 bar
->run_barrier(GL_ATOMIC_COUNTER_BARRIER_BIT
) &&
960 /* Second pass: Modify the source image using atomic
961 * counter increments (write-after-read). */
962 set_uniform_int(prog
, "pass", 1) &&
963 draw_grid(grid
, prog
) &&
965 /* Check that the read-back results from the first
967 check_img_green(img
);
969 glDeleteProgram(prog
);
974 barrier_subtest(enum piglit_result
*status
, bool guard
,
975 bool (*run
)(const struct image_barrier_info
*, unsigned),
976 const char *name
, const struct image_barrier_info
*bar
,
979 subtest(status
, guard
, run(bar
, l
) || bar
->control_test
,
980 "%s/%s barrier test/%dx%d", name
, bar
->name
, l
, l
);
984 piglit_init(int argc
, char **argv
)
986 const bool quick
= (argc
>= 2 && !strcmp(argv
[1], "--quick"));
987 const struct image_barrier_info
*bar
;
988 enum piglit_result status
= PIGLIT_PASS
;
991 piglit_require_extension("GL_ARB_shader_image_load_store");
992 piglit_require_extension("GL_ARB_shader_atomic_counters");
994 for (l
= 4; l
<= L
; l
*= 4) {
995 for (bar
= image_barriers
; bar
->name
; ++bar
) {
996 if (quick
&& bar
->control_test
)
999 barrier_subtest(&status
,
1000 get_image_stage(GL_VERTEX_SHADER
),
1001 run_test_vertex_array_raw
,
1002 "Vertex array/RaW", bar
, l
);
1004 barrier_subtest(&status
, true, run_test_element_array_raw
,
1005 "Element array/RaW", bar
, l
);
1007 barrier_subtest(&status
, can_test_ubo_raw(),
1009 "Uniform buffer/RaW", bar
, l
);
1011 barrier_subtest(&status
, true, run_test_tex_fetch_raw
,
1012 "Texture fetch/RaW", bar
, l
);
1014 barrier_subtest(&status
, true, run_test_image_raw
,
1015 "Image/RaW", bar
, l
);
1017 barrier_subtest(&status
, true, run_test_image_war
,
1018 "Image/WaR", bar
, l
);
1020 barrier_subtest(&status
,
1021 (get_image_stage(GL_VERTEX_SHADER
) &&
1022 piglit_is_extension_supported(
1023 "GL_ARB_draw_indirect")),
1024 run_test_indirect_raw
,
1025 "Indirect/RaW", bar
, l
);
1027 barrier_subtest(&status
, true, run_test_pixel_raw
,
1028 "Pixel/RaW", bar
, l
);
1030 barrier_subtest(&status
, true, run_test_pixel_waw
,
1031 "Pixel/WaW", bar
, l
);
1033 barrier_subtest(&status
, true, run_test_tex_update_raw
,
1034 "Texture update/RaW", bar
, l
);
1036 barrier_subtest(&status
, true, run_test_tex_update_waw
,
1037 "Texture update/WaW", bar
, l
);
1039 barrier_subtest(&status
, true, run_test_buf_update_raw
,
1040 "Buffer update/RaW", bar
, l
);
1042 barrier_subtest(&status
, true, run_test_buf_update_waw
,
1043 "Buffer update/WaW", bar
, l
);
1045 barrier_subtest(&status
, true, run_test_fb_raw
,
1046 "Framebuffer/RaW", bar
, l
);
1048 barrier_subtest(&status
, true, run_test_fb_waw
,
1049 "Framebuffer/WaW", bar
, l
);
1051 barrier_subtest(&status
,
1052 (get_image_stage(GL_VERTEX_SHADER
) &&
1053 piglit_is_extension_supported(
1054 "GL_ARB_transform_feedback2")),
1056 "Transform feedback/WaW", bar
, l
);
1058 barrier_subtest(&status
, true, run_test_atom_raw
,
1059 "Atomic counter/RaW", bar
, l
);
1061 barrier_subtest(&status
, true, run_test_atom_war
,
1062 "Atomic counter/WaR", bar
, l
);
1066 piglit_report_result(status
);
1070 piglit_display(void)