ARB_ubo/referenced-by-shader: pass if shader compiler moves UBOs between shaders
[piglit.git] / tests / spec / arb_shader_image_load_store / dead-fragments.c
blobc06aaa0027135350ca30da2d2cb7c9c775d6c25b
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 dead-fragments.c
26 * Quoting the ARB_shader_image_load_store extension:
27 * "If a fragment shader is invoked to process fragments or samples
28 * not covered by a primitive being rasterized to facilitate the
29 * approximation of derivatives for texture lookups, stores and
30 * atomics have no effect."
32 * The purpose of this test is to check this assertion, as well as
33 * that image stores and atomics have no effect after a fragment is
34 * discarded. Both tests are repeated for a few different built-in
35 * functions.
38 #include "common.h"
40 /** Window width. */
41 #define W 16
43 /** Window height. */
44 #define H 96
46 /** Total number of pixels in the window and image. */
47 #define N (W * H)
49 PIGLIT_GL_TEST_CONFIG_BEGIN
51 config.supports_gl_core_version = 32;
53 config.window_width = W;
54 config.window_height = H;
55 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
56 config.khr_no_error_support = PIGLIT_NO_ERRORS;
58 PIGLIT_GL_TEST_CONFIG_END
60 struct image_op_info {
61 /** Image built-in name. */
62 const char *name;
64 /** GLSL statement that invokes this image built-in. */
65 const char *hunk;
68 static const struct image_op_info image_ops[] = {
70 "imageStore",
71 "void inc(ivec2 idx) {\n"
72 " imageStore(img, IMAGE_ADDR(idx),"
73 " imageLoad(img, IMAGE_ADDR(idx)) + BASE_T(1));\n"
74 "}\n"
77 "imageAtomicAdd",
78 "void inc(ivec2 idx) {\n"
79 " imageAtomicAdd(img, IMAGE_ADDR(idx), BASE_T(1));\n"
80 "}\n"
83 "imageAtomicMax",
84 "void inc(ivec2 idx) {\n"
85 " imageAtomicMax(img, IMAGE_ADDR(idx),"
86 " imageLoad(img, IMAGE_ADDR(idx)).x + BASE_T(1));\n"
87 "}\n"
90 "imageAtomicExchange",
91 "void inc(ivec2 idx) {\n"
92 " imageAtomicExchange(img, IMAGE_ADDR(idx),"
93 " imageLoad(img, IMAGE_ADDR(idx)).x + BASE_T(1));\n"
94 "}\n"
97 "imageAtomicCompSwap",
98 "void inc(ivec2 idx) {\n"
99 " imageAtomicCompSwap(img, IMAGE_ADDR(idx),"
100 " imageLoad(img, IMAGE_ADDR(idx)).x,"
101 " imageLoad(img, IMAGE_ADDR(idx)).x + BASE_T(1));\n"
102 "}\n"
104 { 0 }
107 static bool
108 init_image(const struct image_info img)
110 uint32_t pixels[N];
111 int i;
113 for (i = 0; i < N; ++i)
114 pixels[i] = i / W;
116 return upload_image(img, 0, pixels);
119 static bool
120 check_discard(const struct grid_info grid, const struct image_info img,
121 unsigned w, unsigned h)
123 uint32_t pixels[H][W], expect[H][W];
124 int i, j;
126 for (i = 0; i < W; ++i)
127 for (j = 0; j < H; ++j)
128 expect[j][i] = (i % 5 == 0 ? 0 : 1) + j;
130 return download_image(img, 0, pixels[0]) &&
131 check_pixels_v(img, pixels[0], expect[0]);
134 static bool
135 check_derivative(const struct grid_info grid, const struct image_info img,
136 unsigned w, unsigned h)
138 uint32_t pixels_fb[H][W], expect_fb[H][W];
139 uint32_t pixels_img[H][W], expect_img[H][W];
140 int i, j;
142 for (i = 0; i < W; ++i) {
143 for (j = 0; j < H; ++j) {
144 expect_fb[j][i] = (j < h && i < w ? 1000 :
145 encode(get_image_format(GL_R32F), 0.5));
146 expect_img[j][i] = (j < h && i < w ? 1 : 0) + j;
150 if (!download_result(grid, pixels_fb[0]) ||
151 !download_image(img, 0, pixels_img[0]))
152 return false;
154 if (!check_pixels_v(img, pixels_fb[0], expect_fb[0])) {
155 printf(" Source: framebuffer\n");
157 * Purely informational check, we don't care what the
158 * result is as long as derivatives are being
159 * calculated, don't fail if the result doesn't equal
160 * the expected value as it's most likely an accuracy
161 * issue.
165 if (!check_pixels_v(img, pixels_img[0], expect_img[0])) {
166 printf(" Source: image\n");
167 return false;
170 return true;
173 static bool
174 run_test(const struct image_op_info *op,
175 unsigned w, unsigned h,
176 bool (*check)(const struct grid_info grid,
177 const struct image_info img,
178 unsigned w, unsigned h),
179 const char *body)
181 const struct grid_info grid =
182 grid_info(GL_FRAGMENT_SHADER, GL_R32UI, W, H);
183 const struct image_info img = image_info_for_grid(grid);
184 GLuint prog = generate_program(
185 grid, GL_FRAGMENT_SHADER,
186 concat(image_hunk(img, ""),
187 hunk("IMAGE_UNIFORM_T img;\n"),
188 hunk(op->hunk),
189 hunk(body), NULL));
190 bool ret = prog &&
191 init_fb(grid) &&
192 init_image(img) &&
193 set_uniform_int(prog, "img", 0) &&
194 draw_grid(set_grid_size(grid, w, h), prog) &&
195 check(grid, img, w, h);
197 glDeleteProgram(prog);
198 return ret;
201 void
202 piglit_init(int argc, char **argv)
204 enum piglit_result status = PIGLIT_PASS;
205 const struct image_op_info *op;
207 piglit_require_extension("GL_ARB_shader_image_load_store");
209 for (op = image_ops; op->name; ++op) {
211 * Draw a rectangle discarding a subset of the
212 * fragments before inc() is run, then make sure that
213 * it had no effect for those fragments.
215 subtest(&status, true,
216 run_test(op, W, H, check_discard,
217 "GRID_T op(ivec2 idx, GRID_T x) {\n"
218 " if (idx.x % 5 == 0)\n"
219 " discard;\n"
220 " inc(idx);\n"
221 " return x;\n"
222 "}\n"),
223 "%s/discard test", op->name);
226 * Draw a 1-pixel wide rectangle and make a derivative
227 * computation in the orthogonal direction to get the
228 * GPU to run fragment shader invocations located
229 * outside the primitive, then make sure that inc()
230 * had no effect for those fragments.
232 subtest(&status, true,
233 run_test(op, W - 3, 1, check_derivative,
234 "GRID_T op(ivec2 idx, GRID_T x) {\n"
235 " x = uvec4(1000 * dFdy(vec4("
236 " imageLoad(img, IMAGE_ADDR(idx)))));"
237 " inc(idx);\n"
238 " return x;\n"
239 "}\n"),
240 "%s/derivative test", op->name);
243 piglit_report_result(status);
246 enum piglit_result
247 piglit_display(void)
249 return PIGLIT_FAIL;