Reviewed-by: Jordan Justen <jordan.l.jus...@intel.com>
On 2015-01-31 07:41:24, Francisco Jerez wrote: > Define helper data structures and functions to query several kinds of > information for any supported image format, target or shader stage, > like the matching pixel transfer type and format for a given image > format, GLSL type information, error tolerance, maximum supported > dimensions and samples for a given image dimensionality, number of > supported image uniforms for a given shader stage, etc. > > This also defines the image_info data structure that aggregates some > combination of image target, format and dimensions in a single object > to avoid having to repeat the same three arguments constantly when > working with images. > > v2: Encode per-image base datatype information in a struct instead of > having separate switch-case statements spread over several query > functions. Add comment explaining the reason why there are no > specific semantics attached to image dimensions. (Ian) > --- > tests/spec/arb_shader_image_load_store/image.c | 743 > +++++++++++++++++++++++++ > tests/spec/arb_shader_image_load_store/image.h | 386 +++++++++++++ > 2 files changed, 1129 insertions(+) > create mode 100644 tests/spec/arb_shader_image_load_store/image.c > create mode 100644 tests/spec/arb_shader_image_load_store/image.h > > diff --git a/tests/spec/arb_shader_image_load_store/image.c > b/tests/spec/arb_shader_image_load_store/image.c > new file mode 100644 > index 0000000..58cda9b > --- /dev/null > +++ b/tests/spec/arb_shader_image_load_store/image.c > @@ -0,0 +1,743 @@ > +/* > + * 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 image.c > + * > + * Common image format, target and shader stage metadata. > + */ > + > +#include "image.h" > + > +struct image_extent > +image_optimal_extent(struct image_extent ext) > +{ > + const unsigned n = product(ext); > + const unsigned w = 1 << MIN2(ffs(n) - 1, (int)log2(n) / 2); > + const struct image_extent opt = { > + w, n / w, 1, 1 > + }; > + > + return opt; > +} > + > +const struct image_format_info image_formats_load_store[] = { > + { "rgba32f", GL_RGBA32F, GL_RGBA, GL_FLOAT, { 32, 32, 32, 32 } }, > + { "rgba16f", GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, { 16, 16, 16, 16 } > }, > + { "rg32f", GL_RG32F, GL_RG, GL_FLOAT, { 32, 32, 0, 0 } }, > + { "rg16f", GL_RG16F, GL_RG, GL_HALF_FLOAT, { 16, 16, 0, 0 } }, > + { "r11f_g11f_b10f", GL_R11F_G11F_B10F, GL_RGB, > GL_UNSIGNED_INT_10F_11F_11F_REV, { 11, 11, 10, 0 } }, > + { "r32f", GL_R32F, GL_RED, GL_FLOAT, { 32, 0, 0, 0 } }, > + { "r16f", GL_R16F, GL_RED, GL_HALF_FLOAT, { 16, 0, 0, 0 } }, > + { "rgba32ui", GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, { 32, > 32, 32, 32 } }, > + { "rgba16ui", GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, { 16, > 16, 16, 16 } }, > + { "rgb10_a2ui", GL_RGB10_A2UI, GL_RGBA_INTEGER, > GL_UNSIGNED_INT_2_10_10_10_REV, { 10, 10, 10, 2 } }, > + { "rgba8ui", GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, { 8, 8, > 8, 8 } }, > + { "rg32ui", GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, { 32, 32, 0, > 0 } }, > + { "rg16ui", GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT, { 16, 16, > 0, 0 } }, > + { "rg8ui", GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE, { 8, 8, 0, 0 } > }, > + { "r32ui", GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, { 32, 0, 0, 0 > } }, > + { "r16ui", GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, { 16, 0, 0, > 0 } }, > + { "r8ui", GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, { 8, 0, 0, 0 } > }, > + { "rgba32i", GL_RGBA32I, GL_RGBA_INTEGER, GL_INT, { 32, 32, 32, 32 } > }, > + { "rgba16i", GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT, { 16, 16, 16, 16 > } }, > + { "rgba8i", GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, { 8, 8, 8, 8 } }, > + { "rg32i", GL_RG32I, GL_RG_INTEGER, GL_INT, { 32, 32, 0, 0 } }, > + { "rg16i", GL_RG16I, GL_RG_INTEGER, GL_SHORT, { 16, 16, 0, 0 } }, > + { "rg8i", GL_RG8I, GL_RG_INTEGER, GL_BYTE, { 8, 8, 0, 0 } }, > + { "r32i", GL_R32I, GL_RED_INTEGER, GL_INT, { 32, 0, 0, 0 } }, > + { "r16i", GL_R16I, GL_RED_INTEGER, GL_SHORT, { 16, 0, 0, 0 } }, > + { "r8i", GL_R8I, GL_RED_INTEGER, GL_BYTE, { 8, 0, 0, 0 } }, > + { "rgba16", GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, { 16, 16, 16, 16 > } }, > + { "rgb10_a2", GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, > { 10, 10, 10, 2 } }, > + { "rgba8", GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, { 8, 8, 8, 8 } }, > + { "rg16", GL_RG16, GL_RG, GL_UNSIGNED_SHORT, { 16, 16, 0, 0 } }, > + { "rg8", GL_RG8, GL_RG, GL_UNSIGNED_BYTE, { 8, 8, 0, 0 } }, > + { "r16", GL_R16, GL_RED, GL_UNSIGNED_SHORT, { 16, 0, 0, 0 } }, > + { "r8", GL_R8, GL_RED, GL_UNSIGNED_BYTE, { 8, 0, 0, 0 } }, > + { "rgba16_snorm", GL_RGBA16_SNORM, GL_RGBA, GL_SHORT, { 16, 16, 16, > 16 } }, > + { "rgba8_snorm", GL_RGBA8_SNORM, GL_RGBA, GL_BYTE, { 8, 8, 8, 8 } }, > + { "rg16_snorm", GL_RG16_SNORM, GL_RG, GL_SHORT, { 16, 16, 0, 0 } }, > + { "rg8_snorm", GL_RG8_SNORM, GL_RG, GL_BYTE, { 8, 8, 0, 0 } }, > + { "r16_snorm", GL_R16_SNORM, GL_RED, GL_SHORT, { 16, 0, 0, 0 } }, > + { "r8_snorm", GL_R8_SNORM, GL_RED, GL_BYTE, { 8, 0, 0, 0 } }, > + { 0 } > +}; > + > +const struct image_format_info image_formats_atomic[] = { > + { "r32ui", GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, { 32, 0, 0, 0 > } }, > + { "r32i", GL_R32I, GL_RED_INTEGER, GL_INT, { 32, 0, 0, 0 } }, > + { 0 } > +}; > + > +const struct image_format_info * > +get_image_format(GLenum f) > +{ > + const struct image_format_info *format; > + > + for (format = image_formats_load_store; format->format; ++format) { > + if (format->format == f) > + return format; > + } > + > + return NULL; > +} > + > +/** > + * Information specific to an image base data type as seen by the > + * shader. > + */ > +struct image_type_info { > + /** Logical base format as seen by the shader. */ > + GLenum base_format; > + > + /** Logical component type as seen by the shader. */ > + GLenum base_type; > + > + /** Logical internal format as seen by the shader. */ > + GLenum base_internal_format; > + > + /** Matching GLSL component data type. */ > + const char *scalar_type_name; > + > + /** Matching GLSL vector data type. */ > + const char *vector_type_name; > + > + /** GLSL image type prefix ("i", "u" or ""). */ > + const char *image_type_name; > +}; > + > +static const struct image_type_info * > +get_image_type(const struct image_format_info *format) > +{ > + switch (format->pixel_format) { > + case GL_RGBA: > + case GL_RGB: > + case GL_RG: > + case GL_RED: { > + static const struct image_type_info type = { > + GL_RGBA, GL_FLOAT, GL_RGBA32F, > + "float", "vec4", "image" > + }; > + return &type; > + } > + case GL_RGBA_INTEGER: > + case GL_RG_INTEGER: > + case GL_RED_INTEGER: > + switch (format->pixel_type) { > + case GL_INT: > + case GL_SHORT: > + case GL_BYTE: { > + static const struct image_type_info type = { > + GL_RGBA_INTEGER, GL_INT, GL_RGBA32I, > + "int", "ivec4", "iimage" > + }; > + return &type; > + } > + case GL_UNSIGNED_INT: > + case GL_UNSIGNED_SHORT: > + case GL_UNSIGNED_INT_2_10_10_10_REV: > + case GL_UNSIGNED_BYTE: { > + static const struct image_type_info type = { > + GL_RGBA_INTEGER, GL_UNSIGNED_INT, > GL_RGBA32UI, > + "uint", "uvec4", "uimage" > + }; > + return &type; > + } > + default: > + abort(); > + } > + default: > + abort(); > + } > +} > + > +GLenum > +image_base_format(const struct image_format_info *format) > +{ > + return get_image_type(format)->base_format; > +} > + > +GLenum > +image_base_type(const struct image_format_info *format) > +{ > + return get_image_type(format)->base_type; > +} > + > +GLenum > +image_base_internal_format(const struct image_format_info *format) > +{ > + return get_image_type(format)->base_internal_format; > +} > + > +const char * > +image_scalar_type_name(const struct image_format_info *format) > +{ > + return get_image_type(format)->scalar_type_name; > +} > + > +const char * > +image_vector_type_name(const struct image_format_info *format) > +{ > + return get_image_type(format)->vector_type_name; > +} > + > +const char * > +image_type_name(const struct image_format_info *format) > +{ > + return get_image_type(format)->image_type_name; > +} > + > +GLenum > +image_compat_format(const struct image_format_info *format) > +{ > + const unsigned bits = (format->bits[0] + format->bits[1] + > + format->bits[2] + format->bits[3]); > + > + switch (bits) { > + case 128: > + return GL_RGBA32UI; > + > + case 64: > + return GL_RG32UI; > + > + case 32: > + return GL_R32UI; > + > + case 16: > + return GL_R16UI; > + > + case 8: > + return GL_R8UI; > + > + default: > + abort(); > + } > +} > + > +unsigned > +image_num_components(const struct image_format_info *format) > +{ > + return (!!format->bits[0] + !!format->bits[1] + > + !!format->bits[2] + !!format->bits[3]); > +} > + > +struct image_datum > +image_format_scale(const struct image_format_info *format) > +{ > + struct image_datum v = { 0.0 }; > + int i; > + > + for (i = 0; i < 4 && format->bits[i]; ++i) { > + switch (image_base_type(format)) { > + case GL_FLOAT: > + set_idx(v, i, 1.0); > + break; > + > + case GL_INT: > + set_idx(v, i, 1u << (format->bits[i] - 2)); > + break; > + > + case GL_UNSIGNED_INT: > + set_idx(v, i, 1u << (format->bits[i] - 1)); > + break; > + > + default: > + abort(); > + } > + } > + > + return v; > +} > + > +static unsigned > +image_channel_fraction_bits(const struct image_format_info *format, unsigned > i) > +{ > + if (image_base_type(format) == GL_FLOAT && format->bits[i]) { > + switch (format->pixel_type) { > + case GL_FLOAT: > + return 23; > + > + case GL_HALF_FLOAT: > + return 10; > + > + case GL_UNSIGNED_INT_10F_11F_11F_REV: > + return format->bits[i] - 5; > + > + case GL_SHORT: > + case GL_BYTE: > + return format->bits[i] - 1; > + > + case GL_UNSIGNED_SHORT: > + case GL_UNSIGNED_INT_2_10_10_10_REV: > + case GL_UNSIGNED_BYTE: > + return format->bits[i]; > + > + default: > + abort(); > + } > + } else { > + return 0; > + } > +} > + > +struct image_datum > +image_format_epsilon(const struct image_format_info *format) > +{ > + struct image_datum v = { 0.0 }; > + int i; > + > + for (i = 0; i < 4; ++i) { > + unsigned p = image_channel_fraction_bits(format, i); > + set_idx(v, i, (p ? MAX2(1.0 / ((1 << p) - 1), 1e-5) : 0)); > + } > + > + return v; > +} > + > +uint32_t > +encode(const struct image_format_info *format, double x) > +{ > + switch (image_base_type(format)) { > + case GL_UNSIGNED_INT: > + return x; > + > + case GL_INT: > + return (int32_t)x; > + > + case GL_FLOAT: { > + float y = x; > + return *(uint32_t *)&y; > + } > + default: > + abort(); > + } > +} > + > +double > +decode(const struct image_format_info *format, uint32_t x) > +{ > + switch (image_base_type(format)) { > + case GL_UNSIGNED_INT: > + return x; > + > + case GL_INT: > + return (int32_t)x; > + > + case GL_FLOAT: > + return *(float *)&x; > + > + default: > + abort(); > + } > +} > + > +const struct image_target_info * > +image_targets(void) > +{ > + const struct image_target_info known[] = { > + { "1D", GL_TEXTURE_1D, "int" }, > + { "2D", GL_TEXTURE_2D, "ivec2" }, > + { "3D", GL_TEXTURE_3D, "ivec3" }, > + { "2DRect", GL_TEXTURE_RECTANGLE, "ivec2" }, > + { "Cube", GL_TEXTURE_CUBE_MAP, "ivec3" }, > + { "Buffer", GL_TEXTURE_BUFFER, "int" }, > + { "1DArray", GL_TEXTURE_1D_ARRAY, "ivec2" }, > + { "2DArray", GL_TEXTURE_2D_ARRAY, "ivec3" }, > + { "CubeArray", GL_TEXTURE_CUBE_MAP_ARRAY, "ivec3" }, > + { "2DMS", GL_TEXTURE_2D_MULTISAMPLE, "ivec2" }, > + { "2DMSArray", GL_TEXTURE_2D_MULTISAMPLE_ARRAY, "ivec3" }, > + { 0 } > + }; > + static struct image_target_info supported[ARRAY_SIZE(known)]; > + > + if (!supported[0].name) { > + int max_samples = 0, i, n = 0; > + > + glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &max_samples); > + > + for (i = 0; i < ARRAY_SIZE(known); ++i) { > + if ((known[i].target != GL_TEXTURE_2D_MULTISAMPLE && > + known[i].target != > GL_TEXTURE_2D_MULTISAMPLE_ARRAY) || > + max_samples > 1) { > + supported[n++] = known[i]; > + } > + } > + } > + > + return supported; > +} > + > +const struct image_target_info * > +get_image_target(GLenum t) > +{ > + const struct image_target_info *target; > + > + for (target = image_targets(); target->target; ++target) { > + if (target->target == t) > + return target; > + } > + > + return NULL; > +} > + > +struct image_extent > +image_target_limits(const struct image_target_info *target) > +{ > + struct image_extent ext = { 1, 1, 1, 1 }; > + > + switch (target->target) { > + case GL_TEXTURE_1D: > + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (int *)&ext.x); > + break; > + > + case GL_TEXTURE_2D: > + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (int *)&ext.x); > + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (int *)&ext.y); > + break; > + > + case GL_TEXTURE_3D: > + glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, (int *)&ext.x); > + glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, (int *)&ext.y); > + glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, (int *)&ext.z); > + break; > + > + case GL_TEXTURE_RECTANGLE: > + glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE, (int *)&ext.x); > + glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE, (int *)&ext.y); > + break; > + > + case GL_TEXTURE_CUBE_MAP: > + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, (int *)&ext.x); > + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, (int *)&ext.y); > + ext.z = 6; > + break; > + > + case GL_TEXTURE_BUFFER: > + glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, (int *)&ext.x); > + break; > + > + case GL_TEXTURE_1D_ARRAY: > + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (int *)&ext.x); > + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, (int *)&ext.y); > + break; > + > + case GL_TEXTURE_2D_ARRAY: > + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (int *)&ext.x); > + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (int *)&ext.y); > + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, (int *)&ext.z); > + break; > + > + case GL_TEXTURE_CUBE_MAP_ARRAY: > + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, (int *)&ext.x); > + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, (int *)&ext.y); > + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, (int *)&ext.z); > + break; > + > + case GL_TEXTURE_2D_MULTISAMPLE: > + glGetIntegerv(GL_MAX_IMAGE_SAMPLES, (int *)&ext.x); > + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (int *)&ext.y); > + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (int *)&ext.z); > + break; > + > + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: > + glGetIntegerv(GL_MAX_IMAGE_SAMPLES, (int *)&ext.x); > + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (int *)&ext.y); > + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (int *)&ext.z); > + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, (int *)&ext.w); > + break; > + > + default: > + abort(); > + } > + > + return ext; > +} > + > +unsigned > +image_target_samples(const struct image_target_info *target) > +{ > + if (target->target == GL_TEXTURE_2D_MULTISAMPLE || > + target->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { > + return image_target_limits(target).x; > + } else { > + return 1; > + } > +} > + > +struct image_extent > +image_extent_for_target(const struct image_target_info *target, > + unsigned w, unsigned h) > +{ > + switch (target->target) { > + case GL_TEXTURE_1D: { > + struct image_extent ext = { w * h, 1, 1, 1 }; > + return ext; > + } > + case GL_TEXTURE_2D: { > + struct image_extent ext = { w, h, 1, 1 }; > + return ext; > + } > + case GL_TEXTURE_3D: { > + struct image_extent ext = { w, w, h / w, 1 }; > + return ext; > + } > + case GL_TEXTURE_RECTANGLE: { > + struct image_extent ext = { w, h, 1, 1 }; > + return ext; > + } > + case GL_TEXTURE_CUBE_MAP: { > + struct image_extent ext = { w, w, h / w, 1 }; > + assert(ext.z == 6); > + return ext; > + } > + case GL_TEXTURE_BUFFER: { > + struct image_extent ext = { w * h, 1, 1, 1 }; > + return ext; > + } > + case GL_TEXTURE_1D_ARRAY: { > + struct image_extent ext = { w, h, 1, 1 }; > + return ext; > + } > + case GL_TEXTURE_2D_ARRAY: { > + struct image_extent ext = { w, w, h / w, 1 }; > + return ext; > + } > + case GL_TEXTURE_CUBE_MAP_ARRAY: { > + struct image_extent ext = { w, w, h / w, 1 }; > + assert(ext.z % 6 == 0); > + return ext; > + } > + case GL_TEXTURE_2D_MULTISAMPLE: { > + struct image_extent ext = { 2, w / 2, h, 1 }; > + return ext; > + } > + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: { > + struct image_extent ext = { 2, w / 2, w, h / w }; > + return ext; > + } > + default: > + abort(); > + } > +} > + > +GLenum > +image_layer_target(const struct image_target_info *target) > +{ > + switch (target->target) { > + case GL_TEXTURE_1D: > + case GL_TEXTURE_1D_ARRAY: > + return GL_TEXTURE_1D; > + > + case GL_TEXTURE_2D: > + case GL_TEXTURE_3D: > + case GL_TEXTURE_CUBE_MAP: > + case GL_TEXTURE_2D_ARRAY: > + case GL_TEXTURE_CUBE_MAP_ARRAY: > + return GL_TEXTURE_2D; > + > + case GL_TEXTURE_RECTANGLE: > + return GL_TEXTURE_RECTANGLE; > + > + case GL_TEXTURE_BUFFER: > + return GL_TEXTURE_BUFFER; > + > + case GL_TEXTURE_2D_MULTISAMPLE: > + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: > + return GL_TEXTURE_2D_MULTISAMPLE; > + > + default: > + abort(); > + } > +} > + > +unsigned > +image_target_mipmapping_dimensions(const struct image_target_info *target) > +{ > + switch (target->target) { > + case GL_TEXTURE_RECTANGLE: > + case GL_TEXTURE_BUFFER: > + case GL_TEXTURE_2D_MULTISAMPLE: > + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: > + return 0; > + > + case GL_TEXTURE_1D: > + case GL_TEXTURE_1D_ARRAY: > + return 1; > + > + case GL_TEXTURE_2D: > + case GL_TEXTURE_CUBE_MAP: > + case GL_TEXTURE_2D_ARRAY: > + case GL_TEXTURE_CUBE_MAP_ARRAY: > + return 2; > + > + case GL_TEXTURE_3D: > + return 3; > + > + default: > + abort(); > + } > +} > + > +const struct image_stage_info * > +image_stages(void) > +{ > + const struct image_stage_info known[] = { > + { "Vertex", GL_VERTEX_SHADER, GL_VERTEX_SHADER_BIT }, > + { "Tessellation control", GL_TESS_CONTROL_SHADER, > + GL_TESS_CONTROL_SHADER_BIT }, > + { "Tessellation evaluation", GL_TESS_EVALUATION_SHADER, > + GL_TESS_EVALUATION_SHADER_BIT }, > + { "Geometry", GL_GEOMETRY_SHADER, GL_GEOMETRY_SHADER_BIT }, > + { "Fragment", GL_FRAGMENT_SHADER, GL_FRAGMENT_SHADER_BIT }, > + { "Compute", GL_COMPUTE_SHADER, GL_COMPUTE_SHADER_BIT }, > + }; > + static struct image_stage_info supported[ARRAY_SIZE(known) + 1]; > + > + if (!supported[0].name) { > + int i, n = 0; > + > + for (i = 0; i < ARRAY_SIZE(known); ++i) { > + if (image_stage_max_images(&known[i])) > + supported[n++] = known[i]; > + } > + } > + > + return supported; > +} > + > +const struct image_stage_info * > +get_image_stage(GLenum s) > +{ > + const struct image_stage_info *stage; > + > + for (stage = image_stages(); stage->stage; ++stage) { > + if (stage->stage == s) > + return stage; > + } > + > + return NULL; > +} > + > +unsigned > +image_stage_max_images(const struct image_stage_info *stage) > +{ > + int n = 0; > + > + switch (stage->stage) { > + case GL_FRAGMENT_SHADER: > + glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &n); > + return n; > + > + case GL_VERTEX_SHADER: > + glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &n); > + return n; > + > + case GL_GEOMETRY_SHADER: > + if (piglit_get_gl_version() >= 32) > + glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &n); > + return n; > + > + case GL_TESS_CONTROL_SHADER: > + if > (piglit_is_extension_supported("GL_ARB_tessellation_shader")) > + glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, > &n); > + return n; > + > + case GL_TESS_EVALUATION_SHADER: > + if > (piglit_is_extension_supported("GL_ARB_tessellation_shader")) > + glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, > + &n); > + return n; > + > + case GL_COMPUTE_SHADER: > + if (piglit_is_extension_supported("GL_ARB_compute_shader")) > + glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &n); > + return n; > + > + default: > + return 0; > + } > +} > + > +unsigned > +max_combined_images(void) > +{ > + int n; > + > + glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &n); > + return n; > +} > + > +unsigned > +max_image_units(void) > +{ > + int n; > + > + glGetIntegerv(GL_MAX_IMAGE_UNITS, &n); > + return n; > +} > + > +unsigned > +image_num_layers(const struct image_info img) > +{ > + switch (image_layer_target(img.target)) { > + case GL_TEXTURE_1D: > + return img.size.y; > + > + case GL_TEXTURE_2D: > + return img.size.z; > + > + case GL_TEXTURE_2D_MULTISAMPLE: > + return img.size.w; > + > + default: > + return 1; > + } > +} > + > +unsigned > +image_num_levels(const struct image_info img) > +{ > + const unsigned d = image_target_mipmapping_dimensions(img.target); > + unsigned i, size = 1; > + > + for (i = 0; i < d; ++i) > + size = MAX2(size, get_idx(img.size, i)); > + > + return (unsigned)log2(size) + 1; > +} > + > +struct image_extent > +image_level_size(const struct image_info img, unsigned l) > +{ > + const unsigned d = image_target_mipmapping_dimensions(img.target); > + struct image_extent size; > + int i; > + > + for (i = 0; i < d; ++i) > + set_idx(size, i, MAX2(get_idx(img.size, i) >> l, 1)); > + > + for (i = d; i < 4; ++i) > + set_idx(size, i, get_idx(img.size, i)); > + > + return size; > +} > diff --git a/tests/spec/arb_shader_image_load_store/image.h > b/tests/spec/arb_shader_image_load_store/image.h > new file mode 100644 > index 0000000..54d32ed > --- /dev/null > +++ b/tests/spec/arb_shader_image_load_store/image.h > @@ -0,0 +1,386 @@ > +/* > + * 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 image.h > + * > + * Common image format, target and shader stage metadata. > + */ > + > +#ifndef __PIGLIT_ARB_SHADER_IMAGE_LOAD_STORE_IMAGE_H__ > +#define __PIGLIT_ARB_SHADER_IMAGE_LOAD_STORE_IMAGE_H__ > + > +#include "piglit-util-gl.h" > + > +/** > + * Image color value. > + */ > +struct image_datum { > + double x; > + double y; > + double z; > + double w; > +}; > + > +/** > + * Size of an image. > + * > + * Note that most tests treat images as a 4-dimensional array of > + * pixels with no specific semantics attached to each dimension > + * (e.g. the x dimension will be the number of samples for multisample > + * images but the horizontal coordinate for 2D textures). This is a > + * deliberate decision that greatly reduces the amount of duplication, > + * as in many cases you can just run the same test in a loop for all > + * image targets. > + * > + * Unused dimensions equal 1 by convention. > + */ > +struct image_extent { > + unsigned x; > + unsigned y; > + unsigned z; > + unsigned w; > +}; > + > +#define get_idx(v, i) \ > + ((i) == 0 ? (v).x : \ > + (i) == 1 ? (v).y : \ > + (i) == 2 ? (v).z : \ > + (i) == 3 ? (v).w : 0) > + > +#define set_idx(v, i, a) \ > + (*((i) == 0 ? &(v).x : \ > + (i) == 1 ? &(v).y : \ > + (i) == 2 ? &(v).z : \ > + (i) == 3 ? &(v).w : NULL)) = (a) > + > +#define product(v) ((v).x * (v).y * (v).z * (v).w) > + > +/** > + * Get a two-dimensional image_extent with the same number of elements > + * as the argument, where each dimension is reasonably close to the > + * square root of the total number of elements, e.g. for use as grid > + * invocation size. > + */ > +struct image_extent > +image_optimal_extent(struct image_extent ext); > + > +struct image_format_info { > + /** Format name as specified by GLSL. */ > + const char *name; > + > + /** Format enum. */ > + GLenum format; > + > + /** Pixel transfer format (e.g. as specified for glGetTexImage()). */ > + GLenum pixel_format; > + > + /** Pixel transfer type (e.g. as specified for glGetTexImage()). */ > + GLenum pixel_type; > + > + /** Number of storage bits for each component. */ > + unsigned bits[4]; > +}; > + > +/** > + * Image formats supported by image load and store built-ins. > + */ > +extern const struct image_format_info image_formats_load_store[]; > + > +/** > + * Image formats supported by image atomic built-ins. > + */ > +extern const struct image_format_info image_formats_atomic[]; > + > +/** > + * Get information for the specified image format. > + */ > +const struct image_format_info * > +get_image_format(GLenum format); > + > +/** > + * Get the logical base format as seen by the shader (either GL_RGBA > + * or GL_RGBA_INTEGER). > + */ > +GLenum > +image_base_format(const struct image_format_info *format); > + > +/** > + * Get the logical component type as seen by the shader. > + */ > +GLenum > +image_base_type(const struct image_format_info *format); > + > +/** > + * Get the logical internal format as seen by the shader. > + */ > +GLenum > +image_base_internal_format(const struct image_format_info *format); > + > +/** > + * Get the GLSL component data type for an image format. > + */ > +const char * > +image_scalar_type_name(const struct image_format_info *format); > + > +/** > + * Get the GLSL vector data type for an image format. > + */ > +const char * > +image_vector_type_name(const struct image_format_info *format); > + > +/** > + * Get the GLSL image type prefix for an image format ("i", "u" or > + * ""). > + */ > +const char * > +image_type_name(const struct image_format_info *format); > + > +/** > + * Get a compatible unsigned integer format of the same size. > + */ > +GLenum > +image_compat_format(const struct image_format_info *format); > + > +/** > + * Get the number of color components representable in an image format. > + */ > +unsigned > +image_num_components(const struct image_format_info *format); > + > +/** > + * Get an arbitrary per-component test scale used to make sure that we > + * exercise a significant portion of the representable range without > + * overflowing it. > + */ > +struct image_datum > +image_format_scale(const struct image_format_info *format); > + > +/** > + * Get the per-component error tolerance for an image format. > + */ > +struct image_datum > +image_format_epsilon(const struct image_format_info *format); > + > +/** > + * Convert \a x to the base data type of the specified image format. > + */ > +uint32_t > +encode(const struct image_format_info *format, double x); > + > +/** > + * Convert \a x from the base data type of the specified image format. > + */ > +double > +decode(const struct image_format_info *format, uint32_t x); > + > +struct image_target_info { > + /** Target name and GLSL image type suffix. */ > + const char *name; > + > + /** Target enum. */ > + GLenum target; > + > + /** Vector type used as address argument for this target. */ > + const char *addr_type_name; > +}; > + > +/** > + * Get all image targets supported by the implementation. > + */ > +const struct image_target_info * > +image_targets(void); > + > +/** > + * Get information for the specified target. > + */ > +const struct image_target_info * > +get_image_target(GLenum t); > + > +/** > + * Get the maximum supported dimensions for the specified target. > + */ > +struct image_extent > +image_target_limits(const struct image_target_info *target); > + > +/** > + * Get the maximum supported number of samples for the specified > + * target. > + */ > +unsigned > +image_target_samples(const struct image_target_info *target); > + > +/** > + * Get reasonable dimensions for an image of type \a target intended > + * to be in one-to-one mapping to a two-dimensional grid of dimensions > + * \a w and \a h. > + */ > +struct image_extent > +image_extent_for_target(const struct image_target_info *target, > + unsigned w, unsigned h); > + > +/** > + * Get the target type for a single layer of the specified image > + * target. > + */ > +GLenum > +image_layer_target(const struct image_target_info *target); > + > +/** > + * Get the number of dimensions of an image target that are minified > + * in higher mipmap levels. > + */ > +unsigned > +image_target_mipmapping_dimensions(const struct image_target_info *target); > + > +struct image_stage_info { > + /** Shader stage name. */ > + const char *name; > + > + /** Target enum. */ > + GLenum stage; > + > + /** Value used in bit sets for this shader stage. */ > + GLbitfield bit; > +}; > + > +/** > + * Get all shader stages that support image access in pipeline order. > + */ > +const struct image_stage_info * > +image_stages(void); > + > +/** > + * Get information for the specified stage. > + */ > +const struct image_stage_info * > +get_image_stage(GLenum s); > + > +/** > + * Get the maximum number of supported image uniforms from the > + * specified stage. > + */ > +unsigned > +image_stage_max_images(const struct image_stage_info *stage); > + > +/** > + * Get the maximum sum of image uniforms from all shaders. > + */ > +unsigned > +max_combined_images(void); > + > +/** > + * Get the maximum number of independent image units. > + */ > +unsigned > +max_image_units(void); > + > +struct image_info { > + /** Texture target of this image object. */ > + const struct image_target_info *target; > + > + /** Format of this image object. */ > + const struct image_format_info *format; > + > + /** Dimensions of this image object. */ > + struct image_extent size; > + > + /** Error tolerance for this image object. */ > + struct image_datum epsilon; > +}; > + > +/** > + * Construct an image_info object. > + */ > +static inline struct image_info > +image_info(GLenum target, GLenum format, unsigned w, unsigned h) > +{ > + const struct image_target_info *t = get_image_target(target); > + const struct image_format_info *f = get_image_format(format); > + const struct image_info img = { > + t, f, > + image_extent_for_target(t, w, h), > + image_format_epsilon(f) > + }; > + > + return img; > +} > + > +/** > + * Set the dimensions of an image. > + */ > +static inline struct image_info > +set_image_size(struct image_info img, > + unsigned x, unsigned y, unsigned z, unsigned w) > +{ > + const struct image_extent size = { x, y, z, w }; > + img.size = size; > + return img; > +} > + > +/** > + * Get the number of layers of an image. > + */ > +unsigned > +image_num_layers(const struct image_info img); > + > +/** > + * Get the maximum number of mipmap levels for an image. > + */ > +unsigned > +image_num_levels(const struct image_info img); > + > +/** > + * Get the dimensions of the specified mipmap level of an image. > + */ > +struct image_extent > +image_level_size(const struct image_info img, unsigned l); > + > +/** > + * Get the offset in texels of the specified mipmap level of an > + * image. > + */ > +static inline unsigned > +image_level_offset(const struct image_info img, unsigned l) > +{ > + return (l == 0 ? 0 : > + image_level_offset(img, l - 1) + > + product(image_level_size(img, l - 1))); > +} > + > +/** > + * Construct an image_info object for mipmap level \a l of the > + * specified base image. > + */ > +static inline struct image_info > +image_info_for_level(struct image_info img, unsigned l) > +{ > + const struct image_info level_img = { > + img.target, img.format, > + image_level_size(img, l), > + img.epsilon > + }; > + > + return level_img; > +} > + > +#endif > -- > 2.1.3 > > _______________________________________________ > Piglit mailing list > Piglit@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/piglit _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/piglit