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 * The spec defines two different image unit binding modes for
27 * textures with multiple layers, depending on the "layered" parameter
28 * of glBindImageTexture():
30 * "If <layered> is TRUE, the entire level is bound. If <layered> is
31 * FALSE, only the single layer identified by <layer> will be bound.
32 * When <layered> is FALSE, the single bound layer is treated as a
33 * different texture target for image accesses:
35 * * one-dimensional array texture layers are treated as one-dimensional
38 * * two-dimensional array, three-dimensional, cube map, cube map array
39 * texture layers are treated as two-dimensional textures; and
41 * * two-dimensional multisample array textures are treated as
42 * two-dimensional multisample textures."
44 * We check that this is the case by binding a texture of each target
45 * in layered or unlayered mode and then dumping all the accessible
46 * contents of the texture to the framebuffer from a fragment shader.
47 * After each individual texel is read its old contents are
48 * overwritten by the shader.
50 * For textures that don't have multiple layers we check that the
51 * described process reads and subsequently overwrites the full
52 * texture contents regardless of the values of the layered and layer
53 * parameters, since according to the spec:
55 * "If the texture identified by <texture> does not have multiple
56 * layers or faces, the entire texture level is bound, regardless of
57 * the values specified by <layered> and <layer>."
68 /** Total number of pixels in the window and image. */
71 PIGLIT_GL_TEST_CONFIG_BEGIN
73 config
.supports_gl_core_version
= 32;
75 config
.window_width
= W
;
76 config
.window_height
= H
;
77 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
78 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
80 PIGLIT_GL_TEST_CONFIG_END
83 init_image(const struct image_info img
, bool layered
, unsigned l
)
85 uint32_t pixels
[4 * N
];
89 for (i
= 0; i
< 4 * N
; ++i
)
90 pixels
[i
] = encode(img
.format
, i
);
92 ret
= upload_image(img
, 0, pixels
);
94 glBindImageTexture(0, get_texture(0), 0, layered
, l
,
95 GL_READ_WRITE
, img
.format
->format
);
97 return ret
&& piglit_check_gl_error(GL_NO_ERROR
);
101 check(const struct grid_info grid
, const struct image_info img
, unsigned l
)
103 const unsigned layer_sz
= 4 * product(grid
.size
);
104 uint32_t pixels_fb
[4 * N
], expect_fb
[4 * N
];
105 uint32_t pixels_img
[4 * N
], expect_img
[4 * N
];
108 if (!download_result(grid
, pixels_fb
) ||
109 !download_image(img
, 0, pixels_img
))
112 for (i
= 0; i
< layer_sz
; ++i
) {
114 * The framebuffer contents should reflect layer l of
115 * the image which is bound to the image unit.
117 expect_fb
[i
] = encode(grid
.format
, layer_sz
* l
+ i
);
120 for (i
= 0; i
< 4 * N
; ++i
) {
121 if (i
/ layer_sz
== l
) {
123 * Layer l should have been modified by the
126 expect_img
[i
] = encode(img
.format
, 33);
129 * Other layers should have remained
132 expect_img
[i
] = encode(img
.format
, i
);
136 if (!check_pixels_v(image_info_for_grid(grid
), pixels_fb
, expect_fb
)) {
137 printf(" Source: framebuffer\n");
141 if (!check_pixels_v(img
, pixels_img
, expect_img
)) {
142 printf(" Source: image\n");
150 * If \a layered is false, bind an individual layer of a texture to an
151 * image unit, read its contents and write back a different value to
152 * the same location. If \a layered is true or the texture has a
153 * single layer, the whole texture will be read and written back.
155 * For textures with a single layer, the arguments \a layered and \a
156 * layer which are passed to the same arguments of
157 * glBindImageTexture() should have no effect as required by the spec.
160 run_test(const struct image_target_info
*target
,
161 bool layered
, unsigned layer
)
163 const struct image_info real_img
= image_info(
164 target
->target
, GL_RGBA32F
, W
, H
);
165 const unsigned slices
= (layered
? 1 : image_num_layers(real_img
));
167 * "Slice" of the image that will be bound to the pipeline.
169 const struct image_info slice_img
= image_info(
170 (layered
? target
->target
: image_layer_target(target
)),
171 GL_RGBA32F
, W
, H
/ slices
);
173 * Grid with as many elements as the slice.
175 const struct grid_info grid
= grid_info(
176 GL_FRAGMENT_SHADER
, GL_RGBA32F
, W
, H
/ slices
);
177 GLuint prog
= generate_program(
178 grid
, GL_FRAGMENT_SHADER
,
179 concat(image_hunk(slice_img
, ""),
180 hunk("IMAGE_UNIFORM_T img;\n"
182 "GRID_T op(ivec2 idx, GRID_T x) {\n"
183 " GRID_T v = imageLoad(img, IMAGE_ADDR(idx));\n"
184 " imageStore(img, IMAGE_ADDR(idx), DATA_T(33));\n"
187 bool ret
= prog
&& init_fb(grid
) &&
188 init_image(real_img
, layered
, layer
) &&
189 set_uniform_int(prog
, "img", 0) &&
190 draw_grid(grid
, prog
) &&
191 check(grid
, real_img
, (slices
== 1 ? 0 : layer
));
193 glDeleteProgram(prog
);
198 piglit_init(int argc
, char **argv
)
200 enum piglit_result status
= PIGLIT_PASS
;
201 const struct image_target_info
*target
;
203 piglit_require_extension("GL_ARB_shader_image_load_store");
205 for (target
= image_targets(); target
->name
; ++target
) {
206 subtest(&status
, true,
207 run_test(target
, false, 5),
208 "image%s/non-layered binding test", target
->name
);
210 subtest(&status
, true,
211 run_test(target
, true, 5),
212 "image%s/layered binding test", target
->name
);
215 piglit_report_result(status
);