ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / arb_shader_image_load_store / invalid.c
blob7193042371767ee4994c16905b54bb50ac5eb1ff
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 invalid.c
26 * The ARB_shader_image_load_store extension defines an image access
27 * to be invalid when certain conditions are met, in which case image
28 * stores and atomics are defined to have no effect and image loads
29 * and atomics give zero as result. This test causes such invalid
30 * accesses and checks that the result is as expected and that no data
31 * is accidentally overwritten.
33 * The spec describes other conditions that cause an image access to
34 * have undefined results. In those cases we simply check that the
35 * undefined access didn't lead to program termination.
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 /** Allowed image formats. */
65 const struct image_format_info *formats;
67 /** GLSL statement that invokes this image built-in. */
68 const char *hunk;
71 static const struct image_op_info image_ops[] = {
73 "imageLoad", image_formats_load_store,
74 "GRID_T op(ivec2 idx, GRID_T x) {\n"
75 " return imageLoad(imgs[u], off + IMAGE_ADDR(idx));\n"
76 "}\n"
79 "imageStore", image_formats_load_store,
80 "GRID_T op(ivec2 idx, GRID_T x) {\n"
81 " imageStore(imgs[u], off + IMAGE_ADDR(idx), DATA_T(33));\n"
82 " return GRID_T(0, 0, 0, SCALE.w == 0 ? 1 : 0);"
83 "}\n"
86 "imageAtomicAdd", image_formats_atomic,
87 "GRID_T op(ivec2 idx, GRID_T x) {\n"
88 " return GRID_T(imageAtomicAdd(imgs[u],"
89 " off + IMAGE_ADDR(idx),"
90 " BASE_T(33)),"
91 " 0, 0, 1);\n"
92 "}\n"
95 "imageAtomicMin", image_formats_atomic,
96 "GRID_T op(ivec2 idx, GRID_T x) {\n"
97 " return GRID_T(imageAtomicMin(imgs[u],"
98 " off + IMAGE_ADDR(idx),"
99 " BASE_T(33)),"
100 " 0, 0, 1);\n"
101 "}\n"
104 "imageAtomicMax", image_formats_atomic,
105 "GRID_T op(ivec2 idx, GRID_T x) {\n"
106 " return GRID_T(imageAtomicMax(imgs[u],"
107 " off + IMAGE_ADDR(idx),"
108 " BASE_T(33)),"
109 " 0, 0, 1);\n"
110 "}\n"
113 "imageAtomicAnd", image_formats_atomic,
114 "GRID_T op(ivec2 idx, GRID_T x) {\n"
115 " return GRID_T(imageAtomicAnd(imgs[u],"
116 " off + IMAGE_ADDR(idx),"
117 " BASE_T(33)),"
118 " 0, 0, 1);\n"
119 "}\n"
122 "imageAtomicOr", image_formats_atomic,
123 "GRID_T op(ivec2 idx, GRID_T x) {\n"
124 " return GRID_T(imageAtomicOr(imgs[u],"
125 " off + IMAGE_ADDR(idx),"
126 " BASE_T(33)),"
127 " 0, 0, 1);\n"
128 "}\n"
131 "imageAtomicXor", image_formats_atomic,
132 "GRID_T op(ivec2 idx, GRID_T x) {\n"
133 " return GRID_T(imageAtomicXor(imgs[u],"
134 " off + IMAGE_ADDR(idx),"
135 " BASE_T(33)),"
136 " 0, 0, 1);\n"
137 "}\n"
140 "imageAtomicExchange", image_formats_atomic,
141 "GRID_T op(ivec2 idx, GRID_T x) {\n"
142 " return GRID_T(imageAtomicExchange(imgs[u],"
143 " off + IMAGE_ADDR(idx),"
144 " BASE_T(33)),"
145 " 0, 0, 1);\n"
146 "}\n"
149 "imageAtomicCompSwap", image_formats_atomic,
150 "GRID_T op(ivec2 idx, GRID_T x) {\n"
151 " return GRID_T(imageAtomicCompSwap(imgs[u],"
152 " off + IMAGE_ADDR(idx),"
153 " BASE_T(0), BASE_T(33)),"
154 " 0, 0, 1);\n"
155 "}\n"
157 { 0 }
160 static bool
161 init_image(const struct image_info img, GLuint prog)
163 uint32_t pixels[4 * N];
165 return init_pixels(img, pixels, 1, 1, 1, 1) &&
166 upload_image(img, 0, pixels) &&
167 set_uniform_int(prog, "imgs[0]", 0);
170 static bool
171 init_level(const struct image_info img, unsigned level,
172 GLenum format, unsigned w, unsigned h)
174 uint32_t pixels[4 * N];
176 init_pixels(img, pixels, 1, 1, 1, 1);
177 glBindTexture(GL_TEXTURE_2D, get_texture(0));
178 glTexImage2D(GL_TEXTURE_2D, level, format,
179 w, h, 0, img.format->pixel_format,
180 image_base_type(img.format), pixels);
182 return piglit_check_gl_error(GL_NO_ERROR);
185 static bool
186 check(const struct grid_info grid, const struct image_info img)
188 uint32_t pixels_fb[4 * N], pixels_img[4 * N];
190 if (!download_result(grid, pixels_fb) ||
191 !download_image(img, 0, pixels_img))
192 return false;
194 /* Check that the built-in return value is zero (nonexisting texel). */
195 if (!check_pixels(image_info_for_grid(grid), pixels_fb, 0, 0, 0,
196 (image_num_components(img.format) < 4 ? 1 : 0))) {
197 printf(" Source: framebuffer\n");
198 return false;
201 /* Check that the image wasn't modified. */
202 if (!check_pixels(img, pixels_img, 1, 1, 1, 1)) {
203 printf(" Source: image\n");
204 return false;
207 return true;
210 static bool
211 invalidate_unbound(const struct image_info img, GLuint prog)
213 glBindImageTexture(0, 0, 0, GL_FALSE, 0, GL_READ_ONLY,
214 img.format->format);
216 return piglit_check_gl_error(GL_NO_ERROR);
219 static bool
220 invalidate_incomplete(const struct image_info img, GLuint prog)
222 /* Bind a mipmap level with incorrect dimensions so the
223 * texture becomes incomplete. */
224 bool ret = init_level(img, 1, img.format->format, W, H);
226 glBindImageTexture(0, get_texture(0), 1, GL_TRUE, 0, GL_READ_WRITE,
227 img.format->format);
229 return ret && piglit_check_gl_error(GL_NO_ERROR);
232 static bool
233 invalidate_level_bounds(const struct image_info img, GLuint prog)
235 const int level = 1;
236 const struct image_extent size = image_level_size(img, level);
237 /* Create a second mipmap level */
238 bool ret = init_level(img, level, img.format->format, size.x, size.y);
240 /* and set it as base level, */
241 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, &level);
243 /* but keep the the first level bound. */
244 glBindImageTexture(0, get_texture(0), 0, GL_TRUE, 0, GL_READ_WRITE,
245 img.format->format);
247 return ret && piglit_check_gl_error(GL_NO_ERROR);
250 static bool
251 invalidate_invalid_format(const struct image_info img, GLuint prog)
253 const GLenum base_format = image_base_internal_format(img.format);
254 /* Pick an invalid texture format with a compatible base
255 * type. */
256 bool ret = init_level(img, 0, (base_format == GL_RGBA32F ?
257 GL_RGB5_A1 : GL_RGB8UI), W, H);
259 glBindImageTexture(0, get_texture(0), 0, GL_TRUE, 0,
260 GL_READ_WRITE, img.format->format);
262 return ret && piglit_check_gl_error(GL_NO_ERROR);
265 static bool
266 invalidate_incompatible_format(const struct image_info img, GLuint prog)
268 GLenum base_format = image_base_internal_format(img.format);
269 /* Pick an incompatible texture format with a compatible base
270 * type. */
271 glBindImageTexture(0, get_texture(0), 0, GL_TRUE, 0,
272 GL_READ_WRITE, (base_format == GL_RGBA32F ?
273 GL_RGBA8 : GL_RG32UI));
275 return piglit_check_gl_error(GL_NO_ERROR);
278 static bool
279 invalidate_layer_bounds(const struct image_info img, GLuint prog)
281 glBindImageTexture(0, get_texture(0), 0, GL_FALSE, N,
282 GL_READ_WRITE, img.format->format);
284 return piglit_check_gl_error(GL_NO_ERROR);
287 static bool
288 invalidate_address_bounds(const struct image_info img, GLuint prog)
290 return set_uniform_int(prog, "off", N);
293 static bool
294 invalidate_index_bounds(const struct image_info img, GLuint prog)
296 return set_uniform_int(prog, "u", 0xdeadcafe);
299 static bool
300 invalidate_nop(const struct image_info img, GLuint prog)
302 return true;
305 static bool
306 run_test(const struct image_op_info *op,
307 const struct image_info real_img,
308 const struct image_info prog_img,
309 bool (*invalidate)(const struct image_info, GLuint),
310 bool control_test)
312 const struct grid_info grid =
313 grid_info(GL_FRAGMENT_SHADER,
314 image_base_internal_format(real_img.format), W, H);
315 GLuint prog = generate_program(
316 grid, GL_FRAGMENT_SHADER,
317 concat(image_hunk(prog_img, ""),
318 hunk("IMAGE_UNIFORM_T imgs[1];\n"
319 "uniform int u;\n"
320 "uniform int off;\n"),
321 hunk(op->hunk),
322 NULL));
323 bool ret = prog &&
324 init_fb(grid) &&
325 init_image(real_img, prog) &&
326 invalidate(real_img, prog) &&
327 draw_grid(grid, prog) &&
328 (check(grid, real_img) || control_test);
330 glDeleteProgram(prog);
331 return ret;
334 void
335 piglit_init(int argc, char **argv)
337 enum piglit_result status = PIGLIT_PASS;
338 const struct image_op_info *op;
339 const struct image_format_info *format;
340 const struct image_target_info *target;
342 piglit_require_extension("GL_ARB_shader_image_load_store");
344 for (op = image_ops; op->name; ++op) {
345 const struct image_info def_img = image_info(
346 GL_TEXTURE_2D, op->formats[0].format, W, H);
347 const struct image_info def_img_buffer = image_info(
348 GL_TEXTURE_BUFFER, op->formats[0].format, W, H);
351 * According to the spec, an access is considered
352 * invalid in the following cases, in which image
353 * stores and atomics should have no effect, and image
354 * loads should return zero:
356 * " * no texture is bound to the selected image unit;
357 * [...]"
359 subtest(&status, true,
360 run_test(op, def_img, def_img,
361 invalidate_unbound, false),
362 "%s/unbound image test", op->name);
365 * " * the texture bound to the selected image unit is
366 * incomplete; [...]"
368 subtest(&status, true,
369 run_test(op, def_img, def_img,
370 invalidate_incomplete, false),
371 "%s/incomplete image test", op->name);
374 * " * the texture level bound to the image unit is
375 * less than the base level or greater than the
376 * maximum level of the texture; [...]"
378 subtest(&status, true,
379 run_test(op, def_img, def_img,
380 invalidate_level_bounds, false),
381 "%s/level bounds test", op->name);
384 * " * the internal format of the texture bound to the
385 * image unit is not found in Table X.2; [...]"
387 subtest(&status, true,
388 run_test(op, def_img, def_img,
389 invalidate_invalid_format, false),
390 "%s/invalid format test", op->name);
393 * " * the internal format of the texture bound to the
394 * image unit is incompatible with the specified
395 * <format> according to Table X.3; [...]"
397 subtest(&status, true,
398 run_test(op, def_img, def_img,
399 invalidate_incompatible_format, false),
400 "%s/incompatible format test", op->name);
402 /* Test for the regression which happened when
403 * GL_TEXTURE_BUFFER was allowed to have incompatible format.
405 subtest(&status, true,
406 run_test(op, def_img_buffer, def_img_buffer,
407 invalidate_incompatible_format, false),
408 "%s/incompatible format test/image%s",
409 op->name, def_img_buffer.target->name);
412 * " * the texture bound to the image unit has layers,
413 * and the selected layer or cube map face doesn't
414 * exist; [...]"
416 subtest(&status, true,
417 run_test(op,
418 image_info(GL_TEXTURE_2D_ARRAY,
419 op->formats[0].format, W, H),
420 def_img, invalidate_layer_bounds, false),
421 "%s/layer bounds test", op->name);
424 * " * the selected texel tau_i, tau_i_j, or tau_i_j_k
425 * doesn't exist; [...]"
427 for (target = image_targets(); target->name; ++target) {
428 const struct image_info img = image_info(
429 target->target, op->formats[0].format, W, H);
431 subtest(&status, true,
432 run_test(op, img, img,
433 invalidate_address_bounds, false),
434 "%s/address bounds test/image%s/%s",
435 op->name, img.target->name, img.format->name);
438 for (format = &op->formats[1]; format->name; ++format) {
439 const struct image_info img = image_info(
440 GL_TEXTURE_2D, format->format, W, H);
442 subtest(&status, true,
443 run_test(op, img, img,
444 invalidate_address_bounds, false),
445 "%s/address bounds test/image%s/%s",
446 op->name, img.target->name, img.format->name);
450 * The following cases have undefined results, but may
451 * not lead to program termination:
453 * "If the index used to select an individual [array]
454 * element is negative or greater than or equal to
455 * the size of the array [...]"
457 subtest(&status, true,
458 run_test(op, def_img, def_img,
459 invalidate_index_bounds, true),
460 "%s/index bounds test", op->name);
463 * "the type of image variable used to access the
464 * image unit does not match the target of a texture
465 * bound to the image unit [...]"
467 subtest(&status, true,
468 run_test(op, def_img,
469 image_info(GL_TEXTURE_3D,
470 op->formats[0].format, W, H),
471 invalidate_nop, true),
472 "%s/target mismatch test", op->name);
475 * "the format layout qualifier for an image variable
476 * used for an image load or atomic operation does
477 * not match the format of the image unit [...]"
479 subtest(&status, true,
480 run_test(op,
481 image_info(GL_TEXTURE_2D,
482 GL_R11F_G11F_B10F, W, H),
483 def_img, invalidate_nop, true),
484 "%s/format mismatch test", op->name);
488 piglit_report_result(status);
491 enum piglit_result
492 piglit_display(void)
494 return PIGLIT_FAIL;