2 * Copyright 2015 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
21 * DEALINGS IN THE SOFTWARE.
26 * Tests GLSL's imageSize builtin. The code is highly-based on
27 * image_load_store's max-size test from Francisco Jerez. It also uses the
28 * grid framework he introduced.
30 * From GL_ARB_shader_image_size's spec:
32 * "Including the following line in a shader can be used to control the
33 * language features described in this extension:
35 * #extension GL_ARB_shader_image_size
37 * A new preprocessor #define is added to the OpenGL Shading Language:
39 * #define GL_ARB_shader_image_size 1
41 * Add to section 8.11 "Image Functions"
44 * int imageSize(gimage1D image)
45 * ivec2 imageSize(gimage2D image)
46 * ivec3 imageSize(gimage3D image)
47 * ivec2 imageSize(gimageCube image)
48 * ivec3 imageSize(gimageCubeArray image)
49 * ivec2 imageSize(gimageRect image)
50 * ivec2 imageSize(gimage1DArray image)
51 * ivec3 imageSize(gimage2DArray image)
52 * int imageSize(gimageBuffer image)
53 * ivec2 imageSize(gimage2DMS image)
54 * ivec3 imageSize(gimage2DMSArray image)
58 * Returns the dimensions of the image or images bound to <image>. For
59 * arrayed images, the last component of the return value will hold the
60 * size of the array. Cube images return the dimensions of one face, and
61 * number of cubes in the cube map array, if arrayed."
64 #include "../arb_shader_image_load_store/common.h"
65 #include "piglit-util-gl.h"
67 PIGLIT_GL_TEST_CONFIG_BEGIN
69 config
.supports_gl_core_version
= 32;
71 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
|
72 PIGLIT_GL_VISUAL_DOUBLE
;
74 PIGLIT_GL_TEST_CONFIG_END
77 randomize_image(const struct image_info img
, unsigned unit
)
79 const unsigned n
= image_num_components(img
.format
) * product(img
.size
);
80 uint32_t *pixels
= malloc(sizeof(uint32_t) * n
);
83 ret
= upload_image(img
, unit
, pixels
);
90 check(const struct grid_info grid
, struct image_info img_src
)
92 struct image_info img
= image_info_for_grid(grid
);
93 const unsigned n
= image_num_components(img
.format
) * product(img
.size
);
94 uint32_t *pixels
= malloc(sizeof(uint32_t) * n
);
97 ret
= download_result(grid
, pixels
);
99 if (img_src
.target
->target
== GL_TEXTURE_CUBE_MAP_ARRAY
) {
100 /* Unlike image-load-store's size (exported by the framework
101 * used for this test), image-size reports the third
102 * coordinate of cubemap arrays as the number of cubes and not
103 * the number of faces. Correct for this by dividing by 6.
105 ret
&= check_pixels(img
, pixels
, img_src
.size
.x
, img_src
.size
.y
,
106 img_src
.size
.z
/ 6.0, img_src
.size
.w
);
107 } else if (img_src
.target
->target
== GL_TEXTURE_CUBE_MAP
) {
108 /* Unlike image-load-store's size (exported by the framework
109 * used for this test), image-size reports only the size of one
110 * face, not including the number of faces. From the
111 * ARB_shader_image_size extension:
112 * "Cube images return the dimensions of one face."
114 ret
&= check_pixels(img
, pixels
, img_src
.size
.x
, img_src
.size
.y
,
116 } else if (image_target_samples(img_src
.target
) > 1) {
117 /* Unlike image-load-store's size (exported by the framework
118 * used for this test), image-size does not report the sample
119 * count as the first component. Let's fix this by shiftling
120 * left the components.
122 ret
&= check_pixels(img
, pixels
, img_src
.size
.y
, img_src
.size
.z
,
123 img_src
.size
.w
, 1.0);
125 ret
&= check_pixels(img
, pixels
, img_src
.size
.x
, img_src
.size
.y
,
126 img_src
.size
.z
, img_src
.size
.w
);
134 run_test(const struct image_format_info
*format
,
135 const struct image_target_info
*target
,
136 const struct image_stage_info
*stage
,
137 const struct image_extent size
)
139 const struct grid_info grid
= grid_info(stage
->stage
, GL_RGBA32I
,
141 const struct image_info img
= {
142 target
, format
, size
,
143 image_format_epsilon(grid
.format
)
145 GLuint prog
= generate_program(
147 concat(hunk("#extension GL_ARB_shader_image_size : enable\n"),
149 hunk("readonly IMAGE_UNIFORM_T src_img;\n"
151 "GRID_T op(ivec2 idx, GRID_T x) {\n"
152 " return ivec4(imageSize(src_img), ivec3(1));\n"
154 bool ret
= prog
&& init_fb(grid
) &&
155 randomize_image(img
, 0) &&
156 set_uniform_int(prog
, "src_img", 0) &&
157 draw_grid(grid
, prog
) &&
160 glDeleteProgram(prog
);
164 static struct image_extent
165 get_test_extent(const struct image_target_info
*target
, unsigned d
)
167 const struct image_extent ls
= image_target_limits(target
);
168 const unsigned high
= ~0, low
= 8;
169 struct image_extent ext
;
172 for (i
= 0; i
< 4; ++i
)
173 set_idx(ext
, i
, MIN2(get_idx(ls
, i
), (i
== d
? high
: low
)));
175 if (target
->target
== GL_TEXTURE_CUBE_MAP
||
176 target
->target
== GL_TEXTURE_CUBE_MAP_ARRAY
) {
177 /* Cube maps have to be square and the number of faces
178 * should be a multiple of six. */
180 ext
.z
= 6 * MAX2(ext
.z
/ 6, 1);
182 } else if (image_target_samples(target
) > 1) {
183 /* Use the maximum number of samples to keep things
185 ext
.x
= image_target_samples(target
);
192 should_test_dimension(const struct image_target_info
*target
, int d
)
194 const struct image_extent ls
= image_target_limits(target
);
196 return get_idx(ls
, d
) > 1 &&
197 /* Skip second cube map dimension as faces have to be
199 !(target
->target
== GL_TEXTURE_CUBE_MAP
&& d
>= 1) &&
200 !(target
->target
== GL_TEXTURE_CUBE_MAP_ARRAY
&& d
== 1) &&
201 /* Skip sample dimension. */
202 !(image_target_samples(target
) > 1 && d
== 0);
206 is_test_reasonable(bool quick
, const struct image_extent size
)
208 /* Set an arbitrary limit on the number of texels so the test
209 * doesn't take forever. */
210 return product(size
) < (quick
? 4 : 64) * 1024 * 1024;
214 is_format_interesting(const struct image_format_info
*format
, bool override
)
216 switch(format
->format
)
233 is_stage_interesting(const struct image_stage_info
*stage
, bool override
)
237 case GL_FRAGMENT_SHADER
:
238 case GL_COMPUTE_SHADER
:
246 test_max_dimensions(const struct image_format_info
*format
,
247 const struct image_target_info
*target
,
248 const struct image_stage_info
*stage
,
249 enum piglit_result
*status
,
250 bool quick
, bool slow
)
253 for (d
= 0; d
< 4; ++d
) {
254 if (should_test_dimension(target
, d
)) {
255 const struct image_extent size
=
256 get_test_extent(target
, d
);
259 !is_test_reasonable(!slow
, size
) ||
260 !is_format_interesting(format
, slow
) ||
261 !is_stage_interesting(stage
, slow
))
264 subtest(status
, true,
265 run_test(format
, target
, stage
, size
),
266 "%s/%s/image%s max size test/%dx%dx%dx%d",
267 format
->name
, stage
->name
, target
->name
,
268 size
.x
, size
.y
, size
.z
, size
.w
);
274 test_small_dimensions(const struct image_format_info
*format
,
275 const struct image_target_info
*target
,
276 const struct image_stage_info
*stage
,
277 enum piglit_result
*status
,
280 const struct image_extent size
=
281 image_extent_for_target(target
,
284 if (!is_format_interesting(format
, slow
) ||
285 !is_stage_interesting(stage
, slow
))
288 subtest(status
, true,
289 run_test(format
, target
, stage
, size
),
290 "%s/%s/image%s size test/%dx%dx%dx%d",
291 format
->name
, stage
->name
, target
->name
,
292 size
.x
, size
.y
, size
.z
, size
.w
);
296 piglit_init(int argc
, char **argv
)
298 const bool quick
= (argc
>= 2 && !strcmp(argv
[1], "--quick"));
299 const bool slow
= (argc
>= 2 && !strcmp(argv
[1], "--slow"));
300 enum piglit_result status
= PIGLIT_PASS
;
301 const struct image_format_info
*format
;
302 const struct image_target_info
*target
;
303 const struct image_stage_info
*stage
;
305 /* The spec of the extension says we should require GL 4.2 but let's
306 * just request GL_ARB_shader_image_size which will in turn require
307 * GL_ARB_shader_image_load_store which should be sufficient.
309 piglit_require_extension("GL_ARB_shader_image_size");
311 for (format
= image_formats_load_store
; format
->format
; ++format
) {
312 for (stage
= image_stages(); stage
->stage
; ++stage
) {
313 for (target
= image_targets(); target
->name
; ++target
) {
314 test_small_dimensions(format
, target
,
318 test_max_dimensions(format
, target
,
325 piglit_report_result(status
);