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
24 /** @file max-images.c
26 * Check that images work as expected up to the reported limit of
27 * image units and the per-shader and combined limit of image
39 /** Total number of pixels in the window and images. */
42 PIGLIT_GL_TEST_CONFIG_BEGIN
44 config
.supports_gl_core_version
= 32;
46 config
.window_width
= W
;
47 config
.window_height
= H
;
48 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
49 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
51 PIGLIT_GL_TEST_CONFIG_END
54 * Return the total number of image uniforms used by the shader stages
55 * specified in the \a stages bit-field.
58 num_images_for_stages(const struct grid_info grid
, unsigned stages
)
60 const struct image_stage_info
*stage
;
63 for (stage
= image_stages(); stage
->name
; ++stage
) {
64 if (grid
.stages
& stages
& stage
->bit
)
65 n
+= image_stage_max_images(stage
);
69 return MIN2(max_combined_images(), n
);
73 * Return the total number of image uniforms used by the specified
77 num_images_for_stage(const struct grid_info grid
,
78 const struct image_stage_info
*stage
)
80 return num_images_for_stages(grid
, (stage
->bit
<< 1) - 1) -
81 num_images_for_stages(grid
, stage
->bit
- 1);
85 init_images(const struct image_info img
)
90 for (unit
= 0; unit
< max_image_units(); ++unit
) {
91 for (i
= 0; i
< N
; ++i
)
92 pixels
[i
] = (i
== unit
? 1 : 0);
94 if (!upload_image(img
, unit
, pixels
))
102 * Bind all image uniforms present in the program to the available
103 * image units, re-using the same unit several times if necessary in
107 bind_images(const struct grid_info grid
, GLuint prog
)
109 const unsigned m
= max_image_units();
110 const struct image_stage_info
*stage
;
112 for (stage
= image_stages(); stage
->name
; ++stage
) {
113 if (grid
.stages
& stage
->bit
) {
114 const unsigned first
=
115 num_images_for_stages(grid
, stage
->bit
- 1);
116 const unsigned n
= num_images_for_stage(grid
, stage
);
117 const unsigned stage_idx
= stage
- image_stages();
120 for (i
= 0; i
< n
; ++i
) {
123 (void)!asprintf(&name
, "imgs_%d[%d]", stage_idx
, i
);
125 if (!set_uniform_int(prog
, name
,
138 stage_hunk(const struct grid_info grid
,
139 const struct image_stage_info
*stage
)
143 (void)!asprintf(&s
, "#define IMGS imgs_%d\n"
144 "#define NUM_IMGS %d\n",
145 (int)(stage
- image_stages()),
146 num_images_for_stage(grid
, stage
));
151 generate_source(const struct grid_info grid
,
152 const struct image_info img
, GLuint s
)
154 const struct image_stage_info
*stage
= get_image_stage(s
);
156 if (stage
&& num_images_for_stage(grid
, stage
)) {
158 * Sum up the values read from corresponding locations
159 * of all bound image uniforms.
161 return concat(stage_hunk(grid
, stage
),
163 hunk("IMAGE_UNIFORM_T IMGS[NUM_IMGS];\n"
165 "GRID_T op(ivec2 idx, GRID_T x) {\n"
168 " for (i = 0; i < NUM_IMGS; ++i)\n"
169 " x += imageLoad(IMGS[i], IMAGE_ADDR(idx));\n"
180 check(const struct grid_info grid
, const struct image_info img
)
182 const int n
= num_images_for_stages(grid
, ~0);
183 const int m
= max_image_units();
184 uint32_t pixels
[N
], expect
[N
];
187 for (i
= 0; i
< N
; ++i
) {
190 * The sum at this location is just the number
191 * of times that the image with index i was
192 * bound to the pipeline.
194 expect
[i
] = (n
- i
+ m
- 1) / m
;
197 * No image has a non-zero value at this
198 * location, so the sum is zero.
204 return download_result(grid
, pixels
) &&
205 check_pixels_v(img
, pixels
, expect
);
209 run_test(GLbitfield shaders
)
211 const struct grid_info grid
= {
213 get_image_format(GL_R32UI
),
216 const struct image_info img
= image_info_for_grid(grid
);
217 GLuint prog
= generate_program(
220 generate_source(grid
, img
, GL_VERTEX_SHADER
),
221 GL_TESS_CONTROL_SHADER
,
222 generate_source(grid
, img
, GL_TESS_CONTROL_SHADER
),
223 GL_TESS_EVALUATION_SHADER
,
224 generate_source(grid
, img
, GL_TESS_EVALUATION_SHADER
),
226 generate_source(grid
, img
, GL_GEOMETRY_SHADER
),
228 generate_source(grid
, img
, GL_FRAGMENT_SHADER
),
230 generate_source(grid
, img
, GL_COMPUTE_SHADER
));
231 bool ret
= prog
&& init_fb(grid
) &&
233 bind_images(grid
, prog
) &&
234 draw_grid(grid
, prog
) &&
237 glDeleteProgram(prog
);
242 piglit_init(int argc
, char **argv
)
244 enum piglit_result status
= PIGLIT_PASS
;
245 const struct image_stage_info
*stage
;
247 piglit_require_extension("GL_ARB_shader_image_load_store");
249 for (stage
= image_stages(); stage
->name
; ++stage
) {
250 subtest(&status
, true,
251 run_test(stage
->bit
),
252 "%s shader max image uniforms test",
256 subtest(&status
, true,
257 run_test((get_image_stage(GL_VERTEX_SHADER
) ?
258 GL_VERTEX_SHADER_BIT
: 0) |
259 (get_image_stage(GL_TESS_CONTROL_SHADER
) ?
260 GL_TESS_CONTROL_SHADER_BIT
: 0) |
261 (get_image_stage(GL_TESS_EVALUATION_SHADER
) ?
262 GL_TESS_EVALUATION_SHADER_BIT
: 0) |
263 (get_image_stage(GL_GEOMETRY_SHADER
) ?
264 GL_GEOMETRY_SHADER_BIT
: 0) |
265 GL_FRAGMENT_SHADER_BIT
),
266 "Combined max image uniforms test");
268 piglit_report_result(status
);