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

Reply via email to