diff options
author | Francisco Jerez <currojerez@riseup.net> | 2015-01-31 17:07:00 +0200 |
---|---|---|
committer | Francisco Jerez <currojerez@riseup.net> | 2015-01-31 18:02:07 +0200 |
commit | 90d795cbf74f789ff89a458461cb6e215bf3dbaa (patch) | |
tree | 2dfd75b466ab63c3c10957abc335614462e68c17 | |
parent | 8c539bb805dd98706f3f10bda5f4c9664b110977 (diff) |
arb_shader_image_load_store: Add misc. image manipulation code and hook up to the build system.
-rw-r--r-- | tests/all.py | 6 | ||||
-rw-r--r-- | tests/spec/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt | 15 | ||||
-rw-r--r-- | tests/spec/arb_shader_image_load_store/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/spec/arb_shader_image_load_store/common.c | 621 | ||||
-rw-r--r-- | tests/spec/arb_shader_image_load_store/common.h | 140 |
6 files changed, 784 insertions, 0 deletions
diff --git a/tests/all.py b/tests/all.py index d6f4ac3b9..417ed2930 100644 --- a/tests/all.py +++ b/tests/all.py @@ -4421,6 +4421,12 @@ spec['ARB_direct_state_access']['getcompressedtextureimage'] = PiglitGLTest(['ar spec['ARB_direct_state_access']['texture-storage-multisample'] = PiglitGLTest(['arb_direct_state_access-texture-storage-multisample'], run_concurrent=True) spec['ARB_direct_state_access']['texture-buffer'] = PiglitGLTest(['arb_direct_state_access-texture-buffer'], run_concurrent=True) +arb_shader_image_load_store = {} +spec['ARB_shader_image_load_store'] = arb_shader_image_load_store +import_glsl_parser_tests(spec['ARB_shader_image_load_store'], + os.path.join(TESTS_DIR, 'spec', 'arb_shader_image_load_store'), + ['']) + profile.tests['hiz'] = hiz profile.tests['fast_color_clear'] = fast_color_clear profile.tests['glean'] = glean diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt index 890b1d299..25519237e 100644 --- a/tests/spec/CMakeLists.txt +++ b/tests/spec/CMakeLists.txt @@ -42,6 +42,7 @@ add_subdirectory (arb_shader_subroutine) add_subdirectory (arb_shader_texture_lod/execution) add_subdirectory (arb_shader_atomic_counters) add_subdirectory (arb_shader_objects) +add_subdirectory (arb_shader_image_load_store) add_subdirectory (arb_shading_language_420pack/execution) add_subdirectory (arb_stencil_texturing) add_subdirectory (arb_sync) diff --git a/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt b/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt new file mode 100644 index 000000000..cc5586daf --- /dev/null +++ b/tests/spec/arb_shader_image_load_store/CMakeLists.gl.txt @@ -0,0 +1,15 @@ +include_directories( + ${GLEXT_INCLUDE_DIR} + ${OPENGL_INCLUDE_PATH} + ${piglit_SOURCE_DIR}/tests/util +) + +link_libraries ( + piglitutil_${piglit_target_api} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} +) + +set(depends image.c grid.c common.c) + +# vim: ft=cmake: diff --git a/tests/spec/arb_shader_image_load_store/CMakeLists.txt b/tests/spec/arb_shader_image_load_store/CMakeLists.txt new file mode 100644 index 000000000..144a306f4 --- /dev/null +++ b/tests/spec/arb_shader_image_load_store/CMakeLists.txt @@ -0,0 +1 @@ +piglit_include_target_api() diff --git a/tests/spec/arb_shader_image_load_store/common.c b/tests/spec/arb_shader_image_load_store/common.c new file mode 100644 index 000000000..88b0f750c --- /dev/null +++ b/tests/spec/arb_shader_image_load_store/common.c @@ -0,0 +1,621 @@ +/* + * Copyright (C) 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** @file common.c + * + * Common utility functions for the ARB_shader_image_load_store tests. + */ + +#include "common.h" + +bool +set_uniform_int(GLuint prog, const char *name, int value) +{ + int loc, last_prog; + + loc = glGetUniformLocation(prog, name); + if (loc < 0) + return true; + + glGetIntegerv(GL_CURRENT_PROGRAM, &last_prog); + if (prog != last_prog) + glUseProgram(prog); + + glUniform1i(loc, value); + + return piglit_check_gl_error(GL_NO_ERROR); +} + +static GLuint *textures, *buffers; +static unsigned num_textures, num_buffers; + +GLuint +get_texture(unsigned unit) +{ + if (unit >= num_textures) { + const unsigned n = unit + 1; + + textures = realloc(textures, sizeof(GLuint) * n); + memset(&textures[num_textures], 0, + sizeof(GLuint) * (n - num_textures)); + num_textures = n; + } + + return textures[unit]; +} + +GLuint +get_buffer(unsigned unit) +{ + if (unit >= num_buffers) { + const unsigned n = unit + 1; + + buffers = realloc(buffers, sizeof(GLuint) * n); + memset(&buffers[num_buffers], 0, + sizeof(GLuint) * (n - num_buffers)); + num_buffers = n; + } + + return buffers[unit]; +} + +static GLuint fb[2], cb[2], zb[2]; +static GLfloat vp[2][4]; + +static bool +generate_fb(const struct grid_info grid, unsigned idx) +{ + if (!fb[idx]) { + glGenFramebuffers(1, &fb[idx]); + glGenRenderbuffers(1, &cb[idx]); + glGenRenderbuffers(1, &zb[idx]); + } + + glBindFramebuffer(GL_FRAMEBUFFER, fb[idx]); + + glBindRenderbuffer(GL_RENDERBUFFER, cb[idx]); + glRenderbufferStorage(GL_RENDERBUFFER, grid.format->format, + grid.size.x, grid.size.y); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, cb[idx]); + + glBindRenderbuffer(GL_RENDERBUFFER, zb[idx]); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32F, + grid.size.x, grid.size.y); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, zb[idx]); + + vp[idx][0] = 0; + vp[idx][1] = 0; + vp[idx][2] = grid.size.x; + vp[idx][3] = grid.size.y; + glViewportIndexedfv(0, vp[idx]); + + return piglit_check_gl_error(GL_NO_ERROR); +} + +bool +upload_image(const struct image_info img, unsigned unit, + const uint32_t *pixels) +{ + return upload_image_levels(img, 1, 0, unit, pixels); +} + +bool +upload_image_levels(const struct image_info img, unsigned num_levels, + unsigned level, unsigned unit, const uint32_t *pixels) +{ + const unsigned m = image_num_components(img.format); + int i, l; + + if (get_texture(unit)) { + glDeleteTextures(1, &textures[unit]); + textures[unit] = 0; + } + + if (get_buffer(unit)) { + glDeleteBuffers(1, &buffers[unit]); + buffers[unit] = 0; + } + + glGenTextures(1, &textures[unit]); + glBindTexture(img.target->target, textures[unit]); + + switch (img.target->target) { + case GL_TEXTURE_1D: + for (l = 0; l < num_levels; ++l) { + const struct image_extent size = image_level_size(img, l); + + glTexImage1D(GL_TEXTURE_1D, l, img.format->format, + size.x, 0, img.format->pixel_format, + image_base_type(img.format), + &pixels[m * image_level_offset(img, l)]); + } + break; + + case GL_TEXTURE_2D: + for (l = 0; l < num_levels; ++l) { + const struct image_extent size = image_level_size(img, l); + + glTexImage2D(GL_TEXTURE_2D, l, img.format->format, + size.x, size.y, 0, + img.format->pixel_format, + image_base_type(img.format), + &pixels[m * image_level_offset(img, l)]); + } + break; + + case GL_TEXTURE_3D: + for (l = 0; l < num_levels; ++l) { + const struct image_extent size = image_level_size(img, l); + + glTexImage3D(GL_TEXTURE_3D, l, img.format->format, + size.x, size.y, size.z, 0, + img.format->pixel_format, + image_base_type(img.format), + &pixels[m * image_level_offset(img, l)]); + } + break; + + case GL_TEXTURE_RECTANGLE: + assert(num_levels == 1); + + glTexImage2D(GL_TEXTURE_RECTANGLE, 0, img.format->format, + img.size.x, img.size.y, 0, img.format->pixel_format, + image_base_type(img.format), pixels); + break; + + case GL_TEXTURE_CUBE_MAP: + for (l = 0; l < num_levels; ++l) { + const unsigned offset = m * image_level_offset(img, l); + const struct image_extent size = image_level_size(img, l); + const unsigned face_sz = m * product(size) / 6; + + for (i = 0; i < 6; ++i) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, l, + img.format->format, size.x, size.y, 0, + img.format->pixel_format, + image_base_type(img.format), + &pixels[offset + face_sz * i]); + } + break; + + case GL_TEXTURE_BUFFER: { + /* + * glTexImage*() isn't supposed to work with buffer + * textures. We copy the unpacked pixels to a texture + * with the desired internal format to let the GL pack + * them for us. + */ + const struct image_extent grid = image_optimal_extent(img.size); + GLuint packed_tex; + + assert(num_levels == 1); + + glGenBuffers(1, &buffers[unit]); + glBindBuffer(GL_PIXEL_PACK_BUFFER, buffers[unit]); + glBufferData(GL_PIXEL_PACK_BUFFER, + m * img.size.x * sizeof(uint32_t), + NULL, GL_STATIC_DRAW); + + glGenTextures(1, &packed_tex); + glBindTexture(GL_TEXTURE_2D, packed_tex); + + glTexImage2D(GL_TEXTURE_2D, 0, img.format->format, + grid.x, grid.y, 0, img.format->pixel_format, + image_base_type(img.format), pixels); + glGetTexImage(GL_TEXTURE_2D, 0, img.format->pixel_format, + img.format->pixel_type, NULL); + glDeleteTextures(1, &packed_tex); + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + + glTexBuffer(GL_TEXTURE_BUFFER, image_compat_format(img.format), + buffers[unit]); + break; + } + case GL_TEXTURE_1D_ARRAY: + for (l = 0; l < num_levels; ++l) { + const struct image_extent size = image_level_size(img, l); + + glTexImage2D(GL_TEXTURE_1D_ARRAY, l, img.format->format, + size.x, size.y, 0, img.format->pixel_format, + image_base_type(img.format), + &pixels[m * image_level_offset(img, l)]); + } + break; + + case GL_TEXTURE_2D_ARRAY: + for (l = 0; l < num_levels; ++l) { + const struct image_extent size = image_level_size(img, l); + + glTexImage3D(GL_TEXTURE_2D_ARRAY, l, img.format->format, + size.x, size.y, size.z, 0, + img.format->pixel_format, + image_base_type(img.format), + &pixels[m * image_level_offset(img, l)]); + } + break; + + case GL_TEXTURE_CUBE_MAP_ARRAY: + for (l = 0; l < num_levels; ++l) { + const struct image_extent size = image_level_size(img, l); + + glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, l, img.format->format, + size.x, size.y, size.z, 0, + img.format->pixel_format, + image_base_type(img.format), + &pixels[m * image_level_offset(img, l)]); + } + break; + + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: { + /* + * GL doesn't seem to provide any direct way to + * initialize a multisample texture, so we use + * imageStore() to render to it from the fragment + * shader copying the contents of a larger + * single-sample 2D texture. + */ + const struct grid_info grid = { + get_image_stage(GL_FRAGMENT_SHADER)->bit, + img.format, + image_optimal_extent(img.size) + }; + GLuint prog = generate_program( + grid, GL_FRAGMENT_SHADER, + concat(image_hunk(image_info_for_grid(grid), "SRC_"), + image_hunk(img, "DST_"), + hunk("readonly uniform SRC_IMAGE_T src_img;\n" + "writeonly uniform DST_IMAGE_T dst_img;\n" + "\n" + "GRID_T op(ivec2 idx, GRID_T x) {\n" + " imageStore(dst_img, DST_IMAGE_ADDR(idx),\n" + " imageLoad(src_img, SRC_IMAGE_ADDR(idx)));\n" + " return x;\n" + "}\n"), NULL)); + bool ret = prog && generate_fb(grid, 1); + GLuint tmp_tex; + + assert(num_levels == 1); + + glGenTextures(1, &tmp_tex); + glBindTexture(GL_TEXTURE_2D, tmp_tex); + + if (img.target->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { + glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, + img.size.x, img.format->format, + img.size.y, img.size.z, img.size.w, + GL_FALSE); + } else { + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, + img.size.x, img.format->format, + img.size.y, img.size.z, + GL_FALSE); + } + + glTexImage2D(GL_TEXTURE_2D, 0, img.format->format, + grid.size.x, grid.size.y, 0, + img.format->pixel_format, image_base_type(img.format), + pixels); + + glBindImageTexture(unit, textures[unit], 0, GL_TRUE, 0, + GL_WRITE_ONLY, img.format->format); + glBindImageTexture(6, tmp_tex, 0, GL_TRUE, 0, + GL_READ_ONLY, img.format->format); + + ret &= set_uniform_int(prog, "src_img", 6) && + set_uniform_int(prog, "dst_img", unit) && + draw_grid(grid, prog); + + glDeleteProgram(prog); + glDeleteTextures(1, &tmp_tex); + + glBindFramebuffer(GL_FRAMEBUFFER, fb[0]); + glViewportIndexedfv(0, vp[0]); + + glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); + + if (!ret) + return false; + break; + } + default: + abort(); + } + + glBindImageTexture(unit, textures[unit], level, GL_TRUE, 0, + GL_READ_WRITE, img.format->format); + + return piglit_check_gl_error(GL_NO_ERROR); +} + +bool +download_image(const struct image_info img, unsigned unit, + uint32_t *r_pixels) +{ + return download_image_levels(img, 1, unit, r_pixels); +} + +bool +download_image_levels(const struct image_info img, unsigned num_levels, + unsigned unit, uint32_t *r_pixels) +{ + const unsigned m = image_num_components(img.format); + int i, l; + + glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT | + GL_BUFFER_UPDATE_BARRIER_BIT | + GL_PIXEL_BUFFER_BARRIER_BIT | + GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); + + glBindTexture(img.target->target, textures[unit]); + + switch (img.target->target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_1D_ARRAY: + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + assert(img.target->target != GL_TEXTURE_RECTANGLE || + num_levels == 1); + + for (l = 0; l < num_levels; ++l) + glGetTexImage(img.target->target, l, + img.format->pixel_format, + image_base_type(img.format), + &r_pixels[m * image_level_offset(img, l)]); + break; + + case GL_TEXTURE_CUBE_MAP: + for (l = 0; l < num_levels; ++l) { + const unsigned offset = m * image_level_offset(img, l); + const unsigned face_sz = + m * product(image_level_size(img, l)) / 6; + + for (i = 0; i < 6; ++i) + glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, + l, img.format->pixel_format, + image_base_type(img.format), + &r_pixels[offset + face_sz * i]); + + } + break; + + case GL_TEXTURE_BUFFER: { + /* + * glGetTexImage() isn't supposed to work with buffer + * textures. We copy the packed pixels to a texture + * with the same internal format as the image to let + * the GL unpack it for us. + */ + const struct image_extent grid = image_optimal_extent(img.size); + GLuint packed_tex; + + assert(num_levels == 1); + + glGenTextures(1, &packed_tex); + glBindTexture(GL_TEXTURE_2D, packed_tex); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffers[unit]); + + glTexImage2D(GL_TEXTURE_2D, 0, img.format->format, + grid.x, grid.y, 0, img.format->pixel_format, + img.format->pixel_type, NULL); + glGetTexImage(GL_TEXTURE_2D, 0, img.format->pixel_format, + image_base_type(img.format), r_pixels); + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glDeleteTextures(1, &packed_tex); + break; + } + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: { + /* + * GL doesn't seem to provide any direct way to read + * back a multisample texture, so we use imageLoad() + * to copy its contents to a larger single-sample 2D + * texture from the fragment shader. + */ + const struct grid_info grid = { + get_image_stage(GL_FRAGMENT_SHADER)->bit, + img.format, + image_optimal_extent(img.size) + }; + GLuint prog = generate_program( + grid, GL_FRAGMENT_SHADER, + concat(image_hunk(img, "SRC_"), + image_hunk(image_info_for_grid(grid), "DST_"), + hunk("readonly uniform SRC_IMAGE_T src_img;\n" + "writeonly uniform DST_IMAGE_T dst_img;\n" + "\n" + "GRID_T op(ivec2 idx, GRID_T x) {\n" + " imageStore(dst_img, DST_IMAGE_ADDR(idx),\n" + " imageLoad(src_img, SRC_IMAGE_ADDR(idx)));\n" + " return x;\n" + "}\n"), NULL)); + bool ret = prog && generate_fb(grid, 1); + GLuint tmp_tex; + + assert(num_levels == 1); + + glGenTextures(1, &tmp_tex); + glBindTexture(GL_TEXTURE_2D, tmp_tex); + + glTexImage2D(GL_TEXTURE_2D, 0, img.format->format, + grid.size.x, grid.size.y, 0, + img.format->pixel_format, image_base_type(img.format), + NULL); + + glBindImageTexture(unit, textures[unit], 0, GL_TRUE, 0, + GL_READ_ONLY, img.format->format); + glBindImageTexture(6, tmp_tex, 0, GL_TRUE, 0, + GL_WRITE_ONLY, img.format->format); + + ret &= set_uniform_int(prog, "src_img", unit) && + set_uniform_int(prog, "dst_img", 6) && + draw_grid(grid, prog); + + glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); + + glGetTexImage(GL_TEXTURE_2D, 0, img.format->pixel_format, + image_base_type(img.format), r_pixels); + + glDeleteProgram(prog); + glDeleteTextures(1, &tmp_tex); + + glBindFramebuffer(GL_FRAMEBUFFER, fb[0]); + glViewportIndexedfv(0, vp[0]); + + if (!ret) + return false; + break; + } + default: + abort(); + } + + return piglit_check_gl_error(GL_NO_ERROR); +} + +bool +init_pixels(const struct image_info img, uint32_t *r_pixels, + double r, double g, double b, double a) +{ + const double init[4] = { r, g, b, a }; + const unsigned m = image_num_components(img.format); + unsigned i, j; + + for (i = 0; i < product(img.size); ++i) { + for (j = 0; j < m; ++j) { + r_pixels[i * m + j] = encode(img.format, init[j]); + } + } + + return true; +} + +static bool +check_pixels_vs(const struct image_info img, unsigned stride, + const uint32_t *pixels, const uint32_t *expect) +{ + const unsigned m = image_num_components(img.format); + unsigned i, j; + + for (i = 0; i < product(img.size); ++i) { + const uint32_t *v = &pixels[m * i]; + const uint32_t *u = &expect[stride * m * i]; + + for (j = 0; j < m; ++j) { + if ((fabs(decode(img.format, v[j]) - decode(img.format, u[j])) > + get_idx(img.epsilon, j)) && + isfinite(decode(img.format, u[j]))) { + printf("Probe value at (%u, %u, %u, %u)\n", + i % img.size.x, + i / img.size.x % img.size.y, + i / img.size.x / img.size.y % img.size.z, + i / img.size.x / img.size.y / img.size.z); + + printf(" Expected:"); + + for (j = 0; j < m; ++j) + printf(" %f", decode(img.format, u[j])); + + printf("\n Observed:"); + + for (j = 0; j < m; ++j) + printf(" %f", decode(img.format, v[j])); + + printf("\n"); + return false; + } + } + } + + return true; +} + +bool +check_pixels(const struct image_info img, const uint32_t *pixels, + double r, double g, double b, double a) +{ + const uint32_t expect[4] = { + encode(img.format, r), encode(img.format, g), + encode(img.format, b), encode(img.format, a) + }; + + return check_pixels_vs(img, 0, pixels, expect); +} + +bool +check_pixels_v(const struct image_info img, const uint32_t *pixels, + const uint32_t *expect) +{ + return check_pixels_vs(img, 1, pixels, expect); +} + +bool +init_fb(const struct grid_info grid) +{ + bool ret = true; + + if (grid.stages & GL_COMPUTE_SHADER_BIT) { + const struct image_info img = image_info_for_grid(grid); + const unsigned n = product(grid.size) * + image_num_components(grid.format); + uint32_t *pixels = malloc(n * sizeof(*pixels)); + + ret = init_pixels(img, pixels, 0.5, 0.5, 0.5, 0.5) && + upload_image(img, 7, pixels); + + free(pixels); + } else { + ret = generate_fb(grid, 0); + + glClearColor(0.5, 0.5, 0.5, 0.5); + glClear(GL_COLOR_BUFFER_BIT); + + glClearDepth(0.5); + glClear(GL_DEPTH_BUFFER_BIT); + } + + return ret; +} + +bool +download_result(const struct grid_info grid, uint32_t *r_pixels) +{ + if (grid.stages & GL_COMPUTE_SHADER_BIT) { + /* No actual framebuffer. Results are returned into + * an image. */ + return download_image(image_info_for_grid(grid), 7, r_pixels); + + } else { + glReadPixels(0, 0, grid.size.x, grid.size.y, + grid.format->pixel_format, + image_base_type(grid.format), + r_pixels); + return piglit_check_gl_error(GL_NO_ERROR); + } +} diff --git a/tests/spec/arb_shader_image_load_store/common.h b/tests/spec/arb_shader_image_load_store/common.h new file mode 100644 index 000000000..800a116f6 --- /dev/null +++ b/tests/spec/arb_shader_image_load_store/common.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** @file common.h + * + * Common utility functions for the ARB_shader_image_load_store tests. + */ + +#ifndef __PIGLIT_ARB_SHADER_IMAGE_LOAD_STORE_COMMON_H__ +#define __PIGLIT_ARB_SHADER_IMAGE_LOAD_STORE_COMMON_H__ + +#include "image.h" +#include "grid.h" +#include "piglit-util-gl.h" + +/** + * Report the result of a subtest using a more convenient syntax. + */ +#define subtest(status, guard, result, ...) do { \ + enum piglit_result _status = (!(guard) ? PIGLIT_SKIP : \ + (result) ? PIGLIT_PASS : \ + PIGLIT_FAIL); \ + \ + piglit_report_subtest_result(_status, __VA_ARGS__); \ + \ + if (_status == PIGLIT_FAIL) \ + *status = PIGLIT_FAIL; \ + } while (0) + +/** + * Set an integer uniform to the specified value. + */ +bool +set_uniform_int(GLuint prog, const char *name, int value); + +/** + * Accessor for the texture object bound to the specified image unit. + */ +GLuint +get_texture(unsigned unit); + +/** + * Accessor for the buffer object bound to the specified image unit. + */ +GLuint +get_buffer(unsigned unit); + +/** + * Upload \a pixels to an image of the specified format and + * dimensionality, and bind it to the specified image unit. + */ +bool +upload_image(const struct image_info img, unsigned unit, + const uint32_t *pixels); + +/** + * Analogous to upload_image(), but in addition it may be used to + * specify \a num_levels mipmap levels for the same texture at once. + * Level \a level will be bound to the given image unit. + */ +bool +upload_image_levels(const struct image_info img, unsigned num_levels, + unsigned level, unsigned unit, + const uint32_t *pixels); + +/** + * Download the image bound to the specified image unit into + * \a r_pixels. + */ +bool +download_image(const struct image_info img, unsigned unit, + uint32_t *r_pixels); + +/** + * Analogous to download_image(), but in addition it may be used to + * download \a num_levels mipmap levels at once from the same image. + */ +bool +download_image_levels(const struct image_info img, unsigned num_levels, + unsigned unit, uint32_t *r_pixels); + +/** + * Initialize a two-dimensional array of pixels to the specified + * constant value. + */ +bool +init_pixels(const struct image_info img, uint32_t *pixels, + double r, double g, double b, double a); + +/** + * Check that all elements from a two-dimensional array of pixels + * equal the specified constant value. + */ +bool +check_pixels(const struct image_info img, const uint32_t *pixels, + double r, double g, double b, double a); + +/** + * Check that two two-dimensional arrays of pixels are equal. + */ +bool +check_pixels_v(const struct image_info img, + const uint32_t *pixels, + const uint32_t *expect); + +/** + * Initialize and clear the framebuffer, or an image read-back buffer + * when using the compute stage. + */ +bool +init_fb(const struct grid_info grid); + +/** + * Download the contents of the framebuffer, or the image read-back + * buffer when using the compute stage. + */ +bool +download_result(const struct grid_info grid, uint32_t *r_pixels); + +#endif |