diff options
author | Francisco Jerez <currojerez@riseup.net> | 2014-12-04 12:53:46 +0200 |
---|---|---|
committer | Francisco Jerez <currojerez@riseup.net> | 2015-01-31 18:29:33 +0200 |
commit | 774da7f87e743856baddf8ceb7beba195907d3e2 (patch) | |
tree | 57be0dec591e5fc279a782ac510ab1ebcc34279e | |
parent | 7cbbb32e10947e1a58f6534e0c4df095a33d2f3f (diff) |
arb_shader_image_load_store: Import image aliasing test.
Test if the implementation is incorrectly assuming that different
image uniforms point to disjoint locations in memory, which could lead
to incorrect code transformations and break valid GLSL programs.
-rw-r--r-- | tests/all.py | 1 | ||||
-rw-r--r-- | tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt | 1 | ||||
-rw-r--r-- | tests/spec/arb_shader_image_load_store/restrict.c | 179 |
3 files changed, 181 insertions, 0 deletions
diff --git a/tests/all.py b/tests/all.py index 978810368..3fe03f6af 100644 --- a/tests/all.py +++ b/tests/all.py @@ -4440,6 +4440,7 @@ arb_shader_image_load_store['max-images'] = PiglitGLTest(['arb_shader_image_load arb_shader_image_load_store['max-size'] = PiglitGLTest(['arb_shader_image_load_store-max-size'], run_concurrent=True) arb_shader_image_load_store['minmax'] = PiglitGLTest(['arb_shader_image_load_store-minmax'], run_concurrent=True) arb_shader_image_load_store['qualifiers'] = PiglitGLTest(['arb_shader_image_load_store-qualifiers'], run_concurrent=True) +arb_shader_image_load_store['restrict'] = PiglitGLTest(['arb_shader_image_load_store-restrict'], run_concurrent=True) profile.tests['hiz'] = hiz profile.tests['fast_color_clear'] = fast_color_clear 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 57948f1aa..bf202e466 100644 --- a/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt +++ b/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt @@ -26,5 +26,6 @@ piglit_add_executable(arb_shader_image_load_store-max-images max-images.c ${depe piglit_add_executable(arb_shader_image_load_store-max-size max-size.c ${depends}) piglit_add_executable(arb_shader_image_load_store-minmax minmax.c ${depends}) piglit_add_executable(arb_shader_image_load_store-qualifiers qualifiers.c ${depends}) +piglit_add_executable(arb_shader_image_load_store-restrict restrict.c ${depends}) # vim: ft=cmake: diff --git a/tests/spec/arb_shader_image_load_store/restrict.c b/tests/spec/arb_shader_image_load_store/restrict.c new file mode 100644 index 000000000..32d3092fa --- /dev/null +++ b/tests/spec/arb_shader_image_load_store/restrict.c @@ -0,0 +1,179 @@ +/* + * 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 restrict.c + * + * Test if the implementation is incorrectly assuming that different + * image uniforms point to disjoint locations in memory, which could lead + * to code reordering and access coalescing that could break valid GLSL + * programs. This is done by repeatedly reading and writing to an image + * through two different uniforms that alias the same image in a way that + * is likely to misrender if the implementation is coalescing loads. + * + * The same test is repeated with the "restrict" keyword which + * explicitly allows the implementation to make such assumptions. The + * rendering results from this test are ignored as it's only useful to + * test the "restrict" keyword and to find out if the implementation + * is making such transformations since otherwise the main test is not + * meaningful. + */ + +#include "common.h" + +/** Window width. */ +#define W 16 + +/** Window height. */ +#define H 96 + +/** Total number of pixels in the window and image. */ +#define N (W * H) + +PIGLIT_GL_TEST_CONFIG_BEGIN + +config.supports_gl_core_version = 32; + +config.window_width = W; +config.window_height = H; +config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA; + +PIGLIT_GL_TEST_CONFIG_END + +struct image_qualifier_info { + /** Test name. */ + const char *name; + + /** Image qualifier keyword. */ + const char *qualifier; + + /** Informative "control" test whose result is ignored. */ + bool control_test; +}; + +const struct image_qualifier_info image_qualifiers[] = { + { "no qualifier", "", false }, + { "restrict qualifier", "restrict", true }, + { 0 } +}; + +char * +qualifier_hunk(const struct image_qualifier_info *qual) +{ + char *s = NULL; + + asprintf(&s, "#define IMAGE_Q %s\n", qual->qualifier); + return s; +} + +static bool +init_image(const struct image_info img) +{ + uint32_t pixels[4 * N]; + + return init_pixels(img, pixels, 1, 0, 0, 0) && + upload_image(img, 0, pixels); +} + +static bool +check(const struct image_info img) +{ + uint32_t pixels[N]; + uint32_t expect[N]; + int i; + + for (i = 0; i < N; ++i) + expect[i] = (i > W ? 2 : 1) + (i % 2 ? -1 : 1); + + return download_image(img, 0, pixels) && + check_pixels_v(img, pixels, expect); +} + +static bool +run_test(const struct image_qualifier_info *qual) +{ + const struct grid_info grid = + grid_info(GL_FRAGMENT_SHADER, GL_R32UI, W, H); + const struct image_info img = + image_info(GL_TEXTURE_1D, GL_R32UI, W, H); + GLuint prog = generate_program( + grid, + /** + * Write to consecutive locations of an image using a + * the value read from a fixed location of a different + * image uniform which aliases the first image. If + * the implementation incorrectly coalesces repeated + * loads from the fixed location the results of the + * test will be altered. + */ + GL_FRAGMENT_SHADER, + concat(qualifier_hunk(qual), + image_hunk(img, ""), + hunk("IMAGE_Q uniform IMAGE_T src_img;\n" + "IMAGE_Q uniform IMAGE_T dst_img;\n" + "\n" + "GRID_T op(ivec2 idx, GRID_T x) {\n" + " int i;\n" + "\n" + " for (i = 0; i < N / 2; ++i) {\n" + " imageStore(dst_img, 2 * i," + " imageLoad(src_img, W) + 1u);\n" + " imageStore(dst_img, 2 * i + 1," + " imageLoad(src_img, W) - 1u);\n" + " }\n" + "\n" + " return x;\n" + "}\n"), NULL)); + bool ret = prog && + init_fb(grid) && + init_image(img) && + set_uniform_int(prog, "src_img", 0) && + set_uniform_int(prog, "dst_img", 0) && + draw_grid(set_grid_size(grid, 1, 1), prog) && + (check(img) || qual->control_test); + + glDeleteProgram(prog); + return ret; +} + +void +piglit_init(int argc, char **argv) +{ + const struct image_qualifier_info *qual; + enum piglit_result status = PIGLIT_PASS; + + piglit_require_extension("GL_ARB_shader_image_load_store"); + + for (qual = image_qualifiers; qual->name; ++qual) { + subtest(&status, true, run_test(qual), + "%s image aliasing test", qual->name); + } + + + piglit_report_result(status); +} + +enum piglit_result +piglit_display(void) +{ + return PIGLIT_FAIL; +} |