Jordan Justen <jordan.l.jus...@intel.com> writes: > 8-10 and 21 Reviewed-by: Jordan Justen <jordan.l.jus...@intel.com> > > These are some challenging tests to review, but they seem very > thorough. > > For the rest, I think you should proceed with your plan and commit > them without an r-b. > Thank you Jordan, I've added your R-b tags and pushed the series.
> -Jordan > > On 2015-01-31 07:41:32, Francisco Jerez wrote: >> Add tests for the glMemoryBarrier() API which provides a way to >> serialize shader memory transactions issued by previous drawing >> commands with respect to subsequent GL commands. >> >> v2: Skip indirect draw and transform feedback tests when the >> extensions they rely on are not supported. >> --- >> tests/all.py | 1 + >> tests/quick.py | 1 + >> .../arb_shader_image_load_store/CMakeLists.gl.txt | 1 + >> .../arb_shader_image_load_store/host-mem-barrier.c | 1063 >> ++++++++++++++++++++ >> 4 files changed, 1066 insertions(+) >> create mode 100644 tests/spec/arb_shader_image_load_store/host-mem-barrier.c >> >> diff --git a/tests/all.py b/tests/all.py >> index 0e8101f..041bac8 100644 >> --- a/tests/all.py >> +++ b/tests/all.py >> @@ -4431,6 +4431,7 @@ arb_shader_image_load_store['bitcast'] = >> PiglitGLTest('arb_shader_image_load_sto >> arb_shader_image_load_store['coherency'] = >> PiglitGLTest('arb_shader_image_load_store-coherency', run_concurrent=True) >> arb_shader_image_load_store['dead-fragments'] = >> PiglitGLTest('arb_shader_image_load_store-dead-fragments', >> run_concurrent=True) >> arb_shader_image_load_store['early-z'] = >> PiglitGLTest('arb_shader_image_load_store-early-z', run_concurrent=True) >> +arb_shader_image_load_store['host-mem-barrier'] = >> PiglitGLTest('arb_shader_image_load_store-host-mem-barrier', >> 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 2f0d690..72b3b19 100644 >> --- a/tests/quick.py >> +++ b/tests/quick.py >> @@ -14,3 +14,4 @@ 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"] >> +profile.tests['spec']['ARB_shader_image_load_store']['host-mem-barrier'].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 874afac..814a585 100644 >> --- a/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt >> +++ b/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt >> @@ -17,5 +17,6 @@ piglit_add_executable(arb_shader_image_load_store-bitcast >> bitcast.c ${depends}) >> piglit_add_executable(arb_shader_image_load_store-coherency coherency.c >> ${depends}) >> piglit_add_executable(arb_shader_image_load_store-dead-fragments >> dead-fragments.c ${depends}) >> piglit_add_executable(arb_shader_image_load_store-early-z early-z.c >> ${depends}) >> +piglit_add_executable(arb_shader_image_load_store-host-mem-barrier >> host-mem-barrier.c ${depends}) >> >> # vim: ft=cmake: >> diff --git a/tests/spec/arb_shader_image_load_store/host-mem-barrier.c >> b/tests/spec/arb_shader_image_load_store/host-mem-barrier.c >> new file mode 100644 >> index 0000000..ee0d650 >> --- /dev/null >> +++ b/tests/spec/arb_shader_image_load_store/host-mem-barrier.c >> @@ -0,0 +1,1063 @@ >> +/* >> + * 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 host-mem-barrier.c >> + * >> + * Unlike other GL API objects, images are not implicitly synchronized >> + * with subsequent GL operations. The glMemoryBarrier() API is provided >> + * to serialize shader memory transactions issued by previous drawing >> + * commands with respect to a given set of subsequent GL commands >> + * specified as a bit set. >> + * >> + * This test should cause several kinds of data hazard situations >> + * deliberately (RaW, WaR, WaW) between image loads and stores and other >> + * parts of the pipeline including vertex, element and indirect command >> + * fetch, shader uniform buffer, image and atomic counter access, texture >> + * sampling, pixel transfer operations, texture and buffer update >> + * commands, framebuffer writes and reads and transform feedback output. >> + * >> + * The test is repeated for different execution sizes 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 which inhibits all glMemoryBarrier() >> + * calls in order to make sure that the test is leading to data >> + * hazards, 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 64 >> + >> +/** 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 >> + >> +static char * >> +common_hunk(const struct image_info img) >> +{ >> + return concat(hunk("#extension GL_ARB_shader_atomic_counters : >> enable\n"), >> + image_hunk(img, ""), >> + hunk("#define RED DATA_T(1, 0, 0, 1)\n" >> + "#define GREEN DATA_T(0, 1, 0, 1)\n" >> + "\n" >> + "uniform IMAGE_T src_img;\n" >> + "uniform IMAGE_T dst_img;\n" >> + "uniform int pass;\n"), NULL); >> +} >> + >> +struct image_barrier_info { >> + /** Test name. */ >> + const char *name; >> + >> + /** Invoke a memory barrier affecting the specified units. */ >> + bool (*run_barrier)(GLbitfield barriers); >> + >> + /** Informative "control" test with no barriers whose result >> + * is ignored. */ >> + bool control_test; >> +}; >> + >> +static bool >> +run_barrier_none(GLbitfield barriers) >> +{ >> + return true; >> +} >> + >> +static bool >> +run_barrier_one(GLbitfield barriers) >> +{ >> + glMemoryBarrier(barriers); >> + return piglit_check_gl_error(GL_NO_ERROR); >> +} >> + >> +static bool >> +run_barrier_full(GLbitfield barriers) >> +{ >> + glMemoryBarrier(GL_ALL_BARRIER_BITS); >> + return piglit_check_gl_error(GL_NO_ERROR); >> +} >> + >> +const struct image_barrier_info image_barriers[] = { >> + { "control", run_barrier_none, true }, >> + { "one bit", run_barrier_one, false }, >> + { "full", run_barrier_full, false }, >> + { 0 } >> +}; >> + >> +static bool >> +check_fb_green(const struct grid_info grid) >> +{ >> + uint32_t pixels[N][4]; >> + >> + return download_result(grid, pixels[0]) && >> + check_pixels(image_info_for_grid(grid), >> + pixels[0], 0, 1, 0, 1); >> +} >> + >> +static bool >> +check_img_green(const struct image_info img) >> +{ >> + uint32_t pixels[N][4]; >> + >> + return download_image(img, 1, pixels[0]) && >> + check_pixels(img, pixels[0], 0, 1, 0, 1); >> +} >> + >> +static bool >> +init_common(const struct grid_info grid, const struct image_info img, >> + GLuint prog) >> +{ >> + uint32_t pixels[N][4]; >> + >> + if (!init_pixels(img, pixels[0], 0, 1, 0, 1) || >> + !upload_image(img, 0, pixels[0]) || >> + !init_pixels(img, pixels[0], 66, 66, 66, 66) || >> + !upload_image(img, 1, pixels[0])) >> + return false; >> + >> + set_uniform_int(prog, "src_img", 0); >> + set_uniform_int(prog, "dst_img", 1); >> + set_uniform_int(prog, "pass", 0); >> + >> + return init_fb(grid); >> +} >> + >> +static bool >> +run_test_vertex_array_raw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_VERTEX_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_BUFFER, GL_RGBA32F, l, l); >> + static GLuint vao, vbo; >> + GLuint prog = generate_program( >> + grid, GL_VERTEX_SHADER, >> + concat(common_hunk(img), >> + hunk("in vec4 piglit_texcoord;\n" >> + "\n" >> + "GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " if (pass == 1) {\n" >> + " return piglit_texcoord;\n" >> + " } else {\n" >> + " imageStore(dst_img, >> IMAGE_ADDR(idx), GREEN);\n" >> + " return x;\n" >> + " }\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog) && >> + generate_grid_arrays(&vao, &vbo, >> + 1.0 / l - 1.0, 1.0 / l - 1.0, >> + 2.0 / l, 2.0 / l, l, l); >> + >> + /* Bind the image as texcoord vbo simultaneously. */ >> + glBindBuffer(GL_ARRAY_BUFFER, get_buffer(1)); >> + glVertexAttribPointer(PIGLIT_ATTRIB_TEX, 4, GL_FLOAT, GL_FALSE, >> + 0, 0); >> + glEnableVertexAttribArray(PIGLIT_ATTRIB_TEX); >> + >> + /* First pass: render green to the vbo. */ >> + glDrawArrays(GL_POINTS, 0, l * l); >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT); >> + >> + /* Second pass: check that the texcoords are all green >> + * (read-after-write). */ >> + set_uniform_int(prog, "pass", 1); >> + glDrawArrays(GL_POINTS, 0, l * l); >> + >> + ret &= piglit_check_gl_error(GL_NO_ERROR) && >> + check_fb_green(grid); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_element_array_raw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_BUFFER, GL_R32UI, l, l); >> + static GLuint vao, vbo; >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " if (pass == 1) {\n" >> + " return GRID_T(GREEN);\n" >> + " } else {\n" >> + " imageStore(dst_img, >> IMAGE_ADDR(idx)," >> + " >> DATA_T(IMAGE_ADDR(idx)));\n" >> + " return x;\n" >> + " }\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog) && >> + generate_grid_arrays(&vao, &vbo, >> + 1.0 / l - 1.0, 1.0 / l - 1.0, >> + 2.0 / l, 2.0 / l, l, l); >> + >> + /* Bind the image as element buffer simultaneously. */ >> + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, get_buffer(1)); >> + >> + /* First pass: write sequential indices to the element buffer. */ >> + glDrawArrays(GL_POINTS, 0, l * l); >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_ELEMENT_ARRAY_BARRIER_BIT); >> + >> + /* Second pass: render the generated element buffer >> + * (read-after-write). */ >> + set_uniform_int(prog, "pass", 1); >> + glDrawElements(GL_POINTS, l * l, GL_UNSIGNED_INT, 0); >> + >> + ret &= piglit_check_gl_error(GL_NO_ERROR) && >> + check_fb_green(grid); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_ubo_raw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_BUFFER, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("layout(std140) uniform u {\n" >> + " vec4 xs[N];\n" >> + "};\n" >> + "\n" >> + "GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " if (pass == 1) {\n" >> + " return xs[IMAGE_ADDR(idx)];\n" >> + " } else {\n" >> + " imageStore(dst_img, >> IMAGE_ADDR(idx), GREEN);\n" >> + " return x;\n" >> + " }\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog); >> + >> + /* Bind the image as uniform buffer simultaneously. */ >> + glBindBufferBase(GL_UNIFORM_BUFFER, 0, get_buffer(1)); >> + >> + /* First pass: render green to the uniform buffer. */ >> + ret &= draw_grid(grid, prog) && >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_UNIFORM_BARRIER_BIT) && >> + >> + /* Second pass: check that the uniforms are all green >> + * (read-after-write). */ >> + set_uniform_int(prog, "pass", 1) && >> + draw_grid(grid, prog) && >> + check_fb_green(grid); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_tex_fetch_raw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_2D, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("uniform sampler2D tex;\n" >> + "\n" >> + "GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " if (pass == 1) {\n" >> + " return texelFetch(tex, idx, >> 0);\n" >> + " } else {\n" >> + " imageStore(dst_img, >> IMAGE_ADDR(idx), GREEN);\n" >> + " return x;\n" >> + " }\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog); >> + >> + /* Bind the image as texture simultaneously. */ >> + glActiveTexture(GL_TEXTURE0); >> + glBindTexture(GL_TEXTURE_2D, get_texture(1)); >> + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); >> + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); >> + >> + /* First pass: render green to the uniform buffer. */ >> + ret &= draw_grid(grid, prog) && >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_TEXTURE_FETCH_BARRIER_BIT) && >> + set_uniform_int(prog, "pass", 1) && >> + >> + /* Second pass: check that the texture is green >> + * (read-after-write). */ >> + draw_grid(grid, prog) && >> + check_fb_green(grid); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_image_raw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_2D, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " if (pass == 1) {\n" >> + " return imageLoad(dst_img, >> IMAGE_ADDR(idx));\n" >> + " } else {\n" >> + " imageStore(dst_img, >> IMAGE_ADDR(idx), GREEN);\n" >> + " return x;\n" >> + " }\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog) && >> + >> + /* First pass: render green to the image. */ >> + draw_grid(grid, prog) && >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT) && >> + >> + /* Second pass: check that the image is green >> + * (read-after-write). */ >> + set_uniform_int(prog, "pass", 1) && >> + draw_grid(grid, prog) && >> + check_fb_green(grid); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_image_war(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_2D, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " if (pass == 1) {\n" >> + " imageStore(src_img, >> IMAGE_ADDR(idx), RED);\n" >> + " } else {\n" >> + " imageStore(dst_img, >> IMAGE_ADDR(idx)," >> + " imageLoad(src_img, >> IMAGE_ADDR(idx)));\n" >> + " }\n" >> + " return x;\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog) && >> + >> + /* First pass: read back the source image. */ >> + draw_grid(grid, prog) && >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT) && >> + >> + /* Second pass: render red to the source image >> + * (write-after-read). */ >> + set_uniform_int(prog, "pass", 1) && >> + draw_grid(grid, prog) && >> + >> + /* Check that the read-back results from the first >> + * pass are green. */ >> + check_img_green(img); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_indirect_raw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_VERTEX_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_BUFFER, GL_RGBA32UI, l, l); >> + static GLuint vao, vbo; >> + GLuint prog = generate_program( >> + grid, GL_VERTEX_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " if (pass == 1) {\n" >> + " return GRID_T(gl_InstanceID == >> 2 ? GREEN : RED);\n" >> + " } else {\n" >> + " imageStore(dst_img, >> IMAGE_ADDR(idx)," >> + " DATA_T(1, 3, >> IMAGE_ADDR(idx), 0));\n" >> + " return x;\n" >> + " }\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog) && >> + generate_grid_arrays(&vao, &vbo, >> + 1.0 / l - 1.0, 1.0 / l - 1.0, >> + 2.0 / l, 2.0 / l, l, l); >> + >> + /* Bind the image as indirect command buffer >> + * simultaneously. */ >> + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, get_buffer(1)); >> + >> + /* First pass: Render instanced draw commands to the indirect >> + * buffer. */ >> + glDrawArrays(GL_POINTS, 0, l * l); >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_COMMAND_BARRIER_BIT); >> + >> + /* Second pass: render the generated indirect buffer >> + * (read-after-write). */ >> + set_uniform_int(prog, "pass", 1); >> + glMultiDrawArraysIndirect(GL_POINTS, 0, l * l, 0); >> + >> + ret &= piglit_check_gl_error(GL_NO_ERROR) && >> + check_fb_green(grid); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_pixel_raw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_BUFFER, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " imageStore(dst_img, IMAGE_ADDR(idx), >> GREEN);\n" >> + " return x;\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog); >> + uint32_t pixels[N][4]; >> + GLuint tex; >> + >> + /* Bind the image as pixel unpack buffer simultaneously. */ >> + glGenTextures(1, &tex); >> + glBindTexture(GL_TEXTURE_2D, tex); >> + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, get_buffer(1)); >> + >> + /* First pass: render green to the image. */ >> + draw_grid(grid, prog); >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_PIXEL_BUFFER_BARRIER_BIT); >> + >> + /* Second pass: use the result as pixel source >> + * (read-after-write). */ >> + glTexImage2D(GL_TEXTURE_2D, 0, img.format->format, >> + l, l, 0, img.format->pixel_format, >> + img.format->pixel_type, 0); >> + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); >> + >> + /* Check that the resulting texture is green. */ >> + glGetTexImage(GL_TEXTURE_2D, 0, img.format->pixel_format, >> + image_base_type(img.format), pixels); >> + >> + ret &= piglit_check_gl_error(GL_NO_ERROR) && >> + check_pixels(img, pixels[0], 0, 1, 0, 1); >> + >> + glDeleteTextures(1, &tex); >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_pixel_waw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_BUFFER, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " imageStore(dst_img, IMAGE_ADDR(idx), >> RED);\n" >> + " return x;\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog); >> + uint32_t pixels[N][4]; >> + GLuint tex; >> + >> + init_pixels(img, pixels[0], 0, 1, 0, 1); >> + >> + glGenTextures(1, &tex); >> + glBindTexture(GL_TEXTURE_2D, tex); >> + glTexImage2D(GL_TEXTURE_2D, 0, img.format->format, >> + l, l, 0, img.format->pixel_format, >> + image_base_type(img.format), pixels); >> + >> + /* Bind the image as pixel pack buffer simultaneously. */ >> + glBindBuffer(GL_PIXEL_PACK_BUFFER, get_buffer(1)); >> + >> + /* First pass: render red to the image. */ >> + draw_grid(grid, prog); >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_PIXEL_BUFFER_BARRIER_BIT); >> + >> + /* Second pass: use the image as pixel destination filling it >> + * with green (write-after-write). */ >> + glGetTexImage(GL_TEXTURE_2D, 0, img.format->pixel_format, >> + img.format->pixel_type, 0); >> + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); >> + >> + /* Check that the resulting image is green. */ >> + ret &= piglit_check_gl_error(GL_NO_ERROR) && >> + check_img_green(img); >> + >> + glDeleteTextures(1, &tex); >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_tex_update_raw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_2D, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " imageStore(dst_img, IMAGE_ADDR(idx), >> GREEN);\n" >> + " return x;\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog); >> + uint32_t pixels[N][4]; >> + >> + glBindTexture(GL_TEXTURE_2D, get_texture(1)); >> + >> + /* First pass: render green to the image. */ >> + draw_grid(grid, prog); >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT); >> + >> + /* Read back the result (read-after-write). */ >> + glGetTexImage(GL_TEXTURE_2D, 0, img.format->pixel_format, >> + image_base_type(img.format), pixels); >> + >> + ret &= piglit_check_gl_error(GL_NO_ERROR) && >> + check_pixels(img, pixels[0], 0, 1, 0, 1); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_tex_update_waw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_2D, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " imageStore(dst_img, IMAGE_ADDR(idx)," >> + " (idx.y >= H / 2 ? GREEN : >> RED));\n" >> + " return x;\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog); >> + uint32_t pixels[N][4]; >> + >> + init_pixels(set_image_size(img, l, l / 2, 1, 1), >> + pixels[0], 0, 1, 0, 1); >> + >> + glBindTexture(GL_TEXTURE_2D, get_texture(1)); >> + >> + /* First pass: render red to the first half of the image, >> + * green to the second half. */ >> + draw_grid(grid, prog); >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT); >> + >> + /* Fill the first half with green (write-after-write). */ >> + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, l, l / 2, >> + img.format->pixel_format, >> image_base_type(img.format), >> + pixels); >> + >> + /* Check that the resulting image is green. */ >> + ret &= piglit_check_gl_error(GL_NO_ERROR) && >> + check_img_green(img); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_buf_update_raw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_BUFFER, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " imageStore(dst_img, IMAGE_ADDR(idx), >> GREEN);\n" >> + " return x;\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog); >> + uint32_t pixels[N][4]; >> + >> + glBindBuffer(GL_TEXTURE_BUFFER, get_buffer(1)); >> + >> + /* First pass: render green to the image. */ >> + draw_grid(grid, prog); >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_BUFFER_UPDATE_BARRIER_BIT); >> + >> + /* Read back the result (read-after-write). */ >> + glGetBufferSubData(GL_TEXTURE_BUFFER, 0, >> + 4 * l * l * sizeof(uint32_t), pixels[0]); >> + >> + ret &= piglit_check_gl_error(GL_NO_ERROR) && >> + check_pixels(img, pixels[0], 0, 1, 0, 1); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_buf_update_waw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_BUFFER, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " imageStore(dst_img, IMAGE_ADDR(idx)," >> + " (idx.y >= H / 2 ? GREEN : >> RED));\n" >> + " return x;\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog); >> + uint32_t pixels[N][4]; >> + >> + init_pixels(set_image_size(img, l * l / 2, 1, 1, 1), >> + pixels[0], 0, 1, 0, 1); >> + glBindBuffer(GL_TEXTURE_BUFFER, get_buffer(1)); >> + >> + /* First pass: render red to the first half of the image, >> + * green to the second half. */ >> + draw_grid(grid, prog); >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_BUFFER_UPDATE_BARRIER_BIT); >> + >> + /* Fill the first half with green (write-after-write). */ >> + glBufferSubData(GL_TEXTURE_BUFFER, 0, 4 * l * l / 2 * >> sizeof(uint32_t), >> + pixels); >> + >> + /* Check that the resulting image is green. */ >> + ret &= piglit_check_gl_error(GL_NO_ERROR) && >> + check_img_green(img); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_fb_raw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_2D, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " imageStore(dst_img, IMAGE_ADDR(idx), >> GREEN);\n" >> + " return x;\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog); >> + uint32_t pixels[N][4]; >> + GLuint fb; >> + >> + glGenFramebuffers(1, &fb); >> + glBindFramebuffer(GL_READ_FRAMEBUFFER, fb); >> + >> + /* Bind the image as color attachment of the read framebuffer >> + * simultaneously. */ >> + glFramebufferTexture(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, >> + get_texture(1), 0); >> + >> + /* First pass: render green to the image. */ >> + draw_grid(grid, prog); >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_FRAMEBUFFER_BARRIER_BIT); >> + >> + /* Read back and check the result from the read >> + * framebuffer (read-after-write). */ >> + glReadPixels(0, 0, l, l, img.format->pixel_format, >> + image_base_type(img.format), pixels); >> + >> + ret &= piglit_check_gl_error(GL_NO_ERROR) && >> + check_pixels(img, pixels[0], 0, 1, 0, 1); >> + >> + glDeleteFramebuffers(1, &fb); >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_fb_waw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_2D, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " if (pass == 1) {\n" >> + " return GREEN;" >> + " } else {\n" >> + " imageStore(dst_img, >> IMAGE_ADDR(idx), RED);\n" >> + " return RED;\n" >> + " }\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog); >> + GLuint fb; >> + >> + glGenFramebuffers(1, &fb); >> + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb); >> + >> + /* Bind the image as color attachment of the framebuffer >> + * simultaneously. */ >> + glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, >> + get_texture(1), 0); >> + >> + /* First pass: render red to the image. */ >> + ret &= draw_grid(grid, prog) && >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_FRAMEBUFFER_BARRIER_BIT) && >> + >> + /* Second pass: render green to the framebuffer >> + * (write-after-write). */ >> + set_uniform_int(prog, "pass", 1) && >> + draw_grid(grid, prog) && >> + >> + /* Check that the resulting image is green. */ >> + check_img_green(img); >> + >> + glDeleteFramebuffers(1, &fb); >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +setup_xfb_varying(GLuint prog, const char *varying) >> +{ >> + glTransformFeedbackVaryings(prog, 1, &varying, >> GL_INTERLEAVED_ATTRIBS); >> + glLinkProgram(prog); >> + >> + return piglit_check_gl_error(GL_NO_ERROR); >> +} >> + >> +static bool >> +run_test_xfb_waw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_VERTEX_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_BUFFER, GL_RGBA32F, l, l); >> + GLuint prog = generate_program( >> + grid, GL_VERTEX_SHADER, >> + concat(common_hunk(img), >> + hunk("GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " if (pass == 1) {\n" >> + " return GREEN;\n" >> + " } else {\n" >> + " imageStore(dst_img, >> IMAGE_ADDR(idx), RED);\n" >> + " return x;\n" >> + " }\n" >> + "}\n"), NULL)); >> + bool ret = prog && setup_xfb_varying(prog, "vcolor") && >> + init_common(grid, img, prog); >> + GLuint xfb; >> + >> + glGenTransformFeedbacks(1, &xfb); >> + glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb); >> + >> + /* Bind the image as transform feedback buffer >> + * simultaneously. */ >> + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, get_buffer(1)); >> + glBeginTransformFeedback(GL_POINTS); >> + glPauseTransformFeedback(); >> + >> + /* First pass: render red to the image. */ >> + draw_grid(grid, prog); >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT); >> + >> + /* Second pass: Write out the vcolor output to the transform >> + * feedback buffer (write-after-write). */ >> + set_uniform_int(prog, "pass", 1); >> + glResumeTransformFeedback(); >> + draw_grid(grid, prog); >> + glEndTransformFeedback(); >> + >> + /* Check that the resulting image is green. */ >> + ret &= piglit_check_gl_error(GL_NO_ERROR) && >> + check_img_green(img); >> + >> + glDeleteTransformFeedbacks(1, &xfb); >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_atom_raw(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_BUFFER, GL_RGBA32UI, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("layout(binding=0, offset=0) uniform >> atomic_uint c[4];\n" >> + "\n" >> + "GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " if (pass == 1) {\n" >> + " return >> GRID_T(atomicCounter(c[0])," >> + " >> atomicCounter(c[1])," >> + " >> atomicCounter(c[2])," >> + " >> atomicCounter(c[3]));\n" >> + " } else {\n" >> + " imageStore(dst_img, >> IMAGE_ADDR(idx), GREEN);\n" >> + " return x;\n" >> + " }\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog); >> + >> + /* Bind the image as atomic counter buffer simultaneously. */ >> + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, get_buffer(1)); >> + >> + /* First pass: render green to the image. */ >> + ret &= draw_grid(grid, prog) && >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_ATOMIC_COUNTER_BARRIER_BIT) && >> + >> + /* Second pass: Check that the atomic counters read >> + * back green (read-after-write). */ >> + set_uniform_int(prog, "pass", 1) && >> + draw_grid(grid, prog) && >> + check_fb_green(grid); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static bool >> +run_test_atom_war(const struct image_barrier_info *bar, unsigned l) >> +{ >> + const struct grid_info grid = >> + grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, l, l); >> + const struct image_info img = >> + image_info(GL_TEXTURE_BUFFER, GL_RGBA32UI, l, l); >> + GLuint prog = generate_program( >> + grid, GL_FRAGMENT_SHADER, >> + concat(common_hunk(img), >> + hunk("layout(binding=0, offset=0) uniform >> atomic_uint c[4];\n" >> + "\n" >> + "GRID_T op(ivec2 idx, GRID_T x) {\n" >> + " if (pass == 1) {\n" >> + " atomicCounterIncrement(c[0]);" >> + " atomicCounterIncrement(c[1]);" >> + " atomicCounterIncrement(c[2]);" >> + " >> atomicCounterIncrement(c[3]);\n" >> + " } else {\n" >> + " imageStore(dst_img, >> IMAGE_ADDR(idx)," >> + " imageLoad(src_img, >> IMAGE_ADDR(idx)));\n" >> + " }\n" >> + " return x;\n" >> + "}\n"), NULL)); >> + bool ret = prog && init_common(grid, img, prog); >> + >> + /* Bind the image as atomic counter buffer simultaneously. */ >> + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, get_buffer(0)); >> + >> + /* First pass: read back the source image. */ >> + ret &= draw_grid(grid, prog) && >> + >> + /* Barrier. */ >> + bar->run_barrier(GL_ATOMIC_COUNTER_BARRIER_BIT) && >> + >> + /* Second pass: Modify the source image using atomic >> + * counter increments (write-after-read). */ >> + set_uniform_int(prog, "pass", 1) && >> + draw_grid(grid, prog) && >> + >> + /* Check that the read-back results from the first >> + * pass are green. */ >> + check_img_green(img); >> + >> + glDeleteProgram(prog); >> + return ret; >> +} >> + >> +static void >> +barrier_subtest(enum piglit_result *status, bool guard, >> + bool (*run)(const struct image_barrier_info *, unsigned), >> + const char *name, const struct image_barrier_info *bar, >> + unsigned l) >> +{ >> + subtest(status, guard, run(bar, l) || bar->control_test, >> + "%s/%s barrier test/%dx%d", name, bar->name, l, l); >> +} >> + >> +void >> +piglit_init(int argc, char **argv) >> +{ >> + const bool quick = (argc >= 2 && !strcmp(argv[1], "--quick")); >> + const struct image_barrier_info *bar; >> + enum piglit_result status = PIGLIT_PASS; >> + unsigned l; >> + >> + piglit_require_extension("GL_ARB_shader_image_load_store"); >> + piglit_require_extension("GL_ARB_shader_atomic_counters"); >> + >> + for (l = 4; l <= L; l *= 4) { >> + for (bar = image_barriers; bar->name; ++bar) { >> + if (quick && bar->control_test) >> + continue; >> + >> + barrier_subtest(&status, >> + get_image_stage(GL_VERTEX_SHADER), >> + run_test_vertex_array_raw, >> + "Vertex array/RaW", bar, l); >> + >> + barrier_subtest(&status, true, >> run_test_element_array_raw, >> + "Element array/RaW", bar, l); >> + >> + barrier_subtest(&status, true, run_test_ubo_raw, >> + "Uniform buffer/RaW", bar, l); >> + >> + barrier_subtest(&status, true, >> run_test_tex_fetch_raw, >> + "Texture fetch/RaW", bar, l); >> + >> + barrier_subtest(&status, true, run_test_image_raw, >> + "Image/RaW", bar, l); >> + >> + barrier_subtest(&status, true, run_test_image_war, >> + "Image/WaR", bar, l); >> + >> + barrier_subtest(&status, >> + (get_image_stage(GL_VERTEX_SHADER) >> && >> + piglit_is_extension_supported( >> + "GL_ARB_draw_indirect")), >> + run_test_indirect_raw, >> + "Indirect/RaW", bar, l); >> + >> + barrier_subtest(&status, true, run_test_pixel_raw, >> + "Pixel/RaW", bar, l); >> + >> + barrier_subtest(&status, true, run_test_pixel_waw, >> + "Pixel/WaW", bar, l); >> + >> + barrier_subtest(&status, true, >> run_test_tex_update_raw, >> + "Texture update/RaW", bar, l); >> + >> + barrier_subtest(&status, true, >> run_test_tex_update_waw, >> + "Texture update/WaW", bar, l); >> + >> + barrier_subtest(&status, true, >> run_test_buf_update_raw, >> + "Buffer update/RaW", bar, l); >> + >> + barrier_subtest(&status, true, >> run_test_buf_update_waw, >> + "Buffer update/WaW", bar, l); >> + >> + barrier_subtest(&status, true, run_test_fb_raw, >> + "Framebuffer/RaW", bar, l); >> + >> + barrier_subtest(&status, true, run_test_fb_waw, >> + "Framebuffer/WaW", bar, l); >> + >> + barrier_subtest(&status, >> + (get_image_stage(GL_VERTEX_SHADER) >> && >> + piglit_is_extension_supported( >> + >> "GL_ARB_transform_feedback2")), >> + run_test_xfb_waw, >> + "Transform feedback/WaW", bar, l); >> + >> + barrier_subtest(&status, true, run_test_atom_raw, >> + "Atomic counter/RaW", bar, l); >> + >> + barrier_subtest(&status, true, run_test_atom_war, >> + "Atomic counter/WaR", bar, l); >> + } >> + } >> + >> + piglit_report_result(status); >> +} >> + >> +enum piglit_result >> +piglit_display(void) >> +{ >> + return PIGLIT_FAIL; >> +} >> -- >> 2.1.3 >> >> _______________________________________________ >> Piglit mailing list >> Piglit@lists.freedesktop.org >> http://lists.freedesktop.org/mailman/listinfo/piglit
pgpIjcE52t1Xy.pgp
Description: PGP signature
_______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/piglit