ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / arb_shader_image_size / builtin.c
blobb7285299cd5f7905bda9f7f8dd647835c74ce655
1 /*
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
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
21 * DEALINGS IN THE SOFTWARE.
24 /** @file builtin.c
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"
43 * Syntax:
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)
56 * Description:
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
76 static bool
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);
81 bool ret;
83 ret = upload_image(img, unit, pixels);
85 free(pixels);
86 return ret;
89 static bool
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);
95 bool ret;
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,
115 1.0, 1.0);
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);
124 } else {
125 ret &= check_pixels(img, pixels, img_src.size.x, img_src.size.y,
126 img_src.size.z, img_src.size.w);
129 free(pixels);
130 return ret;
133 static bool
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,
140 16, 16);
141 const struct image_info img = {
142 target, format, size,
143 image_format_epsilon(grid.format)
145 GLuint prog = generate_program(
146 grid, stage->stage,
147 concat(hunk("#extension GL_ARB_shader_image_size : enable\n"),
148 image_hunk(img, ""),
149 hunk("readonly IMAGE_UNIFORM_T src_img;\n"
150 "\n"
151 "GRID_T op(ivec2 idx, GRID_T x) {\n"
152 " return ivec4(imageSize(src_img), ivec3(1));\n"
153 "}\n"), NULL));
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) &&
158 check(grid, img);
160 glDeleteProgram(prog);
161 return ret;
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;
170 int i;
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. */
179 ext.y = ext.x;
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
184 * interesting. */
185 ext.x = image_target_samples(target);
188 return ext;
191 static bool
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
198 * square. */
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);
205 static bool
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;
213 static bool
214 is_format_interesting(const struct image_format_info *format, bool override)
216 switch(format->format)
218 case GL_RGBA32F:
219 case GL_RGBA16F:
220 case GL_RGBA32I:
221 case GL_RGBA16I:
222 case GL_RGBA8I:
223 case GL_RGBA32UI:
224 case GL_RGBA16UI:
225 case GL_RGBA8UI:
226 return true;
227 default:
228 return override;
232 static bool
233 is_stage_interesting(const struct image_stage_info *stage, bool override)
235 switch(stage->stage)
237 case GL_FRAGMENT_SHADER:
238 case GL_COMPUTE_SHADER:
239 return true;
240 default:
241 return override;
245 static void
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)
252 int d;
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);
258 if (quick ||
259 !is_test_reasonable(!slow, size) ||
260 !is_format_interesting(format, slow) ||
261 !is_stage_interesting(stage, slow))
262 continue;
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);
273 static void
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,
278 bool slow)
280 const struct image_extent size =
281 image_extent_for_target(target,
282 16, 96);
284 if (!is_format_interesting(format, slow) ||
285 !is_stage_interesting(stage, slow))
286 return;
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);
295 void
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,
315 stage, &status,
316 slow);
318 test_max_dimensions(format, target,
319 stage, &status,
320 quick, slow);
325 piglit_report_result(status);
328 enum piglit_result
329 piglit_display(void)
331 return PIGLIT_FAIL;