ARB_ubo/referenced-by-shader: pass if shader compiler moves UBOs between shaders
[piglit.git] / tests / spec / arb_shader_image_load_store / state.c
blobca3b6c0a3ce527e6dc2a5db460b823b76c78b492
1 /*
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
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 DEALINGS
21 * IN THE SOFTWARE.
24 /** @file state.c
26 * Test image unit binding by creating a number of textures and
27 * binding them as images with different parameters (including
28 * incorrect arguments that are supposed to generate GL errors),
29 * delete and unbind a few images and check using the state query API
30 * that the implementation is keeping track of the image unit state
31 * correctly.
33 * A second test checks that glUniform*() work as specified when used
34 * to assign image units to shader image uniforms.
37 #include "common.h"
39 PIGLIT_GL_TEST_CONFIG_BEGIN
41 /** Image width. */
42 #define W 16
44 /** Image height. */
45 #define H 96
47 /** Total number of pixels in the image. */
48 #define N (W * H)
50 /** Maximum number of mipmap levels. */
51 #define M 11
53 config.supports_gl_core_version = 32;
55 config.window_width = 1;
56 config.window_height = 1;
57 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
58 config.khr_no_error_support = PIGLIT_HAS_ERRORS;
60 PIGLIT_GL_TEST_CONFIG_END
62 struct image_unit_action {
63 enum {
64 /** End of action list. */
65 END = 0,
67 /** Create a new texture object of type \a obj and
68 * bind it to the specified image unit. */
69 BIND_NEW,
71 /** Bind the same texture object that was previously
72 * bound to image unit \a obj to the specified image
73 * unit. */
74 BIND_IDX,
76 /** Bind texture object \a obj to the specified image
77 * unit. */
78 BIND_OBJ,
80 /** Delete the texture object that was previously
81 * bound to image unit \a obj. */
82 DELETE_IDX
83 } action;
85 /** Image unit this action has an effect on. */
86 unsigned idx;
88 /** Object of this action. */
89 unsigned obj;
91 /** Texture mipmap level that should be bound. */
92 int level;
94 /** If true the whole texture level is bound rather than a
95 * single layer. */
96 bool layered;
98 /** If \a layered is false, the index of the individual layer
99 * to bind. */
100 int layer;
102 /** GL_READ_ONLY, GL_WRITE_ONLY or GL_READ_WRITE. */
103 GLenum access;
105 /** Image format used to interpret the texture data. */
106 GLenum format;
108 /** GL error code that should be expected after the completion
109 * of this action. */
110 GLenum expect_status;
113 static const struct image_unit_action actions[] = {
114 { BIND_NEW, 0, GL_TEXTURE_2D,
115 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16UI,
116 GL_NO_ERROR },
117 { BIND_NEW, 1, GL_TEXTURE_2D,
118 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F,
119 GL_NO_ERROR },
120 { BIND_NEW, 2, GL_TEXTURE_BUFFER,
121 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA16F,
122 GL_NO_ERROR },
123 { BIND_NEW, 3, GL_TEXTURE_2D,
124 -1, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA16_SNORM,
125 GL_INVALID_VALUE },
126 { BIND_NEW, 3, GL_TEXTURE_2D,
127 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGB565,
128 GL_INVALID_VALUE },
129 { BIND_NEW, 3, GL_TEXTURE_2D_ARRAY,
130 0, GL_FALSE, -1, GL_WRITE_ONLY, GL_RGBA16_SNORM,
131 GL_INVALID_VALUE },
132 { BIND_OBJ, 3, 0xdeadcafe,
133 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8,
134 GL_INVALID_VALUE },
135 { BIND_NEW, 3, GL_TEXTURE_2D_ARRAY,
136 0, GL_FALSE, 2, GL_WRITE_ONLY, GL_RGBA16,
137 GL_NO_ERROR },
138 { BIND_NEW, 4, GL_TEXTURE_2D_ARRAY,
139 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGBA16,
140 GL_NO_ERROR },
141 { BIND_OBJ, 2, 0,
142 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8,
143 GL_NO_ERROR },
144 { BIND_IDX, ~0, 1,
145 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA16_SNORM,
146 GL_INVALID_VALUE },
147 { BIND_NEW, 5, GL_TEXTURE_2D,
148 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA16F,
149 GL_NO_ERROR },
150 { BIND_NEW, 6, GL_TEXTURE_3D,
151 0, GL_FALSE, 3, GL_WRITE_ONLY, GL_RGBA16F,
152 GL_NO_ERROR },
153 { DELETE_IDX, 5, 5,
154 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8,
155 GL_NO_ERROR },
156 { END }
160 * Get the maximum number of image units supported by the
161 * implementation.
163 static unsigned
164 first_invalid_image_unit(void)
166 int n;
167 glGetIntegerv(GL_MAX_IMAGE_UNITS, &n);
168 return n;
172 * Get the last action that modified the state of image unit \a idx.
174 static struct image_unit_action
175 get_last_unit_action(unsigned idx)
177 /* The initial image unit state is equivalent to this
178 * action. */
179 const struct image_unit_action def_action = {
180 BIND_OBJ, idx, 0, 0, GL_FALSE, 0,
181 GL_READ_ONLY, GL_R8, GL_NO_ERROR
183 const struct image_unit_action *a, *la = &def_action;
185 for (a = actions; a->action; ++a) {
186 if (a->idx == idx)
187 la = a;
190 return *la;
194 * Execute the given action.
196 static bool
197 exec_action(const struct image_unit_action a)
199 if (a.action == BIND_NEW) {
200 const GLenum format = (get_image_format(a.format) ?
201 a.format : GL_RGBA32F);
202 const struct image_info img = image_info(a.obj, format, W, H);
203 const unsigned num_levels = image_num_levels(img);
204 uint32_t pixels[4 * N * M] = { 0 };
206 if (!upload_image_levels(img, num_levels, 0, a.idx, pixels))
207 return false;
209 glBindImageTexture(a.idx, get_texture(a.idx),
210 a.level, a.layered, a.layer,
211 a.access, a.format);
213 } else if (a.action == BIND_IDX) {
214 const unsigned idx = MIN2(a.idx, first_invalid_image_unit());
216 glBindImageTexture(idx, get_texture(a.obj),
217 a.level, a.layered, a.layer,
218 a.access, a.format);
220 } else if (a.action == BIND_OBJ) {
221 glBindImageTexture(a.idx, a.obj,
222 a.level, a.layered, a.layer,
223 a.access, a.format);
225 } else if (a.action == DELETE_IDX) {
226 GLuint tex = get_texture(a.idx);
228 glDeleteTextures(1, &tex);
230 } else {
231 abort();
234 return piglit_check_gl_error(a.expect_status);
237 static bool
238 check_integer(GLenum name, unsigned idx, int expect)
240 int v = 0xdeadcafe;
242 glGetIntegeri_v(name, idx, &v);
243 if (v != expect) {
244 fprintf(stderr, "Invalid value for integer %s index %d\n"
245 " Expected: %d\n"
246 " Observed: %d\n",
247 piglit_get_gl_enum_name(name), idx, expect, v);
248 return false;
251 return true;
254 static bool
255 check_tex_parameter(GLenum target, GLuint obj, GLenum name, int expect)
257 int v = 0xdeadcafe;
259 glBindTexture(target, obj);
260 glGetTexParameteriv(target, name, &v);
261 if (v != expect) {
262 fprintf(stderr, "Invalid value for tex parameter %s\n"
263 " Expected: %d\n"
264 " Observed: %d\n",
265 piglit_get_gl_enum_name(name), expect, v);
266 return false;
269 return true;
273 * Check that the image unit state matches the result of the specified
274 * action.
276 static bool
277 check_action(const struct image_unit_action a)
279 if ((a.action == BIND_NEW ||
280 a.action == BIND_OBJ ||
281 a.action == BIND_IDX) &&
282 a.expect_status == GL_NO_ERROR) {
283 const GLuint obj = (a.action == BIND_NEW ? get_texture(a.idx) :
284 a.action == BIND_IDX ? get_texture(a.obj) :
285 a.obj);
287 if (a.action == BIND_NEW &&
288 !check_tex_parameter(a.obj, obj,
289 GL_IMAGE_FORMAT_COMPATIBILITY_TYPE,
290 GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE))
291 return false;
293 return check_integer(GL_IMAGE_BINDING_NAME, a.idx,
294 obj) &&
295 check_integer(GL_IMAGE_BINDING_LEVEL, a.idx,
296 a.level) &&
297 check_integer(GL_IMAGE_BINDING_LAYERED, a.idx,
298 a.layered) &&
299 check_integer(GL_IMAGE_BINDING_LAYER, a.idx,
300 a.layer) &&
301 check_integer(GL_IMAGE_BINDING_ACCESS, a.idx,
302 a.access) &&
303 check_integer(GL_IMAGE_BINDING_FORMAT, a.idx,
304 a.format);
306 } else {
307 return check_integer(GL_IMAGE_BINDING_NAME, a.idx, 0);
312 * Bind a number of texture objects to different image units and check
313 * that the image unit state was updated correctly.
315 static bool
316 run_test_binding(void)
318 const struct image_unit_action *action;
319 bool ret = true;
320 int i;
322 for (action = actions; action->action; ++action)
323 ret &= exec_action(*action);
325 for (i = 0; i < max_image_units(); ++i)
326 ret &= check_action(get_last_unit_action(i));
328 return ret;
331 static bool
332 check_uniform_int(GLuint prog, int loc, int expect)
334 int v = 0xdeadcafe;
336 glGetUniformiv(prog, loc, &v);
337 if (v != expect) {
338 fprintf(stderr, "Invalid value for uniform %d\n"
339 " Expected: %d\n"
340 " Observed: %d\n",
341 loc, expect, v);
342 return false;
345 return piglit_check_gl_error(GL_NO_ERROR);
348 #define CHECK_INVAL_1(prefix, suffix, args, ret) do { \
349 prefix##suffix args; \
350 ret &= piglit_check_gl_error(GL_INVALID_OPERATION); \
351 } while (0)
353 #define CHECK_INVAL_2(prefix, suffix0, suffix1, args, ret) do { \
354 CHECK_INVAL_1(prefix, suffix0, args, ret); \
355 CHECK_INVAL_1(prefix, suffix1, args, ret); \
356 } while (0)
358 #define CHECK_INVAL_3(prefix, suffix0, suffix1, suffix2, args, ret) do { \
359 CHECK_INVAL_2(prefix, suffix0, suffix1, args, ret); \
360 CHECK_INVAL_1(prefix, suffix2, args, ret); \
361 } while (0)
364 * Test binding image uniforms to image units for a simple shader
365 * program.
367 static bool
368 run_test_uniform(void)
370 const struct grid_info grid =
371 grid_info(GL_FRAGMENT_SHADER, GL_RGBA32F, W, H);
372 GLuint prog = generate_program(
373 grid, GL_FRAGMENT_SHADER,
374 concat(image_hunk(image_info_for_grid(grid), ""),
375 hunk("IMAGE_UNIFORM_T imgs[2];\n"
376 "\n"
377 "GRID_T op(ivec2 idx, GRID_T x) {\n"
378 " imageStore(imgs[0], IMAGE_ADDR(idx), x);\n"
379 " imageStore(imgs[1], IMAGE_ADDR(idx), x);\n"
380 " return x;\n"
381 "}\n"), NULL));
382 const int loc = glGetUniformLocation(prog, "imgs");
383 bool ret = prog && check_uniform_int(prog, loc, 0) &&
384 check_uniform_int(prog, loc + 1, 0);
385 int v[2];
387 glUseProgram(prog);
390 * Image uniforms are bound to image units using
391 * glUniform1i{v}.
393 glUniform1i(loc, 3);
394 ret &= check_uniform_int(prog, loc, 3) &&
395 check_uniform_int(prog, loc + 1, 0);
397 glUniform1i(loc + 1, 3);
398 ret &= check_uniform_int(prog, loc, 3) &&
399 check_uniform_int(prog, loc + 1, 3);
401 v[0] = 4;
402 v[1] = 5;
403 glUniform1iv(loc, 2, v);
404 ret &= check_uniform_int(prog, loc, 4) &&
405 check_uniform_int(prog, loc + 1, 5);
408 * GL_INVALID_VALUE is generated if the value specified is
409 * greater than or equal to the value of GL_MAX_IMAGE_UNITS.
411 glUniform1i(loc, first_invalid_image_unit());
412 ret &= piglit_check_gl_error(GL_INVALID_VALUE);
414 v[0] = 3;
415 v[1] = first_invalid_image_unit() + 1;
416 glUniform1iv(loc, 2, v);
417 ret &= piglit_check_gl_error(GL_INVALID_VALUE);
420 * GL_INVALID_VALUE is generated if the value specified is
421 * less than zero.
423 glUniform1i(loc, -1);
424 ret &= piglit_check_gl_error(GL_INVALID_VALUE);
426 v[0] = 3;
427 v[1] = -4;
428 glUniform1iv(loc, 2, v);
429 ret &= piglit_check_gl_error(GL_INVALID_VALUE);
432 * GL_INVALID_OPERATION is generated by Uniform* functions
433 * other than Uniform1i{v}.
435 CHECK_INVAL_2(glUniform, 1f, 1ui, (loc, 0), ret);
436 CHECK_INVAL_3(glUniform, 2i, 2f, 2ui, (loc, 0, 0), ret);
437 CHECK_INVAL_3(glUniform, 3i, 3f, 3ui, (loc, 0, 0, 0), ret);
438 CHECK_INVAL_3(glUniform, 4i, 4f, 4ui, (loc, 0, 0, 0, 0), ret);
440 CHECK_INVAL_2(glUniform, 1fv, 1uiv, (loc, 1, (void *)v), ret);
441 CHECK_INVAL_3(glUniform, 2iv, 2fv, 2uiv, (loc, 1, (void *)v), ret);
442 CHECK_INVAL_3(glUniform, 3iv, 3fv, 3uiv, (loc, 1, (void *)v), ret);
443 CHECK_INVAL_3(glUniform, 4iv, 4fv, 4uiv, (loc, 1, (void *)v), ret);
445 CHECK_INVAL_3(glUniformMatrix, 2fv, 3fv, 4fv,
446 (loc, 1, GL_FALSE, (float *)v), ret);
447 CHECK_INVAL_3(glUniformMatrix, 2x3fv, 3x2fv, 2x4fv,
448 (loc, 1, GL_FALSE, (float *)v), ret);
449 CHECK_INVAL_3(glUniformMatrix, 4x2fv, 3x4fv, 4x3fv,
450 (loc, 1, GL_FALSE, (float *)v), ret);
452 if (piglit_is_extension_supported("GL_ARB_gpu_shader_fp64")) {
453 CHECK_INVAL_1(glUniform, 1d, (loc, 0), ret);
454 CHECK_INVAL_1(glUniform, 2d, (loc, 0, 0), ret);
455 CHECK_INVAL_1(glUniform, 3d, (loc, 0, 0, 0), ret);
456 CHECK_INVAL_1(glUniform, 4d, (loc, 0, 0, 0, 0), ret);
458 CHECK_INVAL_2(glUniform, 1dv, 2dv, (loc, 1, (double *)v), ret);
459 CHECK_INVAL_2(glUniform, 3dv, 4dv, (loc, 1, (double *)v), ret);
461 CHECK_INVAL_3(glUniformMatrix, 2dv, 3dv, 4dv,
462 (loc, 1, GL_FALSE, (double *)v), ret);
463 CHECK_INVAL_3(glUniformMatrix, 2x3dv, 3x2dv, 2x4dv,
464 (loc, 1, GL_FALSE, (double *)v), ret);
465 CHECK_INVAL_3(glUniformMatrix, 4x2dv, 3x4dv, 4x3dv,
466 (loc, 1, GL_FALSE, (double *)v), ret);
469 glDeleteProgram(prog);
470 return ret;
473 void
474 piglit_init(int argc, char **argv)
476 enum piglit_result status = PIGLIT_PASS;
478 piglit_require_extension("GL_ARB_shader_image_load_store");
480 subtest(&status, true, run_test_binding(),
481 "binding state test");
483 subtest(&status, true, run_test_uniform(),
484 "uniform state test");
486 piglit_report_result(status);
489 enum piglit_result
490 piglit_display(void)
492 return PIGLIT_FAIL;