ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / arb_shader_image_load_store / common.c
blobcbeaac71ed050db1b89af83f4b19de99a785cb1e
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 common.c
26 * Common utility functions for the ARB_shader_image_load_store tests.
29 #include "common.h"
31 bool
32 set_uniform_int(GLuint prog, const char *name, int value)
34 int loc, last_prog;
36 loc = glGetUniformLocation(prog, name);
37 if (loc < 0)
38 return true;
40 glGetIntegerv(GL_CURRENT_PROGRAM, &last_prog);
41 if (prog != last_prog)
42 glUseProgram(prog);
44 glUniform1i(loc, value);
46 return piglit_check_gl_error(GL_NO_ERROR);
49 static GLuint *textures, *buffers;
50 static unsigned num_textures, num_buffers;
52 GLuint
53 get_texture(unsigned unit)
55 if (unit >= num_textures) {
56 const unsigned n = unit + 1;
58 textures = realloc(textures, sizeof(GLuint) * n);
59 memset(&textures[num_textures], 0,
60 sizeof(GLuint) * (n - num_textures));
61 num_textures = n;
64 return textures[unit];
67 GLuint
68 get_buffer(unsigned unit)
70 if (unit >= num_buffers) {
71 const unsigned n = unit + 1;
73 buffers = realloc(buffers, sizeof(GLuint) * n);
74 memset(&buffers[num_buffers], 0,
75 sizeof(GLuint) * (n - num_buffers));
76 num_buffers = n;
79 return buffers[unit];
82 static GLuint fb[2], cb[2], zb[2];
83 static GLfloat vp[2][4];
85 static bool
86 generate_fb(const struct grid_info grid, unsigned idx)
88 if (!fb[idx]) {
89 glGenFramebuffers(1, &fb[idx]);
90 glGenRenderbuffers(1, &cb[idx]);
91 glGenRenderbuffers(1, &zb[idx]);
94 glBindFramebuffer(GL_FRAMEBUFFER, fb[idx]);
96 glBindRenderbuffer(GL_RENDERBUFFER, cb[idx]);
97 glRenderbufferStorage(GL_RENDERBUFFER, grid.format->format,
98 grid.size.x, grid.size.y);
99 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
100 GL_RENDERBUFFER, cb[idx]);
102 glBindRenderbuffer(GL_RENDERBUFFER, zb[idx]);
103 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32F,
104 grid.size.x, grid.size.y);
105 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
106 GL_RENDERBUFFER, zb[idx]);
108 vp[idx][0] = 0;
109 vp[idx][1] = 0;
110 vp[idx][2] = grid.size.x;
111 vp[idx][3] = grid.size.y;
112 glViewportIndexedfv(0, vp[idx]);
114 return piglit_check_gl_error(GL_NO_ERROR);
117 bool
118 upload_image(const struct image_info img, unsigned unit,
119 const uint32_t *pixels)
121 return upload_image_levels(img, 1, 0, unit, pixels);
124 bool
125 upload_image_levels(const struct image_info img, unsigned num_levels,
126 unsigned level, unsigned unit, const uint32_t *pixels)
128 const unsigned m = image_num_components(img.format);
129 int i, l;
131 if (get_texture(unit)) {
132 glDeleteTextures(1, &textures[unit]);
133 textures[unit] = 0;
136 if (get_buffer(unit)) {
137 glDeleteBuffers(1, &buffers[unit]);
138 buffers[unit] = 0;
141 glGenTextures(1, &textures[unit]);
142 glBindTexture(img.target->target, textures[unit]);
144 switch (img.target->target) {
145 case GL_TEXTURE_1D:
146 for (l = 0; l < num_levels; ++l) {
147 const struct image_extent size = image_level_size(img, l);
149 glTexImage1D(GL_TEXTURE_1D, l, img.format->format,
150 size.x, 0, img.format->pixel_format,
151 image_base_type(img.format),
152 &pixels[m * image_level_offset(img, l)]);
154 break;
156 case GL_TEXTURE_2D:
157 for (l = 0; l < num_levels; ++l) {
158 const struct image_extent size = image_level_size(img, l);
160 glTexImage2D(GL_TEXTURE_2D, l, img.format->format,
161 size.x, size.y, 0,
162 img.format->pixel_format,
163 image_base_type(img.format),
164 &pixels[m * image_level_offset(img, l)]);
166 break;
168 case GL_TEXTURE_3D:
169 for (l = 0; l < num_levels; ++l) {
170 const struct image_extent size = image_level_size(img, l);
172 glTexImage3D(GL_TEXTURE_3D, l, img.format->format,
173 size.x, size.y, size.z, 0,
174 img.format->pixel_format,
175 image_base_type(img.format),
176 &pixels[m * image_level_offset(img, l)]);
178 break;
180 case GL_TEXTURE_RECTANGLE:
181 assert(num_levels == 1);
183 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, img.format->format,
184 img.size.x, img.size.y, 0, img.format->pixel_format,
185 image_base_type(img.format), pixels);
186 break;
188 case GL_TEXTURE_CUBE_MAP:
189 for (l = 0; l < num_levels; ++l) {
190 const unsigned offset = m * image_level_offset(img, l);
191 const struct image_extent size = image_level_size(img, l);
192 const unsigned face_sz = m * product(size) / 6;
194 for (i = 0; i < 6; ++i)
195 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, l,
196 img.format->format, size.x, size.y, 0,
197 img.format->pixel_format,
198 image_base_type(img.format),
199 &pixels[offset + face_sz * i]);
201 break;
203 case GL_TEXTURE_BUFFER: {
205 * glTexImage*() isn't supposed to work with buffer
206 * textures. We copy the unpacked pixels to a texture
207 * with the desired internal format to let the GL pack
208 * them for us.
210 const struct image_extent grid = image_optimal_extent(img.size);
211 GLuint packed_tex;
213 assert(num_levels == 1);
215 glGenBuffers(1, &buffers[unit]);
216 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffers[unit]);
217 glBufferData(GL_PIXEL_PACK_BUFFER,
218 img.size.x * image_pixel_size(img.format) / 8,
219 NULL, GL_STATIC_DRAW);
221 glGenTextures(1, &packed_tex);
222 glBindTexture(GL_TEXTURE_2D, packed_tex);
224 glTexImage2D(GL_TEXTURE_2D, 0, img.format->format,
225 grid.x, grid.y, 0, img.format->pixel_format,
226 image_base_type(img.format), pixels);
227 glGetTexImage(GL_TEXTURE_2D, 0, img.format->pixel_format,
228 img.format->pixel_type, NULL);
229 glDeleteTextures(1, &packed_tex);
230 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
232 glTexBuffer(GL_TEXTURE_BUFFER, image_compat_format(img.format),
233 buffers[unit]);
234 break;
236 case GL_TEXTURE_1D_ARRAY:
237 for (l = 0; l < num_levels; ++l) {
238 const struct image_extent size = image_level_size(img, l);
240 glTexImage2D(GL_TEXTURE_1D_ARRAY, l, img.format->format,
241 size.x, size.y, 0, img.format->pixel_format,
242 image_base_type(img.format),
243 &pixels[m * image_level_offset(img, l)]);
245 break;
247 case GL_TEXTURE_2D_ARRAY:
248 for (l = 0; l < num_levels; ++l) {
249 const struct image_extent size = image_level_size(img, l);
251 glTexImage3D(GL_TEXTURE_2D_ARRAY, l, img.format->format,
252 size.x, size.y, size.z, 0,
253 img.format->pixel_format,
254 image_base_type(img.format),
255 &pixels[m * image_level_offset(img, l)]);
257 break;
259 case GL_TEXTURE_CUBE_MAP_ARRAY:
260 for (l = 0; l < num_levels; ++l) {
261 const struct image_extent size = image_level_size(img, l);
263 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, l, img.format->format,
264 size.x, size.y, size.z, 0,
265 img.format->pixel_format,
266 image_base_type(img.format),
267 &pixels[m * image_level_offset(img, l)]);
269 break;
271 case GL_TEXTURE_2D_MULTISAMPLE:
272 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: {
274 * GL doesn't seem to provide any direct way to
275 * initialize a multisample texture, so we use
276 * imageStore() to render to it from the fragment
277 * shader copying the contents of a larger
278 * single-sample 2D texture.
280 const struct grid_info grid = {
281 get_image_stage(GL_FRAGMENT_SHADER)->bit,
282 img.format,
283 image_optimal_extent(img.size)
285 GLuint prog = generate_program(
286 grid, GL_FRAGMENT_SHADER,
287 concat(image_hunk(image_info_for_grid(grid), "SRC_"),
288 image_hunk(img, "DST_"),
289 hunk("readonly SRC_IMAGE_UNIFORM_T src_img;\n"
290 "writeonly DST_IMAGE_UNIFORM_T dst_img;\n"
291 "\n"
292 "GRID_T op(ivec2 idx, GRID_T x) {\n"
293 " imageStore(dst_img, DST_IMAGE_ADDR(idx),\n"
294 " imageLoad(src_img, SRC_IMAGE_ADDR(idx)));\n"
295 " return x;\n"
296 "}\n"), NULL));
297 bool ret = prog && generate_fb(grid, 1);
298 GLuint tmp_tex;
300 assert(num_levels == 1);
302 glGenTextures(1, &tmp_tex);
303 glBindTexture(GL_TEXTURE_2D, tmp_tex);
305 if (img.target->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) {
306 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
307 img.size.x, img.format->format,
308 img.size.y, img.size.z, img.size.w,
309 GL_FALSE);
310 } else {
311 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
312 img.size.x, img.format->format,
313 img.size.y, img.size.z,
314 GL_FALSE);
317 glTexImage2D(GL_TEXTURE_2D, 0, img.format->format,
318 grid.size.x, grid.size.y, 0,
319 img.format->pixel_format, image_base_type(img.format),
320 pixels);
322 glBindImageTexture(unit, textures[unit], 0, GL_TRUE, 0,
323 GL_WRITE_ONLY, img.format->format);
324 glBindImageTexture(6, tmp_tex, 0, GL_TRUE, 0,
325 GL_READ_ONLY, img.format->format);
327 ret &= set_uniform_int(prog, "src_img", 6) &&
328 set_uniform_int(prog, "dst_img", unit) &&
329 draw_grid(grid, prog);
331 glDeleteProgram(prog);
332 glDeleteTextures(1, &tmp_tex);
334 glBindFramebuffer(GL_FRAMEBUFFER, fb[0]);
335 glViewportIndexedfv(0, vp[0]);
337 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
339 if (!ret)
340 return false;
341 break;
343 default:
344 abort();
347 glBindImageTexture(unit, textures[unit], level, GL_TRUE, 0,
348 GL_READ_WRITE, img.format->format);
350 return piglit_check_gl_error(GL_NO_ERROR);
353 bool
354 download_image(const struct image_info img, unsigned unit,
355 uint32_t *r_pixels)
357 return download_image_levels(img, 1, unit, r_pixels);
360 bool
361 download_image_levels(const struct image_info img, unsigned num_levels,
362 unsigned unit, uint32_t *r_pixels)
364 const unsigned m = image_num_components(img.format);
365 int i, l;
367 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT |
368 GL_BUFFER_UPDATE_BARRIER_BIT |
369 GL_PIXEL_BUFFER_BARRIER_BIT |
370 GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
372 glBindTexture(img.target->target, textures[unit]);
374 switch (img.target->target) {
375 case GL_TEXTURE_1D:
376 case GL_TEXTURE_2D:
377 case GL_TEXTURE_3D:
378 case GL_TEXTURE_RECTANGLE:
379 case GL_TEXTURE_1D_ARRAY:
380 case GL_TEXTURE_2D_ARRAY:
381 case GL_TEXTURE_CUBE_MAP_ARRAY:
382 assert(img.target->target != GL_TEXTURE_RECTANGLE ||
383 num_levels == 1);
385 for (l = 0; l < num_levels; ++l)
386 glGetTexImage(img.target->target, l,
387 img.format->pixel_format,
388 image_base_type(img.format),
389 &r_pixels[m * image_level_offset(img, l)]);
390 break;
392 case GL_TEXTURE_CUBE_MAP:
393 for (l = 0; l < num_levels; ++l) {
394 const unsigned offset = m * image_level_offset(img, l);
395 const unsigned face_sz =
396 m * product(image_level_size(img, l)) / 6;
398 for (i = 0; i < 6; ++i)
399 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
400 l, img.format->pixel_format,
401 image_base_type(img.format),
402 &r_pixels[offset + face_sz * i]);
405 break;
407 case GL_TEXTURE_BUFFER: {
409 * glGetTexImage() isn't supposed to work with buffer
410 * textures. We copy the packed pixels to a texture
411 * with the same internal format as the image to let
412 * the GL unpack it for us.
414 const struct image_extent grid = image_optimal_extent(img.size);
415 GLuint packed_tex;
417 assert(num_levels == 1);
419 glGenTextures(1, &packed_tex);
420 glBindTexture(GL_TEXTURE_2D, packed_tex);
421 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffers[unit]);
423 glTexImage2D(GL_TEXTURE_2D, 0, img.format->format,
424 grid.x, grid.y, 0, img.format->pixel_format,
425 img.format->pixel_type, NULL);
426 glGetTexImage(GL_TEXTURE_2D, 0, img.format->pixel_format,
427 image_base_type(img.format), r_pixels);
429 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
430 glDeleteTextures(1, &packed_tex);
431 break;
433 case GL_TEXTURE_2D_MULTISAMPLE:
434 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: {
436 * GL doesn't seem to provide any direct way to read
437 * back a multisample texture, so we use imageLoad()
438 * to copy its contents to a larger single-sample 2D
439 * texture from the fragment shader.
441 const struct grid_info grid = {
442 get_image_stage(GL_FRAGMENT_SHADER)->bit,
443 img.format,
444 image_optimal_extent(img.size)
446 GLuint prog = generate_program(
447 grid, GL_FRAGMENT_SHADER,
448 concat(image_hunk(img, "SRC_"),
449 image_hunk(image_info_for_grid(grid), "DST_"),
450 hunk("readonly SRC_IMAGE_UNIFORM_T src_img;\n"
451 "writeonly DST_IMAGE_UNIFORM_T dst_img;\n"
452 "\n"
453 "GRID_T op(ivec2 idx, GRID_T x) {\n"
454 " imageStore(dst_img, DST_IMAGE_ADDR(idx),\n"
455 " imageLoad(src_img, SRC_IMAGE_ADDR(idx)));\n"
456 " return x;\n"
457 "}\n"), NULL));
458 bool ret = prog && generate_fb(grid, 1);
459 GLuint tmp_tex;
461 assert(num_levels == 1);
463 glGenTextures(1, &tmp_tex);
464 glBindTexture(GL_TEXTURE_2D, tmp_tex);
466 glTexImage2D(GL_TEXTURE_2D, 0, img.format->format,
467 grid.size.x, grid.size.y, 0,
468 img.format->pixel_format, image_base_type(img.format),
469 NULL);
471 glBindImageTexture(unit, textures[unit], 0, GL_TRUE, 0,
472 GL_READ_ONLY, img.format->format);
473 glBindImageTexture(6, tmp_tex, 0, GL_TRUE, 0,
474 GL_WRITE_ONLY, img.format->format);
476 ret &= set_uniform_int(prog, "src_img", unit) &&
477 set_uniform_int(prog, "dst_img", 6) &&
478 draw_grid(grid, prog);
480 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
482 glGetTexImage(GL_TEXTURE_2D, 0, img.format->pixel_format,
483 image_base_type(img.format), r_pixels);
485 glDeleteProgram(prog);
486 glDeleteTextures(1, &tmp_tex);
488 glBindFramebuffer(GL_FRAMEBUFFER, fb[0]);
489 glViewportIndexedfv(0, vp[0]);
491 if (!ret)
492 return false;
493 break;
495 default:
496 abort();
499 return piglit_check_gl_error(GL_NO_ERROR);
502 bool
503 init_pixels(const struct image_info img, uint32_t *r_pixels,
504 double r, double g, double b, double a)
506 const double init[4] = { r, g, b, a };
507 const unsigned m = image_num_components(img.format);
508 unsigned i, j;
510 for (i = 0; i < product(img.size); ++i) {
511 for (j = 0; j < m; ++j) {
512 r_pixels[i * m + j] = encode(img.format, init[j]);
516 return true;
519 static bool
520 check_pixels_vs(const struct image_info img, unsigned stride,
521 const uint32_t *pixels, const uint32_t *expect)
523 const unsigned m = image_num_components(img.format);
524 unsigned i, j;
526 for (i = 0; i < product(img.size); ++i) {
527 const uint32_t *v = &pixels[m * i];
528 const uint32_t *u = &expect[stride * m * i];
530 for (j = 0; j < m; ++j) {
531 if ((fabs(decode(img.format, v[j]) - decode(img.format, u[j])) >
532 get_idx(img.epsilon, j)) &&
533 isfinite(decode(img.format, u[j]))) {
534 printf("Probe value at (%u, %u, %u, %u)\n",
535 i % img.size.x,
536 i / img.size.x % img.size.y,
537 i / img.size.x / img.size.y % img.size.z,
538 i / img.size.x / img.size.y / img.size.z);
540 printf(" Expected:");
542 for (j = 0; j < m; ++j)
543 printf(" %f", decode(img.format, u[j]));
545 printf("\n Observed:");
547 for (j = 0; j < m; ++j)
548 printf(" %f", decode(img.format, v[j]));
550 printf("\n");
551 return false;
556 return true;
559 bool
560 check_pixels(const struct image_info img, const uint32_t *pixels,
561 double r, double g, double b, double a)
563 const uint32_t expect[4] = {
564 encode(img.format, r), encode(img.format, g),
565 encode(img.format, b), encode(img.format, a)
568 return check_pixels_vs(img, 0, pixels, expect);
571 bool
572 check_pixels_v(const struct image_info img, const uint32_t *pixels,
573 const uint32_t *expect)
575 return check_pixels_vs(img, 1, pixels, expect);
578 bool
579 init_fb(const struct grid_info grid)
581 bool ret = true;
583 if (grid.stages & GL_COMPUTE_SHADER_BIT) {
584 const struct image_info img = image_info_for_grid(grid);
585 const unsigned n = product(grid.size) *
586 image_num_components(grid.format);
587 uint32_t *pixels = malloc(n * sizeof(*pixels));
589 ret = init_pixels(img, pixels, 0.5, 0.5, 0.5, 0.5) &&
590 upload_image(img, max_image_units(), pixels);
592 free(pixels);
593 } else {
594 ret = generate_fb(grid, 0);
596 glClearColor(0.5, 0.5, 0.5, 0.5);
597 glClear(GL_COLOR_BUFFER_BIT);
599 glClearDepth(0.5);
600 glClear(GL_DEPTH_BUFFER_BIT);
603 return ret;
606 bool
607 download_result(const struct grid_info grid, uint32_t *r_pixels)
609 if (grid.stages & GL_COMPUTE_SHADER_BIT) {
610 /* No actual framebuffer. Results are returned into
611 * an image. */
612 return download_image(image_info_for_grid(grid),
613 max_image_units(), r_pixels);
615 } else {
616 glReadPixels(0, 0, grid.size.x, grid.size.y,
617 grid.format->pixel_format,
618 image_base_type(grid.format),
619 r_pixels);
620 return piglit_check_gl_error(GL_NO_ERROR);