ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / arb_shader_image_load_store / host-mem-barrier.c
blobcceaf28ca9df09775019d7b17e2ddd75f80ce91f
1 /*
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
13 * Software.
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
21 * IN THE SOFTWARE.
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.
48 #include "common.h"
50 /** Maximum image width. */
51 #define L 64
53 /** Maximum number of pixels. */
54 #define N (L * L)
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
67 static char *
68 common_hunk(const struct image_info img)
70 return concat(hunk("#extension GL_ARB_shader_atomic_counters : enable\n"),
71 image_hunk(img, ""),
72 hunk("#define RED DATA_T(1, 0, 0, 1)\n"
73 "#define GREEN DATA_T(0, 1, 0, 1)\n"
74 "\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 {
81 /** Test name. */
82 const char *name;
84 /** Invoke a memory barrier affecting the specified units. */
85 bool (*run_barrier)(GLbitfield barriers);
87 /** Informative "control" test with no barriers whose result
88 * is ignored. */
89 bool control_test;
92 static bool
93 run_barrier_none(GLbitfield barriers)
95 return true;
98 static bool
99 run_barrier_one(GLbitfield barriers)
101 glMemoryBarrier(barriers);
102 return piglit_check_gl_error(GL_NO_ERROR);
105 static bool
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 },
116 { 0 }
119 static bool
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);
129 static bool
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);
138 static bool
139 init_common(const struct grid_info grid, const struct image_info img,
140 GLuint prog)
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]))
148 return false;
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);
157 static bool
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"
169 "\n"
170 "GRID_T op(ivec2 idx, GRID_T x) {\n"
171 " if (pass == 1) {\n"
172 " return piglit_texcoord;\n"
173 " } else {\n"
174 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
175 " return x;\n"
176 " }\n"
177 "}\n"), NULL));
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,
186 0, 0);
187 glEnableVertexAttribArray(PIGLIT_ATTRIB_TEX);
189 /* First pass: render green to the vbo. */
190 glDrawArrays(GL_POINTS, 0, l * l);
192 /* Barrier. */
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);
204 return ret;
207 static bool
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"
221 " } else {\n"
222 " imageStore(dst_img, IMAGE_ADDR(idx),"
223 " DATA_T(IMAGE_ADDR(idx)));\n"
224 " return x;\n"
225 " }\n"
226 "}\n"), NULL));
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);
238 /* Barrier. */
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);
250 return ret;
253 static bool
254 can_test_ubo_raw(void)
256 int size = 0;
257 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &size);
258 return size >= 16 * N;
261 static bool
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"
272 " vec4 xs[N];\n"
273 "};\n"
274 "\n"
275 "GRID_T op(ivec2 idx, GRID_T x) {\n"
276 " if (pass == 1) {\n"
277 " return xs[IMAGE_ADDR(idx)];\n"
278 " } else {\n"
279 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
280 " return x;\n"
281 " }\n"
282 "}\n"), NULL));
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) &&
291 /* Barrier. */
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);
301 return ret;
304 static bool
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"
315 "\n"
316 "GRID_T op(ivec2 idx, GRID_T x) {\n"
317 " if (pass == 1) {\n"
318 " return texelFetch(tex, idx, 0);\n"
319 " } else {\n"
320 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
321 " return x;\n"
322 " }\n"
323 "}\n"), NULL));
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) &&
335 /* Barrier. */
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);
345 return ret;
348 static bool
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"
361 " } else {\n"
362 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
363 " return x;\n"
364 " }\n"
365 "}\n"), NULL));
366 bool ret = prog && init_common(grid, img, prog) &&
368 /* First pass: render green to the image. */
369 draw_grid(grid, prog) &&
371 /* Barrier. */
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);
381 return ret;
384 static bool
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"
397 " } else {\n"
398 " imageStore(dst_img, IMAGE_ADDR(idx),"
399 " imageLoad(src_img, IMAGE_ADDR(idx)));\n"
400 " }\n"
401 " return x;\n"
402 "}\n"), NULL));
403 bool ret = prog && init_common(grid, img, prog) &&
405 /* First pass: read back the source image. */
406 draw_grid(grid, prog) &&
408 /* Barrier. */
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
417 * pass are green. */
418 check_img_green(img);
420 glDeleteProgram(prog);
421 return ret;
424 static bool
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"
438 " } else {\n"
439 " imageStore(dst_img, IMAGE_ADDR(idx),"
440 " DATA_T(1, 3, IMAGE_ADDR(idx), 0));\n"
441 " return x;\n"
442 " }\n"
443 "}\n"), NULL));
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
450 * simultaneously. */
451 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, get_buffer(1));
453 /* First pass: Render instanced draw commands to the indirect
454 * buffer. */
455 glDrawArrays(GL_POINTS, 0, l * l);
457 /* Barrier. */
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);
469 return ret;
472 static bool
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"
484 " return x;\n"
485 "}\n"), NULL));
486 bool ret = prog && init_common(grid, img, prog);
487 uint32_t pixels[N][4];
488 GLuint tex;
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);
498 /* Barrier. */
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);
517 return ret;
520 static bool
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"
532 " return x;\n"
533 "}\n"), NULL));
534 bool ret = prog && init_common(grid, img, prog);
535 uint32_t pixels[N][4];
536 GLuint tex;
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);
552 /* Barrier. */
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);
567 return ret;
570 static bool
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"
582 " return x;\n"
583 "}\n"), NULL));
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);
592 /* Barrier. */
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);
603 return ret;
606 static bool
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"
619 " return x;\n"
620 "}\n"), NULL));
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);
633 /* Barrier. */
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),
639 pixels);
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);
646 return ret;
649 static bool
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"
661 " return x;\n"
662 "}\n"), NULL));
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);
671 /* Barrier. */
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);
682 return ret;
685 static bool
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"
698 " return x;\n"
699 "}\n"), NULL));
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);
711 /* Barrier. */
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),
716 pixels);
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);
723 return ret;
726 static bool
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"
738 " return x;\n"
739 "}\n"), NULL));
740 bool ret = prog && init_common(grid, img, prog);
741 uint32_t pixels[N][4];
742 GLuint fb;
744 glGenFramebuffers(1, &fb);
745 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
747 /* Bind the image as color attachment of the read framebuffer
748 * simultaneously. */
749 glFramebufferTexture(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
750 get_texture(1), 0);
752 /* First pass: render green to the image. */
753 draw_grid(grid, prog);
755 /* Barrier. */
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);
768 return ret;
771 static bool
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"
783 " return GREEN;"
784 " } else {\n"
785 " imageStore(dst_img, IMAGE_ADDR(idx), RED);\n"
786 " return RED;\n"
787 " }\n"
788 "}\n"), NULL));
789 bool ret = prog && init_common(grid, img, prog);
790 GLuint fb;
792 glGenFramebuffers(1, &fb);
793 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb);
795 /* Bind the image as color attachment of the framebuffer
796 * simultaneously. */
797 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
798 get_texture(1), 0);
800 /* First pass: render red to the image. */
801 ret &= draw_grid(grid, prog) &&
803 /* Barrier. */
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);
816 return ret;
819 static bool
820 setup_xfb_varying(GLuint prog, const char *varying)
822 glTransformFeedbackVaryings(prog, 1, &varying, GL_INTERLEAVED_ATTRIBS);
823 glLinkProgram(prog);
825 return piglit_check_gl_error(GL_NO_ERROR);
828 static bool
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"
840 " return GREEN;\n"
841 " } else {\n"
842 " imageStore(dst_img, IMAGE_ADDR(idx), RED);\n"
843 " return x;\n"
844 " }\n"
845 "}\n"), NULL));
846 bool ret = prog && setup_xfb_varying(prog, "vcolor") &&
847 init_common(grid, img, prog);
848 GLuint xfb;
850 glGenTransformFeedbacks(1, &xfb);
851 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
853 /* Bind the image as transform feedback buffer
854 * simultaneously. */
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);
862 /* Barrier. */
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);
878 return ret;
881 static bool
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"
892 "\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"
899 " } else {\n"
900 " imageStore(dst_img, IMAGE_ADDR(idx), GREEN);\n"
901 " return x;\n"
902 " }\n"
903 "}\n"), NULL));
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) &&
912 /* Barrier. */
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);
922 return ret;
925 static bool
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"
936 "\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"
943 " } else {\n"
944 " imageStore(dst_img, IMAGE_ADDR(idx),"
945 " imageLoad(src_img, IMAGE_ADDR(idx)));\n"
946 " }\n"
947 " return x;\n"
948 "}\n"), NULL));
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) &&
957 /* Barrier. */
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
966 * pass are green. */
967 check_img_green(img);
969 glDeleteProgram(prog);
970 return ret;
973 static void
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,
977 unsigned l)
979 subtest(status, guard, run(bar, l) || bar->control_test,
980 "%s/%s barrier test/%dx%d", name, bar->name, l, l);
983 void
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;
989 unsigned l;
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)
997 continue;
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(),
1008 run_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")),
1055 run_test_xfb_waw,
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);
1069 enum piglit_result
1070 piglit_display(void)
1072 return PIGLIT_FAIL;