[Piglit] [PATCH 03/25] arb_shader_image_load_store: Add common image metadata.

Francisco Jerez currojerez at riseup.net
Thu Oct 9 02:09:25 PDT 2014


Ian Romanick <idr at freedesktop.org> writes:

> On 10/05/2014 11:00 PM, 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.
>> ---
>>  tests/spec/arb_shader_image_load_store/image.c | 759 +++++++++++++++++++++++++
>>  tests/spec/arb_shader_image_load_store/image.h | 375 ++++++++++++
>>  2 files changed, 1134 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..7e8d7f9
>> --- /dev/null
>> +++ b/tests/spec/arb_shader_image_load_store/image.c
>> @@ -0,0 +1,759 @@
>> +/*
>> + * 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;
>> +}
>> +
>> +GLenum
>> +image_base_format(const struct image_format_info *format)
>> +{
>> +        switch (format->pixel_format) {
>> +        case GL_RGBA:
>> +        case GL_RGB:
>> +        case GL_RG:
>> +        case GL_RED:
>> +                return GL_RGBA;
>> +
>> +        case GL_RGBA_INTEGER:
>> +        case GL_RG_INTEGER:
>> +        case GL_RED_INTEGER:
>> +                return GL_RGBA_INTEGER;
>> +
>> +        default:
>> +                abort();
>> +        }
>> +}
>> +
>> +GLenum
>> +image_base_type(const struct image_format_info *format)
>> +{
>> +        switch (image_base_format(format)) {
>> +        case GL_RGBA:
>> +                return GL_FLOAT;
>> +
>> +        case GL_RGBA_INTEGER:
>> +                switch (format->pixel_type) {
>> +                case GL_INT:
>> +                case GL_SHORT:
>> +                case GL_BYTE:
>> +                        return GL_INT;
>> +
>> +                case GL_UNSIGNED_INT:
>> +                case GL_UNSIGNED_SHORT:
>> +                case GL_UNSIGNED_INT_2_10_10_10_REV:
>> +                case GL_UNSIGNED_BYTE:
>> +                        return GL_UNSIGNED_INT;
>> +
>> +                default:
>> +                        abort();
>> +                }
>> +        default:
>> +                abort();
>> +        }
>> +}
>> +
>> +GLenum
>> +image_base_internal_format(const struct image_format_info *format)
>> +{
>> +        switch (image_base_type(format)) {
>> +        case GL_FLOAT:
>> +                return GL_RGBA32F;
>> +
>> +        case GL_INT:
>> +                return GL_RGBA32I;
>> +
>> +        case GL_UNSIGNED_INT:
>> +                return GL_RGBA32UI;
>> +
>> +        default:
>> +                abort();
>> +        }
>> +}
>> +
>> +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();
>> +        }
>> +}
>> +
>> +const char *
>> +image_scalar_type_name(const struct image_format_info *format)
>> +{
>> +        switch (image_base_type(format)) {
>> +        case GL_FLOAT:
>> +                return "float";
>> +
>> +        case GL_INT:
>> +                return "int";
>> +
>> +        case GL_UNSIGNED_INT:
>> +                return "uint";
>> +
>> +        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]);
>> +}
>> +
>> +const char *
>> +image_vector_type_name(const struct image_format_info *format)
>> +{
>
> It almost seems like this data (and the other two similar functions)
> should be encoded in a table.  That makes it more obvious where to make
> all the changes (i.e., just add another table entry) when, say,
> GL_DOUBLE support is added.  It's just a thought... I'm not married to it.

Do you mean we could define a table of "struct image_type_info {}" (can
you come up with a better name?) encoding the GLSL scalar, vector and
image types and then look up the correct entry based on the base type?
Sure, I can do that.

>
>> +        switch (image_base_type(format)) {
>> +        case GL_FLOAT:
>> +                return "vec4";
>> +
>> +        case GL_INT:
>> +                return "ivec4";
>> +
>> +        case GL_UNSIGNED_INT:
>> +                return "uvec4";
>> +
>> +        default:
>> +                abort();
>> +        }
>> +}
>> +
>> +const char *
>> +image_type_name(const struct image_format_info *format)
>> +{
>> +        switch (image_base_type(format)) {
>> +        case GL_FLOAT:
>> +                return "image";
>> +
>> +        case GL_INT:
>> +                return "iimage";
>> +
>> +        case GL_UNSIGNED_INT:
>> +                return "uimage";
>> +
>> +        default:
>> +                abort();
>> +        }
>> +}
>> +
>> +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 > 0) {
>> +                                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);
>
> Why did you pick this ordering?  It seems... surprising.
>
> I'm wondering if samples and layers should be stored in explicit fields.
>  Maybe have width, height, depth, layers, ands samples fields that
> always mean those things.  That would eliminate the need for
> image_target_samples, for example.
>

Oh, there's a fairly good reason for this.  Most of the
ARB_shader_image_load_store tests just don't care what kind of texture
target they're dealing with, they just treat the image as a
4-dimensional array of pixels.  This means that in many cases we can
just write one test and run it in a loop for each texture target instead
of writing a different test for each one of the 11 texture targets
supported by ARB_shader_image_load_store.  Detaching any special
semantics from each texture dimension was precisely what I intended :).

Maybe I could document this in a comment somewhere to make this less
surprising?

>> +                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 },
>> +                { 0 }
>> +        };
>> +        static struct image_stage_info supported[ARRAY_SIZE(known)];
>> +
>> +        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;
>
> Should this abort() instead?

Hm, it doesn't make much of a difference because returning zero as
number of supported images will just cause this specific stage to be
skipped, but yeah, probably abort() would make more sense.

Thanks for your feedback Ian!

>
>> +        }
>> +}
>> +
>> +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..501cdb7
>> --- /dev/null
>> +++ b/tests/spec/arb_shader_image_load_store/image.h
>> @@ -0,0 +1,375 @@
>> +/*
>> + * 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.  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 a compatible unsigned integer format of the same size.
>> + */
>> +GLenum
>> +image_compat_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.
>> + */
>> +const char *
>> +image_type_name(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
>> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 212 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/piglit/attachments/20141009/4aa865bd/attachment-0001.sig>


More information about the Piglit mailing list