diff options
author | Francisco Jerez <currojerez@riseup.net> | 2014-12-04 12:48:55 +0200 |
---|---|---|
committer | Francisco Jerez <currojerez@riseup.net> | 2015-01-31 18:28:46 +0200 |
commit | aed992baacccbc0b47fc29ceabf78cebfbf66b23 (patch) | |
tree | b93a5cd86fcd0abdd993e9e58d9a449330d8ae47 | |
parent | 01027b7d2a1ca80139ac3a4db1c6cf2cf5d1febe (diff) |
arb_shader_image_load_store: Import memory coherency test.
Test the cache coherency of images declared as "coherent" or
"volatile" when accessed from different combinations of dependent
shader stages.
-rw-r--r-- | tests/all.py | 1 | ||||
-rw-r--r-- | tests/quick.py | 5 | ||||
-rw-r--r-- | tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt | 1 | ||||
-rw-r--r-- | tests/spec/arb_shader_image_load_store/coherency.c | 228 |
4 files changed, 234 insertions, 1 deletions
diff --git a/tests/all.py b/tests/all.py index 9ae9f6b4b..e4bdc1786 100644 --- a/tests/all.py +++ b/tests/all.py @@ -4428,6 +4428,7 @@ import_glsl_parser_tests(spec['ARB_shader_image_load_store'], ['']) arb_shader_image_load_store['atomicity'] = PiglitGLTest(['arb_shader_image_load_store-atomicity'], run_concurrent=True) arb_shader_image_load_store['bitcast'] = PiglitGLTest(['arb_shader_image_load_store-bitcast'], run_concurrent=True) +arb_shader_image_load_store['coherency'] = PiglitGLTest(['arb_shader_image_load_store-coherency'], 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 8762d7d80..10333965d 100644 --- a/tests/quick.py +++ b/tests/quick.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from framework.test import GleanTest +from framework.test import (GleanTest, PiglitGLTest) from tests.all import profile __all__ = ['profile'] @@ -12,3 +12,6 @@ del profile.tests['shaders']['glsl-fs-inline-explosion'] del profile.tests['shaders']['glsl-fs-unroll-explosion'] 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'] = PiglitGLTest( + ['arb_shader_image_load_store-coherency', '--quick'], run_concurrent=True) 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 6b53370f6..6a6aa25d9 100644 --- a/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt +++ b/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt @@ -14,5 +14,6 @@ set(depends image.c grid.c common.c) piglit_add_executable(arb_shader_image_load_store-atomicity atomicity.c ${depends}) piglit_add_executable(arb_shader_image_load_store-bitcast bitcast.c ${depends}) +piglit_add_executable(arb_shader_image_load_store-coherency coherency.c ${depends}) # vim: ft=cmake: diff --git a/tests/spec/arb_shader_image_load_store/coherency.c b/tests/spec/arb_shader_image_load_store/coherency.c new file mode 100644 index 000000000..e8484a7b4 --- /dev/null +++ b/tests/spec/arb_shader_image_load_store/coherency.c @@ -0,0 +1,228 @@ +/* + * 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 coherency.c + * + * Images declared as "coherent" or "volatile" give certain guarantees + * regarding the visibility of memory writes to other shader invocations + * in the pipeline. This test checks the following assertion of the + * spec: + * "When reading a variable declared as 'coherent', the values returned + * will reflect the results of previously completed writes performed by + * other shader invocations. When writing a variable declared as + * 'coherent', the values written will be reflected in subsequent + * coherent reads performed by other shader invocations." + * + * Together with: + * "When executing a shader whose inputs are generated from a previous + * programmable stage, the shader invocations from the previous stage + * are guaranteed to have executed far enough to generate final values + * for all next-stage inputs." + * + * In order to test this we bind two shader programs at different + * execution stages of the pipeline and check that the values written to + * an image from the first stage are visible when the same primitive is + * dispatched at the second stage. This is repeated for all combinations + * of dependent shader stages (what necessarily excludes the compute + * shader), for the "coherent" and "volatile" qualifiers (the latter is + * supposed to give stricter ordering guarantees), and for different + * execution sizes between 4x4 and 1024x1024 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 repeating the same process without any memory qualifiers. + * This is useful to see if the cache is being hit 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 1024 + +/** 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 + +struct image_qualifier_info { + /** Test name. */ + const char *name; + + /** Image qualifier keyword. */ + const char *qualifier; + + /** Informative "control" test with no memory qualifiers whose + * result is ignored. */ + bool control_test; +}; + +const struct image_qualifier_info image_qualifiers[] = { + { "control", "", true }, + { "'coherent' qualifier", "coherent", false }, + { "'volatile' qualifier", "volatile", false }, + { 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) +{ + static uint32_t pixels[N][4]; + + return init_pixels(img, pixels[0], 99, 99, 99, 99) && + upload_image(img, 0, pixels[0]); +} + +static bool +check(const struct grid_info grid, const struct image_info img) +{ + static uint32_t pixels[N][4]; + + return download_result(grid, pixels[0]) && + check_pixels(img, pixels[0], 33, 33, 33, 33); +} + +static bool +run_test(const struct image_qualifier_info *qual, + const struct image_stage_info *stage_w, + const struct image_stage_info *stage_r, + unsigned l) +{ + const struct grid_info grid = { + stage_w->bit | stage_r->bit, + get_image_format(GL_RGBA32UI), + { l, l, 1, 1 } + }; + const struct image_info img = image_info_for_grid(grid); + GLuint prog = generate_program( + grid, + /* + * Write (11, 22, 33, 44) to some location on the + * image from the write stage. + */ + stage_w->stage, + concat(qualifier_hunk(qual), + image_hunk(img, ""), + hunk("IMAGE_Q uniform IMAGE_T img;\n" + "\n" + "GRID_T op(ivec2 idx, GRID_T x) {\n" + " imageStore(img, idx, DATA_T(11, 22, 33, 44));" + " return x;" + "}\n"), NULL), + /* + * The same location will read back the expected value + * if image access is coherent, as the shader inputs + * of the read stage are dependent on the outputs of + * the write stage and consequently they are + * guaranteed to be executed sequentially. + */ + stage_r->stage, + concat(qualifier_hunk(qual), + image_hunk(img, ""), + hunk("IMAGE_Q uniform IMAGE_T img;\n" + "\n" + "GRID_T op(ivec2 idx, GRID_T x) {\n" + " DATA_T v = imageLoad(img, idx);" + " if (v == DATA_T(11, 22, 33, 44))" + " return GRID_T(33, 33, 33, 33);" + " else" + " return GRID_T(77, 77, 77, 77);" + "}\n"), NULL)); + bool ret = prog && + init_fb(grid) && + init_image(img) && + set_uniform_int(prog, "img", 0) && + draw_grid(grid, prog) && + (check(grid, img) || qual->control_test); + + glDeleteProgram(prog); + return ret; +} + +void +piglit_init(int argc, char **argv) +{ + const bool quick = (argc >= 2 && !strcmp(argv[1], "--quick")); + const struct image_qualifier_info *qual; + const struct image_stage_info *stage_w; + const struct image_stage_info *stage_r; + enum piglit_result status = PIGLIT_PASS; + unsigned l; + + piglit_require_extension("GL_ARB_shader_image_load_store"); + + for (l = 4; l <= L; l *= (quick ? 8 : 2)) { + for (qual = image_qualifiers; qual->name; ++qual) { + if (quick && qual->control_test) + continue; + + /* + * Loop for each pair of shader stages + * skipping the compute shader: "coherent" + * gives no useful guarantees in that case + * since its execution ordering is undefined + * with respect to the other shader stages. + */ + for (stage_w = image_stages(); + stage_w->stage && stage_w->stage != GL_COMPUTE_SHADER; + ++stage_w) { + for (stage_r = stage_w + 1; + stage_r->stage && stage_r->stage != GL_COMPUTE_SHADER; + ++stage_r) { + subtest(&status, true, + run_test(qual, stage_w, stage_r, l), + "%s-%s shader/%s coherency test/%dx%d", + stage_w->name, stage_r->name, + qual->name, l, l); + } + } + } + } + + piglit_report_result(status); +} + +enum piglit_result +piglit_display(void) +{ + return PIGLIT_FAIL; +} |