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
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
26 * Test all allowed combinations of image targets, formats, built-in
27 * functions and shader stages. The test initializes an image to some
28 * arbitrary pattern and runs N invocations of a shader that calls the
29 * built-in function once on the corresponding location of the image.
30 * Then the same operation is simulated on the CPU and the results are
31 * compared with each other.
36 /** Window width. The actual width of the image varies with the image
37 * dimensionality, but the total number of pixels \a N remains
44 /** Total number of pixels in the window and image. */
47 PIGLIT_GL_TEST_CONFIG_BEGIN
49 config
.supports_gl_core_version
= 32;
51 config
.window_width
= W
;
52 config
.window_height
= H
;
53 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
54 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
56 PIGLIT_GL_TEST_CONFIG_END
58 struct image_op_info
{
59 /** Image built-in name. */
62 /** Allowed image formats. */
63 const struct image_format_info
*formats
;
65 /** Execute this image built-in on the CPU. */
66 void (*exec
)(const struct image_format_info
*format
,
67 const uint32_t *arg
, uint32_t *img
, uint32_t *ret
);
69 /** GLSL statement that invokes this image built-in. */
74 image_exec_load(const struct image_format_info
*format
,
75 const uint32_t *arg
, uint32_t *img
, uint32_t *ret
)
79 for (i
= 0; i
< image_num_components(format
); ++i
)
84 image_exec_store(const struct image_format_info
*format
,
85 const uint32_t *arg
, uint32_t *img
, uint32_t *ret
)
89 for (i
= 0; i
< image_num_components(format
); ++i
)
92 for (i
= 0; i
< 4; ++i
)
97 image_exec_add(const struct image_format_info
*format
,
98 const uint32_t *arg
, uint32_t *img
, uint32_t *ret
)
101 img
[0] = encode(format
, (decode(format
, img
[0]) +
102 decode(format
, arg
[0])));
106 image_exec_min(const struct image_format_info
*format
,
107 const uint32_t *arg
, uint32_t *img
, uint32_t *ret
)
110 img
[0] = encode(format
, MIN2(decode(format
, img
[0]),
111 decode(format
, arg
[0])));
115 image_exec_max(const struct image_format_info
*format
,
116 const uint32_t *arg
, uint32_t *img
, uint32_t *ret
)
119 img
[0] = encode(format
, MAX2(decode(format
, img
[0]),
120 decode(format
, arg
[0])));
124 image_exec_and(const struct image_format_info
*format
,
125 const uint32_t *arg
, uint32_t *img
, uint32_t *ret
)
128 img
[0] = img
[0] & arg
[0];
132 image_exec_or(const struct image_format_info
*format
,
133 const uint32_t *arg
, uint32_t *img
, uint32_t *ret
)
136 img
[0] = img
[0] | arg
[0];
140 image_exec_xor(const struct image_format_info
*format
,
141 const uint32_t *arg
, uint32_t *img
, uint32_t *ret
)
144 img
[0] = img
[0] ^ arg
[0];
148 image_exec_exchange(const struct image_format_info
*format
,
149 const uint32_t *arg
, uint32_t *img
, uint32_t *ret
)
156 image_exec_comp_swap(const struct image_format_info
*format
,
157 const uint32_t *arg
, uint32_t *img
, uint32_t *ret
)
160 img
[0] = (img
[0] == encode(format
, image_format_scale(format
).x
/ N
) ?
164 static const struct image_op_info image_ops
[] = {
166 "imageLoad", image_formats_load_store
, image_exec_load
,
167 "GRID_T op(ivec2 idx, GRID_T x) {\n"
168 " return imageLoad(img, IMAGE_ADDR(idx));\n"
172 "imageStore", image_formats_load_store
, image_exec_store
,
173 "GRID_T op(ivec2 idx, GRID_T x) {\n"
174 " imageStore(img, IMAGE_ADDR(idx), arg(idx));\n"
179 "imageAtomicAdd", image_formats_atomic
, image_exec_add
,
180 "GRID_T op(ivec2 idx, GRID_T x) {\n"
181 " return GRID_T(imageAtomicAdd(img, IMAGE_ADDR(idx),"
187 "imageAtomicMin", image_formats_atomic
, image_exec_min
,
188 "GRID_T op(ivec2 idx, GRID_T x) {\n"
189 " return GRID_T(imageAtomicMin(img, IMAGE_ADDR(idx),"
195 "imageAtomicMax", image_formats_atomic
, image_exec_max
,
196 "GRID_T op(ivec2 idx, GRID_T x) {\n"
197 " return GRID_T(imageAtomicMax(img, IMAGE_ADDR(idx),"
203 "imageAtomicAnd", image_formats_atomic
, image_exec_and
,
204 "GRID_T op(ivec2 idx, GRID_T x) {\n"
205 " return GRID_T(imageAtomicAnd(img, IMAGE_ADDR(idx),"
211 "imageAtomicOr", image_formats_atomic
, image_exec_or
,
212 "GRID_T op(ivec2 idx, GRID_T x) {\n"
213 " return GRID_T(imageAtomicOr(img, IMAGE_ADDR(idx),"
219 "imageAtomicXor", image_formats_atomic
, image_exec_xor
,
220 "GRID_T op(ivec2 idx, GRID_T x) {\n"
221 " return GRID_T(imageAtomicXor(img, IMAGE_ADDR(idx),"
227 "imageAtomicExchange", image_formats_atomic
, image_exec_exchange
,
228 "GRID_T op(ivec2 idx, GRID_T x) {\n"
229 " return GRID_T(imageAtomicExchange(img, IMAGE_ADDR(idx),"
235 "imageAtomicCompSwap", image_formats_atomic
, image_exec_comp_swap
,
236 "GRID_T op(ivec2 idx, GRID_T x) {\n"
237 " return GRID_T(imageAtomicCompSwap(img, IMAGE_ADDR(idx),"
238 " BASE_T(SCALE.x / N),"
247 init_image_pixels(const struct image_info img
, unsigned unit
,
250 const unsigned m
= image_num_components(img
.format
);
253 for (i
= 0; i
< m
* N
; ++i
)
254 r_pixels
[i
] = encode(img
.format
,
255 get_idx(image_format_scale(img
.format
), i
% m
)
256 * (unit
== 0 ? i
: m
* N
- i
) / (m
* N
));
262 init_image(const struct image_info img
, unsigned unit
)
264 uint32_t pixels
[4 * N
];
266 return init_image_pixels(img
, unit
, pixels
) &&
267 upload_image(img
, unit
, pixels
);
271 check(const struct image_op_info
*op
,
272 const struct grid_info grid
,
273 const struct image_info img
)
275 const struct image_info grid_img
= {
276 get_image_target(GL_TEXTURE_2D
),
277 grid
.format
, grid
.size
, img
.epsilon
279 const unsigned m
= image_num_components(img
.format
);
280 uint32_t pixels_fb
[4 * N
], expect_fb
[4 * N
];
281 uint32_t pixels_img
[4 * N
], expect_img
[4 * N
];
285 if (!download_result(grid
, pixels_fb
) ||
286 !download_image(img
, 0, pixels_img
))
289 /* Initialize the image and argument to the known state. */
290 init_image_pixels(img
, 0, expect_img
);
291 init_image_pixels(img
, 1, arg
);
292 init_pixels(grid_img
, expect_fb
, 0, 0, 0, 1);
294 /* Calculate the result of the image built-in. */
295 for (i
= 0; i
< N
; ++i
)
296 op
->exec(img
.format
, &arg
[m
* i
], &expect_img
[m
* i
],
299 /* Check that the shader gave the same result. */
300 if (!check_pixels_v(grid_img
, pixels_fb
, expect_fb
)) {
301 printf(" Source: framebuffer\n");
305 if (!check_pixels_v(img
, pixels_img
, expect_img
)) {
306 printf(" Source: image\n");
314 run_test(const struct image_op_info
*op
,
315 const struct image_stage_info
*stage
,
316 const struct image_format_info
*format
,
317 const struct image_target_info
*target
)
319 const struct grid_info grid
= grid_info(
320 stage
->stage
, image_base_internal_format(format
), W
, H
);
321 const struct image_info img
= image_info(
322 target
->target
, format
->format
, W
, H
);
323 GLuint prog
= generate_program(
325 concat(image_hunk(img
, ""),
326 hunk("IMAGE_UNIFORM_T img;\n"
327 "IMAGE_UNIFORM_T arg_img;\n"
329 "GRID_T arg(ivec2 idx) {\n"
330 " return imageLoad(arg_img, IMAGE_ADDR(idx));\n"
332 hunk(op
->hunk
), NULL
));
333 bool ret
= prog
&& init_fb(grid
) &&
334 init_image(img
, 0) &&
335 init_image(img
, 1) &&
336 set_uniform_int(prog
, "img", 0) &&
337 set_uniform_int(prog
, "arg_img", 1) &&
338 draw_grid(grid
, prog
) &&
339 check(op
, grid
, img
);
341 glDeleteProgram(prog
);
346 piglit_init(int argc
, char **argv
)
349 * If quick is enabled traverse each variable (stage, op,
350 * format and target) in sequence leaving the other ones fixed
351 * instead of going through the cartesian product of the four
354 const bool quick
= (argc
>= 2 && !strcmp(argv
[1], "--quick"));
355 enum piglit_result status
= PIGLIT_PASS
;
356 const struct image_stage_info
*stage
;
357 const struct image_op_info
*op
;
358 const struct image_format_info
*format
;
359 const struct image_target_info
*target
;
362 piglit_require_extension("GL_ARB_shader_image_load_store");
363 piglit_require_extension("GL_ARB_texture_cube_map_array");
365 for (op
= image_ops
; op
->name
; ++op
) {
366 for (stage
= image_stages(); stage
->name
; ++stage
) {
367 for (format
= op
->formats
; format
->name
; ++format
) {
368 for (target
= image_targets(); target
->name
; ++target
) {
369 subtest(&status
, true,
370 run_test(op
, stage
, format
, target
),
371 "%s/%s shader/%s/image%s test",
372 op
->name
, stage
->name
,
373 format
->name
, target
->name
);
375 if (quick
&& (m
& 1))
379 if (quick
&& ((m
|= 1) & 2))
383 if (quick
&& ((m
|= 2) & 4))
391 piglit_report_result(status
);