/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 Module
 * -------------------------------------------------
 *
 * Copyright 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Negative Shader Function Tests
 *//*--------------------------------------------------------------------*/

#include "es31fNegativeShaderFunctionTests.hpp"

#include "gluShaderProgram.hpp"

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace NegativeTestShared
{
namespace
{

enum ShaderFunction
{
    SHADER_FUNCTION_BITFIELD_REVERSE = 0,
    SHADER_FUNCTION_BIT_COUNT,
    SHADER_FUNCTION_FIND_MSB,
    SHADER_FUNCTION_FIND_LSB,
    SHADER_FUNCTION_UADD_CARRY,
    SHADER_FUNCTION_USUB_BORROW,
    SHADER_FUNCTION_UMUL_EXTENDED,
    SHADER_FUNCTION_IMUL_EXTENDED,
    SHADER_FUNCTION_FREXP,
    SHADER_FUNCTION_LDEXP,
    SHADER_FUNCTION_PACK_UNORM_4X8,
    SHADER_FUNCTION_PACK_SNORM_4X8,
    SHADER_FUNCTION_UNPACK_SNORM_4X8,
    SHADER_FUNCTION_UNPACK_UNORM_4X8,
    SHADER_FUNCTION_EMIT_VERTEX,
    SHADER_FUNCTION_END_PRIMITIVE,
    SHADER_FUNCTION_ATOMIC_ADD,
    SHADER_FUNCTION_ATOMIC_MIN,
    SHADER_FUNCTION_ATOMIC_MAX,
    SHADER_FUNCTION_ATOMIC_AND,
    SHADER_FUNCTION_ATOMIC_OR,
    SHADER_FUNCTION_ATOMIC_XOR,
    SHADER_FUNCTION_ATOMIC_EXCHANGE,
    SHADER_FUNCTION_ATOMIC_COMP_SWAP,
    SHADER_FUNCTION_INTERPOLATED_AT_CENTROID,
    SHADER_FUNCTION_INTERPOLATED_AT_SAMPLE,
    SHADER_FUNCTION_INTERPOLATED_AT_OFFSET,

    SHADER_FUNCTION_LAST
};

enum FunctionTextureModes
{
    FUNCTION_TEXTURE_MODE_NO_BIAS_NO_COMPARE = 0,
    FUNCTION_TEXTURE_MODE_BIAS_OR_COMPARE,

    FUNCTION_TEXTURE_MODE_LAST
};

enum FunctionTextureGatherOffsetModes
{
    FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP = 0,
    FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,

    FUNCTION_TEXTURE_GATHER_OFFSET_MODE_LAST
};

struct TextureGatherOffsetsTestSpec
{
    FunctionTextureGatherOffsetModes mode;
    glu::DataType samplerDataType;
    glu::DataType pDataType;
    glu::DataType offsetsDataType;
    glu::DataType fourthArgument;
    bool offsetIsConst;
    int offsetArraySize;
};

static const glu::DataType s_floatTypes[] = {glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT_VEC3,
                                             glu::TYPE_FLOAT_VEC4};

static const glu::DataType s_intTypes[] = {glu::TYPE_INT, glu::TYPE_INT_VEC2, glu::TYPE_INT_VEC3, glu::TYPE_INT_VEC4};

static const glu::DataType s_uintTypes[] = {glu::TYPE_UINT, glu::TYPE_UINT_VEC2, glu::TYPE_UINT_VEC3,
                                            glu::TYPE_UINT_VEC4};

static const glu::DataType s_nonScalarIntTypes[] = {glu::TYPE_FLOAT,      glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT_VEC3,
                                                    glu::TYPE_FLOAT_VEC4, glu::TYPE_INT_VEC2,   glu::TYPE_INT_VEC3,
                                                    glu::TYPE_INT_VEC4,   glu::TYPE_UINT,       glu::TYPE_UINT_VEC2,
                                                    glu::TYPE_UINT_VEC3,  glu::TYPE_UINT_VEC4};

static const glu::ShaderType s_shaders[] = {glu::SHADERTYPE_VERTEX,
                                            glu::SHADERTYPE_FRAGMENT,
                                            glu::SHADERTYPE_GEOMETRY,
                                            glu::SHADERTYPE_TESSELLATION_CONTROL,
                                            glu::SHADERTYPE_TESSELLATION_EVALUATION,
                                            glu::SHADERTYPE_COMPUTE};

static const glu::DataType s_samplerTypes[] = {
    glu::TYPE_SAMPLER_2D,
    glu::TYPE_INT_SAMPLER_2D,
    glu::TYPE_UINT_SAMPLER_2D,
    glu::TYPE_SAMPLER_3D,
    glu::TYPE_INT_SAMPLER_3D,
    glu::TYPE_UINT_SAMPLER_3D,
    glu::TYPE_SAMPLER_CUBE,
    glu::TYPE_INT_SAMPLER_CUBE,
    glu::TYPE_UINT_SAMPLER_CUBE,
    glu::TYPE_SAMPLER_2D_ARRAY,
    glu::TYPE_INT_SAMPLER_2D_ARRAY,
    glu::TYPE_UINT_SAMPLER_2D_ARRAY,
    glu::TYPE_SAMPLER_CUBE_SHADOW,
    glu::TYPE_SAMPLER_2D_SHADOW,
    glu::TYPE_SAMPLER_2D_ARRAY_SHADOW,
    glu::TYPE_SAMPLER_CUBE_ARRAY,
    glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
    glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
    glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW,

    glu::TYPE_SAMPLER_2D_MULTISAMPLE,
    glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE,
    glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE,

    glu::TYPE_SAMPLER_BUFFER,
    glu::TYPE_INT_SAMPLER_BUFFER,
    glu::TYPE_UINT_SAMPLER_BUFFER,

    glu::TYPE_SAMPLER_2D_MULTISAMPLE_ARRAY,
    glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,
    glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE_ARRAY,
};

void verifyShader(NegativeTestContext &ctx, glu::ShaderType shaderType, std::string shaderSource)
{
    tcu::TestLog &log  = ctx.getLog();
    const char *source = shaderSource.c_str();
    const int length   = (int)shaderSource.size();
    glu::Shader shader(ctx.getRenderContext(), shaderType);

    shader.setSources(1, &source, &length);
    shader.compile();

    log << shader;
    if (shader.getCompileStatus())
    {
        log << tcu::TestLog::Message << "Expected shader to fail, but compilation passed." << tcu::TestLog::EndMessage;
        ctx.fail("Shader was not expected to compile.\n");
    }
}

std::string declareAndInitializeShaderVariable(glu::DataType dataType, std::string varName)
{
    std::ostringstream variable;
    variable << getDataTypeName(dataType) << " " << varName << " = " << getDataTypeName(dataType);
    switch (dataType)
    {
    case glu::TYPE_FLOAT:
        variable << "(1.0);\n";
        break;
    case glu::TYPE_FLOAT_VEC2:
        variable << "(1.0, 1.0);\n";
        break;
    case glu::TYPE_FLOAT_VEC3:
        variable << "(1.0, 1.0, 1.0);\n";
        break;
    case glu::TYPE_FLOAT_VEC4:
        variable << "(1.0, 1.0, 1.0, 1.0);\n";
        break;
    case glu::TYPE_INT:
        variable << "(1);\n";
        break;
    case glu::TYPE_INT_VEC2:
        variable << "(1, 1);\n";
        break;
    case glu::TYPE_INT_VEC3:
        variable << "(1, 1, 1);\n";
        break;
    case glu::TYPE_INT_VEC4:
        variable << "(1, 1, 1, 1);\n";
        break;
    case glu::TYPE_UINT:
        variable << "(1u);\n";
        break;
    case glu::TYPE_UINT_VEC2:
        variable << "(1u, 1u);\n";
        break;
    case glu::TYPE_UINT_VEC3:
        variable << "(1u, 1u, 1u);\n";
        break;
    case glu::TYPE_UINT_VEC4:
        variable << "(1u, 1u, 1u, 1u);\n";
        break;
    default:
        DE_FATAL("Unsupported data type.");
    }
    return variable.str();
}

std::string declareShaderUniform(glu::DataType dataType, std::string varName)
{
    std::ostringstream variable;
    variable << getPrecisionName(glu::PRECISION_HIGHP) << " uniform " << getDataTypeName(dataType) << " " << varName
             << ";\n";
    return variable.str();
}

std::string declareShaderInput(glu::DataType dataType, std::string varName)
{
    std::ostringstream variable;
    variable << "in " << getPrecisionName(glu::PRECISION_HIGHP) << " " << getDataTypeName(dataType) << " " << varName
             << ";\n";
    return variable.str();
}

std::string declareBuffer(glu::DataType dataType, std::string varName)
{
    std::ostringstream variable;
    variable << "buffer SSBO {\n"
             << "    " << getDataTypeName(dataType) << " " << varName << ";\n"
             << "};\n";
    return variable.str();
}

std::string declareShaderArrayVariable(glu::DataType dataType, std::string varName, const int arraySize)
{
    std::ostringstream source;
    source << getDataTypeName(dataType) << " " << varName << "[" << arraySize << "]"
           << " = " << getDataTypeName(dataType) << "[](";

    for (int ndx = 0; ndx < arraySize; ++ndx)
        source << getDataTypeName(dataType) << "(" << 0 << ", " << 0 << ")" << ((ndx < arraySize - 1) ? ", " : "");

    source << ");";
    return source.str();
}

std::string getShaderExtensionDeclaration(std::string extension)
{
    if (extension.empty())
        return std::string("");
    else
    {
        std::ostringstream source;
        source << "#extension " << extension << " : enable\n";
        return source.str();
    }
}

std::string getDataTypeExtension(glu::DataType dataType)
{
    std::ostringstream source;
    switch (dataType)
    {
    case glu::TYPE_SAMPLER_CUBE_ARRAY:
    case glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW:
    case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
    case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
        source << "GL_EXT_texture_cube_map_array";
        break;

    case glu::TYPE_SAMPLER_BUFFER:
    case glu::TYPE_INT_SAMPLER_BUFFER:
    case glu::TYPE_UINT_SAMPLER_BUFFER:
        source << "GL_EXT_texture_buffer";
        break;

    case glu::TYPE_SAMPLER_2D_MULTISAMPLE_ARRAY:
    case glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
    case glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE_ARRAY:
        source << "GL_OES_texture_storage_multisample_2d_array";
        break;

    default:
        break;
    }

    return source.str();
}

std::string getShaderInitialization(NegativeTestContext &ctx, glu::ShaderType shaderType)
{
    std::ostringstream source;

    if (!contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)))
    {
        switch (shaderType)
        {
        case glu::SHADERTYPE_GEOMETRY:
            source << "#extension GL_EXT_geometry_shader : enable\n";
            break;

        case glu::SHADERTYPE_TESSELLATION_CONTROL:
            source << "#extension GL_EXT_tessellation_shader : enable\n";
            break;

        case glu::SHADERTYPE_TESSELLATION_EVALUATION:
            source << "#extension GL_EXT_tessellation_shader : enable\n";
            break;

        default:
            break;
        }
    }

    switch (shaderType)
    {
    case glu::SHADERTYPE_GEOMETRY:
        source << "layout(max_vertices = 5) out;\n";
        break;

    case glu::SHADERTYPE_TESSELLATION_CONTROL:
        source << "layout(vertices = 3) out;\n";
        break;

    case glu::SHADERTYPE_TESSELLATION_EVALUATION:
        source << "layout(triangles, equal_spacing, cw) in;\n";
        break;

    default:
        break;
    }

    return source.str();
}

std::string genShaderSourceBitfieldExtract(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                           glu::DataType valueDataType, glu::DataType offsetDataType,
                                           glu::DataType bitsDataType)
{
    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType) << "void main(void)\n"
           << "{\n"
           << "    " << declareAndInitializeShaderVariable(valueDataType, "value") << "    "
           << declareAndInitializeShaderVariable(offsetDataType, "offset") << "    "
           << declareAndInitializeShaderVariable(bitsDataType, "bits") << "    bitfieldExtract(value, offset, bits);\n"
           << "}\n";

    return source.str();
}

void bitfield_extract_invalid_value_type(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_intTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));

    ctx.beginSection("bitfieldExtract: Invalid value type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                const std::string shaderSource(genShaderSourceBitfieldExtract(
                    ctx, s_shaders[shaderNdx], s_floatTypes[dataTypeNdx], glu::TYPE_INT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void bitfield_extract_invalid_offset_type(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_intTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));

    ctx.beginSection("bitfieldExtract: Invalid offset type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                for (int nonIntNdx = 0; nonIntNdx < DE_LENGTH_OF_ARRAY(s_nonScalarIntTypes); ++nonIntNdx)
                {
                    {
                        const std::string shaderSource(
                            genShaderSourceBitfieldExtract(ctx, s_shaders[shaderNdx], s_intTypes[dataTypeNdx],
                                                           s_nonScalarIntTypes[nonIntNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceBitfieldExtract(ctx, s_shaders[shaderNdx], s_uintTypes[dataTypeNdx],
                                                           s_nonScalarIntTypes[nonIntNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void bitfield_extract_invalid_bits_type(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_intTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));

    ctx.beginSection("bitfieldExtract: Invalid bits type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                for (int nonIntNdx = 0; nonIntNdx < DE_LENGTH_OF_ARRAY(s_nonScalarIntTypes); ++nonIntNdx)
                {
                    {
                        const std::string shaderSource(
                            genShaderSourceBitfieldExtract(ctx, s_shaders[shaderNdx], s_intTypes[dataTypeNdx],
                                                           glu::TYPE_INT, s_nonScalarIntTypes[nonIntNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceBitfieldExtract(ctx, s_shaders[shaderNdx], s_uintTypes[dataTypeNdx],
                                                           glu::TYPE_INT, s_nonScalarIntTypes[nonIntNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

std::string genShaderSourceBitfieldInsert(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                          glu::DataType baseDataType, glu::DataType insertDataType,
                                          glu::DataType offsetDataType, glu::DataType bitsDataType)
{
    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType) << "void main(void)\n"
           << "{\n"
           << "    " << declareAndInitializeShaderVariable(baseDataType, "base") << "    "
           << declareAndInitializeShaderVariable(insertDataType, "insert") << "    "
           << declareAndInitializeShaderVariable(offsetDataType, "offset") << "    "
           << declareAndInitializeShaderVariable(bitsDataType, "bits")
           << "    bitfieldInsert(base, insert, offset, bits);\n"
           << "}\n";

    return source.str();
}

void bitfield_insert_invalid_base_type(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_intTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_intTypes) == DE_LENGTH_OF_ARRAY(s_floatTypes));

    ctx.beginSection("bitfieldInsert: Invalid base type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(
                        genShaderSourceBitfieldInsert(ctx, s_shaders[shaderNdx], s_floatTypes[dataTypeNdx],
                                                      s_intTypes[dataTypeNdx], glu::TYPE_INT, glu::TYPE_INT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceBitfieldInsert(ctx, s_shaders[shaderNdx], s_floatTypes[dataTypeNdx],
                                                      s_uintTypes[dataTypeNdx], glu::TYPE_INT, glu::TYPE_INT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void bitfield_insert_invalid_insert_type(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_intTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_intTypes) == DE_LENGTH_OF_ARRAY(s_floatTypes));

    ctx.beginSection("bitfieldInsert: Invalid insert type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(
                        genShaderSourceBitfieldInsert(ctx, s_shaders[shaderNdx], s_intTypes[dataTypeNdx],
                                                      s_floatTypes[dataTypeNdx], glu::TYPE_INT, glu::TYPE_INT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceBitfieldInsert(ctx, s_shaders[shaderNdx], s_uintTypes[dataTypeNdx],
                                                      s_floatTypes[dataTypeNdx], glu::TYPE_INT, glu::TYPE_INT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx2)
                {
                    if (s_intTypes[dataTypeNdx] == s_intTypes[dataTypeNdx2])
                        continue;

                    {
                        const std::string shaderSource(
                            genShaderSourceBitfieldInsert(ctx, s_shaders[shaderNdx], s_intTypes[dataTypeNdx],
                                                          s_intTypes[dataTypeNdx2], glu::TYPE_INT, glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceBitfieldInsert(ctx, s_shaders[shaderNdx], s_uintTypes[dataTypeNdx],
                                                          s_uintTypes[dataTypeNdx2], glu::TYPE_INT, glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void bitfield_insert_invalid_offset_type(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_intTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));

    ctx.beginSection("bitfieldInsert: Invalid offset type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_nonScalarIntTypes); ++dataTypeNdx2)
                {
                    {
                        const std::string shaderSource(genShaderSourceBitfieldInsert(
                            ctx, s_shaders[shaderNdx], s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx],
                            s_nonScalarIntTypes[dataTypeNdx2], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceBitfieldInsert(
                            ctx, s_shaders[shaderNdx], s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx],
                            s_nonScalarIntTypes[dataTypeNdx2], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void bitfield_insert_invalid_bits_type(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_intTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));

    ctx.beginSection("bitfieldInsert: Invalid bits type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_nonScalarIntTypes); ++dataTypeNdx2)
                {
                    {
                        const std::string shaderSource(genShaderSourceBitfieldInsert(
                            ctx, s_shaders[shaderNdx], s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx], glu::TYPE_INT,
                            s_nonScalarIntTypes[dataTypeNdx2]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceBitfieldInsert(
                            ctx, s_shaders[shaderNdx], s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx],
                            glu::TYPE_INT, s_nonScalarIntTypes[dataTypeNdx2]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// bitfieldReverse, bitCount, findMSB, findLSB
std::string genShaderSourceReverseCountFind(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                            ShaderFunction function, glu::DataType baseDataType)
{
    DE_ASSERT(function == SHADER_FUNCTION_BITFIELD_REVERSE || function == SHADER_FUNCTION_BIT_COUNT ||
              function == SHADER_FUNCTION_FIND_MSB || function == SHADER_FUNCTION_FIND_LSB);

    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType) << "void main(void)\n"
           << "{\n"
           << "    " << declareAndInitializeShaderVariable(baseDataType, "value");

    switch (function)
    {
    case SHADER_FUNCTION_BITFIELD_REVERSE:
        source << "    bitfieldReverse(value);\n";
        break;
    case SHADER_FUNCTION_BIT_COUNT:
        source << "    bitCount(value);\n";
        break;
    case SHADER_FUNCTION_FIND_MSB:
        source << "    findMSB(value);\n";
        break;
    case SHADER_FUNCTION_FIND_LSB:
        source << "    findLSB(value);\n";
        break;
    default:
        DE_FATAL("Unsupported shader function.");
    }

    source << "}\n";

    return source.str();
}

void bitfield_reverse(NegativeTestContext &ctx)
{
    ctx.beginSection("bitfieldReverse: Invalid value type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                const std::string shaderSource(genShaderSourceReverseCountFind(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_BITFIELD_REVERSE, s_floatTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void bit_count(NegativeTestContext &ctx)
{
    ctx.beginSection("bitCount: Invalid value type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                const std::string shaderSource(genShaderSourceReverseCountFind(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_BIT_COUNT, s_floatTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void find_msb(NegativeTestContext &ctx)
{
    ctx.beginSection("findMSB: Invalid value type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                const std::string shaderSource(genShaderSourceReverseCountFind(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_FIND_MSB, s_floatTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void find_lsb(NegativeTestContext &ctx)
{
    ctx.beginSection("findLSB: Invalid value type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                const std::string shaderSource(genShaderSourceReverseCountFind(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_FIND_LSB, s_floatTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// uaddCarry, usubBorrow
std::string genShaderSourceAddCarrySubBorrow(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                             ShaderFunction function, glu::DataType xDataType, glu::DataType yDataType,
                                             glu::DataType carryBorrowDataType)
{
    DE_ASSERT(function == SHADER_FUNCTION_UADD_CARRY || function == SHADER_FUNCTION_USUB_BORROW);

    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType) << "void main(void)\n"
           << "{\n"
           << "    " << declareAndInitializeShaderVariable(xDataType, "x") << "    "
           << declareAndInitializeShaderVariable(yDataType, "y");

    switch (function)
    {
    case SHADER_FUNCTION_UADD_CARRY:
        source << "    " << declareAndInitializeShaderVariable(carryBorrowDataType, "carry")
               << "    uaddCarry(x, y, carry);\n";
        break;

    case SHADER_FUNCTION_USUB_BORROW:
        source << "    " << declareAndInitializeShaderVariable(carryBorrowDataType, "borrow")
               << "    usubBorrow(x, y, borrow);\n";
        break;

    default:
        DE_FATAL("Unsupported shader function.");
    }

    source << "}\n";

    return source.str();
}

void uadd_carry_invalid_x(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("uaddCarry: Invalid x type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UADD_CARRY, s_floatTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UADD_CARRY, s_intTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx2)
                {
                    if (s_uintTypes[dataTypeNdx2] == s_uintTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UADD_CARRY, s_uintTypes[dataTypeNdx2],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void uadd_carry_invalid_y(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("uaddCarry: Invalid y type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UADD_CARRY, s_uintTypes[dataTypeNdx],
                        s_floatTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UADD_CARRY, s_uintTypes[dataTypeNdx],
                        s_intTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx2)
                {
                    if (s_uintTypes[dataTypeNdx2] == s_uintTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UADD_CARRY, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx2], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void uadd_carry_invalid_carry(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("uaddCarry: Invalid carry type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UADD_CARRY, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UADD_CARRY, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx2)
                {
                    if (s_uintTypes[dataTypeNdx2] == s_uintTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UADD_CARRY, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx2]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void usub_borrow_invalid_x(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("usubBorrow: Invalid x type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_USUB_BORROW, s_floatTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_USUB_BORROW, s_intTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx2)
                {
                    if (s_uintTypes[dataTypeNdx2] == s_uintTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_USUB_BORROW, s_uintTypes[dataTypeNdx2],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void usub_borrow_invalid_y(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("usubBorrow: Invalid y type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_USUB_BORROW, s_uintTypes[dataTypeNdx],
                        s_floatTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_USUB_BORROW, s_uintTypes[dataTypeNdx],
                        s_intTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx2)
                {
                    if (s_uintTypes[dataTypeNdx2] == s_uintTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource = genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_USUB_BORROW, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx2], s_uintTypes[dataTypeNdx]);
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void usub_borrow_invalid_borrow(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("usubBorrow: Invalid borrow type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_USUB_BORROW, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_USUB_BORROW, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx2)
                {
                    if (s_uintTypes[dataTypeNdx2] == s_uintTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceAddCarrySubBorrow(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_USUB_BORROW, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx2]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// umulExtended, imulExtended
std::string genShaderSourceMulExtended(NegativeTestContext &ctx, glu::ShaderType shaderType, ShaderFunction function,
                                       glu::DataType xDataType, glu::DataType yDataType, glu::DataType msbDataType,
                                       glu::DataType lsbDataType)
{
    DE_ASSERT(function == SHADER_FUNCTION_UMUL_EXTENDED || function == SHADER_FUNCTION_IMUL_EXTENDED);

    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType) << "void main(void)\n"
           << "{\n"
           << "    " << declareAndInitializeShaderVariable(xDataType, "x") << "    "
           << declareAndInitializeShaderVariable(yDataType, "y") << "    "
           << declareAndInitializeShaderVariable(msbDataType, "msb") << "    "
           << declareAndInitializeShaderVariable(lsbDataType, "lsb");

    switch (function)
    {
    case SHADER_FUNCTION_UMUL_EXTENDED:
        source << "    umulExtended(x, y, msb, lsb);\n";
        break;
    case SHADER_FUNCTION_IMUL_EXTENDED:
        source << "    imulExtended(x, y, msb, lsb);\n";
        break;
    default:
        DE_FATAL("Unsupported shader function.");
    }

    source << "}\n";

    return source.str();
}

void umul_extended_invalid_x(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("umulExtended: Invalid x type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_uintTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UMUL_EXTENDED, s_floatTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UMUL_EXTENDED, s_intTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_uintTypes); ++dataTypeNdx2)
                {
                    if (s_uintTypes[dataTypeNdx2] == s_uintTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UMUL_EXTENDED, s_uintTypes[dataTypeNdx2],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void umul_extended_invalid_y(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("umulExtended: Invalid y type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_uintTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UMUL_EXTENDED, s_uintTypes[dataTypeNdx],
                        s_floatTypes[dataTypeNdx], s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UMUL_EXTENDED, s_uintTypes[dataTypeNdx],
                        s_intTypes[dataTypeNdx], s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_uintTypes); ++dataTypeNdx2)
                {
                    if (s_uintTypes[dataTypeNdx2] == s_uintTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UMUL_EXTENDED, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx2], s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void umul_extended_invalid_msb(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("umulExtended: Invalid msb type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_uintTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UMUL_EXTENDED, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_floatTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UMUL_EXTENDED, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_intTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_uintTypes); ++dataTypeNdx2)
                {
                    if (s_uintTypes[dataTypeNdx2] == s_uintTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UMUL_EXTENDED, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx2], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void umul_extended_invalid_lsb(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("umulExtended: Invalid lsb type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_uintTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UMUL_EXTENDED, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx], s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UMUL_EXTENDED, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_uintTypes); ++dataTypeNdx2)
                {
                    if (s_uintTypes[dataTypeNdx2] == s_uintTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UMUL_EXTENDED, s_uintTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx], s_uintTypes[dataTypeNdx2]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void imul_extended_invalid_x(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("imulExtended: Invalid x type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_IMUL_EXTENDED, s_floatTypes[dataTypeNdx],
                        s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_IMUL_EXTENDED, s_uintTypes[dataTypeNdx],
                        s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx2)
                {
                    if (s_intTypes[dataTypeNdx2] == s_intTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_IMUL_EXTENDED, s_intTypes[dataTypeNdx2],
                        s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void imul_extended_invalid_y(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("imulExtended: Invalid y type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_IMUL_EXTENDED, s_intTypes[dataTypeNdx],
                        s_floatTypes[dataTypeNdx], s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_IMUL_EXTENDED, s_intTypes[dataTypeNdx],
                        s_uintTypes[dataTypeNdx], s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx2)
                {
                    if (s_intTypes[dataTypeNdx2] == s_intTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_IMUL_EXTENDED, s_intTypes[dataTypeNdx],
                        s_intTypes[dataTypeNdx2], s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void imul_extended_invalid_msb(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("imulExtended: Invalid msb type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_IMUL_EXTENDED, s_intTypes[dataTypeNdx],
                        s_intTypes[dataTypeNdx], s_floatTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_IMUL_EXTENDED, s_intTypes[dataTypeNdx],
                        s_intTypes[dataTypeNdx], s_uintTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx2)
                {
                    if (s_intTypes[dataTypeNdx2] == s_intTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_IMUL_EXTENDED, s_intTypes[dataTypeNdx],
                        s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx2], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void imul_extended_invalid_lsb(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("imulExtended: Invalid lsb type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_IMUL_EXTENDED, s_intTypes[dataTypeNdx],
                        s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx], s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_IMUL_EXTENDED, s_intTypes[dataTypeNdx],
                        s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx2)
                {
                    if (s_intTypes[dataTypeNdx2] == s_intTypes[dataTypeNdx])
                        continue;

                    const std::string shaderSource(genShaderSourceMulExtended(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_IMUL_EXTENDED, s_intTypes[dataTypeNdx],
                        s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx2]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// frexp, ldexp
std::string genShaderSourceFrexpLdexp(NegativeTestContext &ctx, glu::ShaderType shaderType, ShaderFunction function,
                                      glu::DataType xDataType, glu::DataType expDataType)
{
    DE_ASSERT(function == SHADER_FUNCTION_FREXP || function == SHADER_FUNCTION_LDEXP);

    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType) << "void main(void)\n"
           << "{\n"
           << "    " << declareAndInitializeShaderVariable(xDataType, "x") << "    "
           << declareAndInitializeShaderVariable(expDataType, "exp");

    switch (function)
    {
    case SHADER_FUNCTION_FREXP:
        source << "    frexp(x, exp);\n";
        break;

    case SHADER_FUNCTION_LDEXP:
        source << "    ldexp(x, exp);\n";
        break;

    default:
        DE_FATAL("Unsupported shader function.");
    }

    source << "}\n";

    return source.str();
}

void frexp_invalid_x(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("frexp: Invalid x type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(
                        genShaderSourceFrexpLdexp(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_FREXP,
                                                  s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceFrexpLdexp(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_FREXP,
                                                  s_uintTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void frexp_invalid_exp(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("frexp: Invalid exp type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(
                        genShaderSourceFrexpLdexp(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_FREXP,
                                                  s_floatTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceFrexpLdexp(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_FREXP,
                                                  s_floatTypes[dataTypeNdx], s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void ldexp_invalid_x(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("ldexp: Invalid x type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(
                        genShaderSourceFrexpLdexp(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_LDEXP,
                                                  s_intTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceFrexpLdexp(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_LDEXP,
                                                  s_uintTypes[dataTypeNdx], s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void ldexp_invalid_exp(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("ldexp: Invalid exp type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(
                        genShaderSourceFrexpLdexp(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_LDEXP,
                                                  s_floatTypes[dataTypeNdx], s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceFrexpLdexp(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_LDEXP,
                                                  s_floatTypes[dataTypeNdx], s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// packUnorm4x8, packSnorm4x8, unpackSnorm4x8, unpackUnorm4x8
std::string genShaderSourcePackUnpackNorm4x8(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                             ShaderFunction function, glu::DataType dataType)
{
    DE_ASSERT(function == SHADER_FUNCTION_PACK_UNORM_4X8 || function == SHADER_FUNCTION_PACK_SNORM_4X8 ||
              function == SHADER_FUNCTION_UNPACK_SNORM_4X8 || function == SHADER_FUNCTION_UNPACK_UNORM_4X8);

    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType) << "void main(void)\n"
           << "{\n";

    switch (function)
    {
    case SHADER_FUNCTION_PACK_UNORM_4X8:
        source << "    mediump " << declareAndInitializeShaderVariable(dataType, "v") << "    packUnorm4x8(v);\n";
        break;

    case SHADER_FUNCTION_PACK_SNORM_4X8:
        source << "    mediump " << declareAndInitializeShaderVariable(dataType, "v") << "    packSnorm4x8(v);\n";
        break;

    case SHADER_FUNCTION_UNPACK_SNORM_4X8:
        source << "    highp " << declareAndInitializeShaderVariable(dataType, "p") << "    unpackSnorm4x8(p);\n";
        break;

    case SHADER_FUNCTION_UNPACK_UNORM_4X8:
        source << "    highp " << declareAndInitializeShaderVariable(dataType, "p") << "    unpackUnorm4x8(p);\n";
        break;

    default:
        DE_FATAL("Unsupported shader function.");
    }

    source << "}\n";

    return source.str();
}

void pack_unorm_4x8(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("packUnorm4x8: Invalid v type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                if (s_floatTypes[dataTypeNdx] == glu::TYPE_FLOAT_VEC4)
                    continue;

                const std::string shaderSource(genShaderSourcePackUnpackNorm4x8(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_PACK_UNORM_4X8, s_floatTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }

            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourcePackUnpackNorm4x8(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_PACK_UNORM_4X8, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourcePackUnpackNorm4x8(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_PACK_UNORM_4X8, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void pack_snorm_4x8(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("packSnorm4x8: Invalid v type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                if (s_floatTypes[dataTypeNdx] == glu::TYPE_FLOAT_VEC4)
                    continue;

                const std::string shaderSource(genShaderSourcePackUnpackNorm4x8(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_PACK_SNORM_4X8, s_floatTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourcePackUnpackNorm4x8(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_PACK_SNORM_4X8, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourcePackUnpackNorm4x8(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_PACK_SNORM_4X8, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void unpack_snorm_4x8(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("unpackSnorm4x8: Invalid v type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_uintTypes); ++dataTypeNdx)
            {
                if (s_uintTypes[dataTypeNdx] == glu::TYPE_UINT)
                    continue;

                const std::string shaderSource(genShaderSourcePackUnpackNorm4x8(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UNPACK_SNORM_4X8, s_uintTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourcePackUnpackNorm4x8(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UNPACK_SNORM_4X8, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourcePackUnpackNorm4x8(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UNPACK_SNORM_4X8, s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void unpack_unorm_4x8(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));

    ctx.beginSection("unpackUnorm4x8: Invalid v type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_uintTypes); ++dataTypeNdx)
            {
                if (s_uintTypes[dataTypeNdx] == glu::TYPE_UINT)
                    continue;

                const std::string shaderSource(genShaderSourcePackUnpackNorm4x8(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UNPACK_UNORM_4X8, s_uintTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_intTypes); ++dataTypeNdx)
            {
                {
                    const std::string shaderSource(genShaderSourcePackUnpackNorm4x8(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UNPACK_UNORM_4X8, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourcePackUnpackNorm4x8(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_UNPACK_UNORM_4X8, s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// textureSize
std::string genShaderSourceTextureSize_sampler(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                               glu::DataType samplerDataType, glu::DataType lodDataType)
{
    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderExtensionDeclaration(getDataTypeExtension(samplerDataType))
           << getShaderInitialization(ctx, shaderType) << declareShaderUniform(samplerDataType, "sampler")
           << "void main(void)\n"
           << "{\n";

    switch (samplerDataType)
    {
    case glu::TYPE_SAMPLER_2D:
    case glu::TYPE_INT_SAMPLER_2D:
    case glu::TYPE_UINT_SAMPLER_2D:
    case glu::TYPE_SAMPLER_3D:
    case glu::TYPE_INT_SAMPLER_3D:
    case glu::TYPE_UINT_SAMPLER_3D:
    case glu::TYPE_SAMPLER_CUBE:
    case glu::TYPE_INT_SAMPLER_CUBE:
    case glu::TYPE_UINT_SAMPLER_CUBE:
    case glu::TYPE_SAMPLER_2D_ARRAY:
    case glu::TYPE_INT_SAMPLER_2D_ARRAY:
    case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
    case glu::TYPE_SAMPLER_CUBE_SHADOW:
    case glu::TYPE_SAMPLER_2D_SHADOW:
    case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
    case glu::TYPE_SAMPLER_CUBE_ARRAY:
    case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
    case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
    case glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW:
        source << "    textureSize(sampler);\n";
        break;

    case glu::TYPE_SAMPLER_2D_MULTISAMPLE:
    case glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE:
    case glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE:
    case glu::TYPE_SAMPLER_BUFFER:
    case glu::TYPE_INT_SAMPLER_BUFFER:
    case glu::TYPE_UINT_SAMPLER_BUFFER:
    case glu::TYPE_SAMPLER_2D_MULTISAMPLE_ARRAY:
    case glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
    case glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE_ARRAY:
        source << "    " << declareAndInitializeShaderVariable(lodDataType, "lod")
               << "    textureSize(sampler, lod);\n";
        break;

    default:
        DE_FATAL("Unsupported data type.");
    }

    source << "}\n";

    return source.str();
}

static bool checkSupport(NegativeTestContext &ctx)
{
    auto ctxType = ctx.getRenderContext().getType();
    return contextSupports(ctxType, glu::ApiType::es(3, 2)) || contextSupports(ctxType, glu::ApiType::core(4, 5));
}

void texture_size_invalid_sampler(NegativeTestContext &ctx)
{
    ctx.beginSection(
        "textureSize: Invalid sampler type - some overloads take two arguments while others take only one.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_samplerTypes); ++dataTypeNdx)
            {
                if (checkSupport(ctx) || ctx.isExtensionSupported(getDataTypeExtension(s_samplerTypes[dataTypeNdx])))
                {
                    ctx.beginSection("Verify sampler data type: " +
                                     std::string(getDataTypeName(s_samplerTypes[dataTypeNdx])));
                    const std::string shaderSource(genShaderSourceTextureSize_sampler(
                        ctx, s_shaders[shaderNdx], s_samplerTypes[dataTypeNdx], glu::TYPE_INT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    ctx.endSection();
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

std::string genShaderSourceTextureSize_lod(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                           glu::DataType samplerDataType, glu::DataType lodDataType)
{
    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderExtensionDeclaration(getDataTypeExtension(samplerDataType))
           << getShaderInitialization(ctx, shaderType) << declareShaderUniform(samplerDataType, "sampler")
           << "void main(void)\n"
           << "{\n"
           << "    " << declareAndInitializeShaderVariable(lodDataType, "lod") << "    textureSize(sampler, lod);\n"
           << "}\n";

    return source.str();
}

void texture_size_invalid_lod(NegativeTestContext &ctx)
{
    ctx.beginSection("textureSize: Invalid lod type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_samplerTypes); ++dataTypeNdx)
            {
                if (checkSupport(ctx) || ctx.isExtensionSupported(getDataTypeExtension(s_samplerTypes[dataTypeNdx])))
                {
                    ctx.beginSection("Verify sampler/lod data type" +
                                     std::string(getDataTypeName(s_samplerTypes[dataTypeNdx])));
                    for (int dataTypeNdx2 = 0; dataTypeNdx2 < DE_LENGTH_OF_ARRAY(s_nonScalarIntTypes); ++dataTypeNdx2)
                    {
                        if (s_nonScalarIntTypes[dataTypeNdx2] == glu::TYPE_INT)
                            continue;

                        const std::string shaderSource(genShaderSourceTextureSize_lod(
                            ctx, s_shaders[shaderNdx], s_samplerTypes[dataTypeNdx], s_nonScalarIntTypes[dataTypeNdx2]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    ctx.endSection();
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// texture
std::string genShaderSourceTexture(NegativeTestContext &ctx, glu::ShaderType shaderType, FunctionTextureModes mode,
                                   glu::DataType samplerDataType, glu::DataType pDataType,
                                   glu::DataType thirdArgumentDataType)
{
    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderExtensionDeclaration(getDataTypeExtension(samplerDataType))
           << getShaderInitialization(ctx, shaderType) << declareShaderUniform(samplerDataType, "sampler")
           << "void main(void)\n"
           << "{\n"
           << "    highp " << declareAndInitializeShaderVariable(pDataType, "lod");

    switch (mode)
    {
    case FUNCTION_TEXTURE_MODE_NO_BIAS_NO_COMPARE:
        source << "    texture(sampler, lod);\n";
        break;

    case FUNCTION_TEXTURE_MODE_BIAS_OR_COMPARE:
        source << "    highp " << declareAndInitializeShaderVariable(thirdArgumentDataType, "thirdArgument")
               << "    texture(sampler, lod, thirdArgument);\n";
        break;

    default:
        DE_FATAL("Unsupported shader function overload.");
    }

    source << "}\n";

    return source.str();
}

std::string genShaderSourceTexture(NegativeTestContext &ctx, glu::ShaderType shaderType, glu::DataType samplerDataType,
                                   glu::DataType pDataType)
{
    return genShaderSourceTexture(ctx, shaderType, FUNCTION_TEXTURE_MODE_NO_BIAS_NO_COMPARE, samplerDataType, pDataType,
                                  glu::TYPE_LAST);
}

std::string genShaderSourceTexture(NegativeTestContext &ctx, glu::ShaderType shaderType, glu::DataType samplerDataType,
                                   glu::DataType pDataType, glu::DataType thirdArgumentDataType)
{
    return genShaderSourceTexture(ctx, shaderType, FUNCTION_TEXTURE_MODE_BIAS_OR_COMPARE, samplerDataType, pDataType,
                                  thirdArgumentDataType);
}

void texture_invalid_p(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));

    ctx.beginSection("texture: Invalid P type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                // SAMPLER_2D
                if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT_VEC2)
                {
                    {
                        const std::string shaderSource(genShaderSourceTexture(
                            ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D,
                                                   s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexture(
                            ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D,
                                                   s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexture(
                            ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D,
                                                   s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D, s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D, s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_UINT_SAMPLER_2D,
                                                                          s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D, s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_INT_SAMPLER_2D,
                                                                          s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_UINT_SAMPLER_2D,
                                                                          s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                // SAMPLER_3D
                if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT_VEC3)
                {
                    {
                        const std::string shaderSource(genShaderSourceTexture(
                            ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_3D, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_3D,
                                                   s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexture(
                            ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_3D, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_3D,
                                                   s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexture(
                            ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D,
                                                   s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_3D, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_3D, s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_3D, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_3D, s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_UINT_SAMPLER_3D,
                                                                          s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_3D, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_3D, s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_3D, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_INT_SAMPLER_3D,
                                                                          s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_UINT_SAMPLER_3D,
                                                                          s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                // SAMPLER_CUBE
                if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT_VEC3)
                {
                    {
                        const std::string shaderSource(genShaderSourceTexture(
                            ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE,
                                                   s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexture(
                            ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE,
                                                   s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexture(
                            ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE,
                                                   s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
                {{const std::string shaderSource(
                    genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE, s_intTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE,
                                                                      s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE, s_intTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE, s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE, s_intTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE, s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
        }
        {
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE,
                                                                      s_uintTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE,
                                                                      s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE, s_uintTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE, s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE, s_uintTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE, s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
        }

        // SAMPLER_2D_ARRAY
        if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT_VEC3)
        {
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY, s_floatTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY, s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_ARRAY, s_floatTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                      glu::TYPE_INT_SAMPLER_2D_ARRAY,
                                                                      s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_ARRAY, s_floatTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                      glu::TYPE_UINT_SAMPLER_2D_ARRAY,
                                                                      s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
        }
        {
            const std::string shaderSource(
                genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY, s_intTypes[dataTypeNdx]));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY,
                                                                  s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_ARRAY, s_intTypes[dataTypeNdx]));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_ARRAY, s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_ARRAY, s_intTypes[dataTypeNdx]));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_ARRAY, s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY,
                                                                  s_uintTypes[dataTypeNdx]));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY,
                                                                  s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_ARRAY, s_uintTypes[dataTypeNdx]));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_ARRAY, s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_ARRAY, s_uintTypes[dataTypeNdx]));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_ARRAY, s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }

        // SAMPLER_2D_SHADOW
        if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT_VEC3)
        {
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_SHADOW, s_floatTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                      glu::TYPE_SAMPLER_2D_SHADOW,
                                                                      s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_SHADOW, s_intTypes[dataTypeNdx]));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_SHADOW, s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_SHADOW, s_uintTypes[dataTypeNdx]));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_SHADOW, s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }

        // SAMPLER_CUBE_SHADOW
        if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT_VEC4)
        {
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_SHADOW, s_floatTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                      glu::TYPE_SAMPLER_CUBE_SHADOW,
                                                                      s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_SHADOW, s_intTypes[dataTypeNdx]));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_SHADOW, s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_SHADOW, s_uintTypes[dataTypeNdx]));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_SHADOW, s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }

        // SAMPLER_2D_ARRAY_SHADOW
        if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT_VEC4)
        {
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY_SHADOW, s_floatTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                      glu::TYPE_SAMPLER_2D_ARRAY_SHADOW,
                                                                      s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY_SHADOW, s_intTypes[dataTypeNdx]));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                  glu::TYPE_SAMPLER_2D_ARRAY_SHADOW,
                                                                  s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(
                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY_SHADOW, s_uintTypes[dataTypeNdx]));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }
        {
            const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                  glu::TYPE_SAMPLER_2D_ARRAY_SHADOW,
                                                                  s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
        }

        // SAMPLER_CUBE_ARRAY
        if (checkSupport(ctx) || ctx.isExtensionSupported(getDataTypeExtension(glu::TYPE_SAMPLER_CUBE_ARRAY)))
        {
            if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT_VEC4)
            {
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY, s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_SAMPLER_CUBE_ARRAY,
                                                                          s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY, s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                                          s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(
                        ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY, s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                                          s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY, s_intTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY, s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY, s_intTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                      glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                                      s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY, s_intTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                      glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                                      s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY, s_uintTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                      glu::TYPE_SAMPLER_CUBE_ARRAY,
                                                                      s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY, s_uintTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                      glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                                      s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY, s_uintTypes[dataTypeNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                      glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                                      s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
        }

        // SAMPLER_CUBE_ARRAY_SHADOW
        if (checkSupport(ctx) || ctx.isExtensionSupported(getDataTypeExtension(glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW)))
        {
            if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT_VEC4)
            {
                std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW,
                                                                s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW,
                                                                s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW,
                                                                s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
        }
    }
    ctx.endSection();
}
} // namespace
ctx.endSection();
} // namespace NegativeTestShared

void texture_invalid_bias_or_compare(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));

    ctx.beginSection("texture: Invalid bias/compare type.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
            {
                // SAMPLER_2D
                if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT)
                {
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D,
                                                   glu::TYPE_FLOAT_VEC2, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D,
                                                   glu::TYPE_FLOAT_VEC2, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D,
                                                   glu::TYPE_FLOAT_VEC2, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC2,
                                                                          s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D,
                                               glu::TYPE_FLOAT_VEC2, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D,
                                               glu::TYPE_FLOAT_VEC2, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D,
                                               glu::TYPE_FLOAT_VEC2, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D,
                                               glu::TYPE_FLOAT_VEC2, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D,
                                               glu::TYPE_FLOAT_VEC2, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                // SAMPLER_3D
                if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT)
                {
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_3D,
                                                   glu::TYPE_FLOAT_VEC3, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_3D,
                                                   glu::TYPE_FLOAT_VEC3, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D,
                                                   glu::TYPE_FLOAT_VEC3, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_SAMPLER_3D, glu::TYPE_FLOAT_VEC3,
                                                                          s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_SAMPLER_3D, glu::TYPE_FLOAT_VEC3,
                                                                          s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_3D,
                                               glu::TYPE_FLOAT_VEC3, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_3D,
                                               glu::TYPE_FLOAT_VEC3, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D,
                                               glu::TYPE_FLOAT_VEC3, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D,
                                               glu::TYPE_FLOAT_VEC3, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                // SAMPLER_CUBE
                if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT)
                {
                    std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE,
                                                                    glu::TYPE_FLOAT_VEC3, s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    shaderSource = genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE,
                                                          glu::TYPE_FLOAT_VEC3, s_floatTypes[dataTypeNdx]);
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    shaderSource = genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE,
                                                          glu::TYPE_FLOAT_VEC3, s_floatTypes[dataTypeNdx]);
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_SAMPLER_CUBE, glu::TYPE_FLOAT_VEC3,
                                                                          s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_SAMPLER_CUBE, glu::TYPE_FLOAT_VEC3,
                                                                          s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE,
                                               glu::TYPE_FLOAT_VEC3, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE,
                                               glu::TYPE_FLOAT_VEC3, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE,
                                               glu::TYPE_FLOAT_VEC3, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE,
                                               glu::TYPE_FLOAT_VEC3, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                // SAMPLER_2D_ARRAY
                if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT)
                {
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY,
                                                   glu::TYPE_FLOAT_VEC3, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_ARRAY,
                                                   glu::TYPE_FLOAT_VEC3, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_ARRAY,
                                                   glu::TYPE_FLOAT_VEC3, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY,
                                               glu::TYPE_FLOAT_VEC3, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY,
                                               glu::TYPE_FLOAT_VEC3, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_ARRAY,
                                               glu::TYPE_FLOAT_VEC3, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_ARRAY,
                                               glu::TYPE_FLOAT_VEC3, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_ARRAY,
                                               glu::TYPE_FLOAT_VEC3, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_ARRAY,
                                               glu::TYPE_FLOAT_VEC3, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                // SAMPLER_2D_SHADOW
                if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT)
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_SHADOW,
                                               glu::TYPE_FLOAT_VEC3, s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_SHADOW,
                                               glu::TYPE_FLOAT_VEC3, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_SHADOW,
                                               glu::TYPE_FLOAT_VEC3, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                // SAMPLER_CUBE_SHADOW
                if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT)
                {
                    std::string shaderSource(genShaderSourceTexture(ctx, s_shaders[shaderNdx],
                                                                    glu::TYPE_SAMPLER_CUBE_SHADOW, glu::TYPE_FLOAT_VEC4,
                                                                    s_floatTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_SHADOW,
                                               glu::TYPE_FLOAT_VEC4, s_intTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_SHADOW,
                                               glu::TYPE_FLOAT_VEC4, s_uintTypes[dataTypeNdx]));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }

                // SAMPLER_CUBE_ARRAY
                if (checkSupport(ctx) || ctx.isExtensionSupported(getDataTypeExtension(glu::TYPE_SAMPLER_CUBE_ARRAY)))
                {
                    if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT)
                    {
                        {
                            const std::string shaderSource(
                                genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY,
                                                       glu::TYPE_FLOAT_VEC4, s_floatTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(
                                genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                       glu::TYPE_FLOAT_VEC4, s_floatTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(
                                genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                       glu::TYPE_FLOAT_VEC4, s_floatTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY,
                                                   glu::TYPE_FLOAT_VEC4, s_intTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY,
                                                   glu::TYPE_FLOAT_VEC4, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                   glu::TYPE_FLOAT_VEC4, s_intTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                   glu::TYPE_FLOAT_VEC4, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                   glu::TYPE_FLOAT_VEC4, s_intTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                   glu::TYPE_FLOAT_VEC4, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }

                // SAMPLER_CUBE_ARRAY_SHADOW
                if (checkSupport(ctx) ||
                    ctx.isExtensionSupported(getDataTypeExtension(glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW)))
                {
                    if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT)
                    {
                        {
                            const std::string shaderSource(
                                genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW,
                                                       glu::TYPE_FLOAT_VEC4, s_floatTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW,
                                                   glu::TYPE_FLOAT_VEC4, s_intTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexture(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW,
                                                   glu::TYPE_FLOAT_VEC4, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// textureLod
std::string genShaderSourceTextureLod(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                      glu::DataType samplerDataType, glu::DataType pDataType, glu::DataType lodDataType)
{
    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderExtensionDeclaration(getDataTypeExtension(samplerDataType))
           << getShaderInitialization(ctx, shaderType) << declareShaderUniform(samplerDataType, "sampler")
           << "void main(void)\n"
           << "{\n"
           << "    " << declareAndInitializeShaderVariable(pDataType, "P") << "    "
           << declareAndInitializeShaderVariable(lodDataType, "lod") << "    textureLod(sampler, P, lod);\n"
           << "}\n";

    return source.str();
}

void texture_lod_invalid_p(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));

    if (checkSupport(ctx) || ctx.isExtensionSupported(getDataTypeExtension(glu::TYPE_SAMPLER_CUBE_ARRAY)))
    {
        ctx.beginSection("textureLod: Invalid P type.");
        for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
        {
            if (ctx.isShaderSupported(s_shaders[shaderNdx]))
            {
                ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
                for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
                {
                    if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT_VEC4)
                    {
                        {
                            const std::string shaderSource(
                                genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY,
                                                          s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(
                                genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                          s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(
                                genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                          s_floatTypes[dataTypeNdx], glu::TYPE_FLOAT));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY,
                                                      s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                      s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                      s_intTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY,
                                                      s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                      s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                      s_uintTypes[dataTypeNdx], glu::TYPE_FLOAT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
                ctx.endSection();
            }
        }
        ctx.endSection();
    }
}

void texture_lod_invalid_lod(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));

    if (checkSupport(ctx) || ctx.isExtensionSupported(getDataTypeExtension(glu::TYPE_SAMPLER_CUBE_ARRAY)))
    {
        ctx.beginSection("textureLod: Invalid lod type.");
        for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
        {
            if (ctx.isShaderSupported(s_shaders[shaderNdx]))
            {
                ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
                for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
                {
                    if (s_floatTypes[dataTypeNdx] != glu::TYPE_FLOAT)
                    {
                        {
                            const std::string shaderSource(
                                genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY,
                                                          glu::TYPE_FLOAT, s_floatTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(
                                genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                          glu::TYPE_FLOAT, s_floatTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(
                                genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                          glu::TYPE_FLOAT, s_floatTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY,
                                                      glu::TYPE_FLOAT_VEC4, s_intTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                      glu::TYPE_FLOAT_VEC4, s_intTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                      glu::TYPE_FLOAT_VEC4, s_intTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY,
                                                      glu::TYPE_FLOAT_VEC4, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                      glu::TYPE_FLOAT_VEC4, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTextureLod(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                      glu::TYPE_FLOAT_VEC4, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
                ctx.endSection();
            }
        }
        ctx.endSection();
    }
}

// texelFetch
std::string genShaderSourceTexelFetch(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                      glu::DataType samplerDataType, glu::DataType pDataType,
                                      glu::DataType sampleDataType)
{
    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderExtensionDeclaration(getDataTypeExtension(samplerDataType))
           << getShaderInitialization(ctx, shaderType) << declareShaderUniform(samplerDataType, "sampler")
           << "void main(void)\n"
           << "{\n"
           << "    " << declareAndInitializeShaderVariable(pDataType, "P");

    switch (samplerDataType)
    {
    case glu::TYPE_SAMPLER_2D_MULTISAMPLE:
    case glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE:
    case glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE:
    case glu::TYPE_SAMPLER_2D_MULTISAMPLE_ARRAY:
    case glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
    case glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE_ARRAY:
        source << "    " << declareAndInitializeShaderVariable(sampleDataType, "varSample")
               << "    texelFetch(sampler, P, varSample);\n";
        break;

    case glu::TYPE_SAMPLER_BUFFER:
    case glu::TYPE_INT_SAMPLER_BUFFER:
    case glu::TYPE_UINT_SAMPLER_BUFFER:
        source << "    texelFetch(sampler, P);\n";
        break;

    default:
        DE_FATAL("Unsupported data type.");
    }

    source << "}\n";

    return source.str();
}

std::string genShaderSourceTexelFetch(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                      glu::DataType samplerDataType, glu::DataType pDataType)
{
    return genShaderSourceTexelFetch(ctx, shaderType, samplerDataType, pDataType, glu::TYPE_LAST);
}

void texel_fetch_invalid_p(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));

    if (checkSupport(ctx) || ctx.isExtensionSupported(getDataTypeExtension(glu::TYPE_SAMPLER_CUBE_ARRAY)))
    {
        ctx.beginSection("texelFetch: Invalid P type.");
        for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
        {
            if (ctx.isShaderSupported(s_shaders[shaderNdx]))
            {
                ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
                for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
                {
                    // SAMPLER_2D_MULTISAMPLE
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_MULTISAMPLE,
                                                      s_floatTypes[dataTypeNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE,
                                                      s_floatTypes[dataTypeNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE,
                                                      s_floatTypes[dataTypeNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }

                    if (s_intTypes[dataTypeNdx] != glu::TYPE_INT_VEC2)
                    {
                        {
                            const std::string shaderSource(
                                genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_MULTISAMPLE,
                                                          s_intTypes[dataTypeNdx], glu::TYPE_INT));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE,
                                s_intTypes[dataTypeNdx], glu::TYPE_INT));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE,
                                s_intTypes[dataTypeNdx], glu::TYPE_INT));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_MULTISAMPLE,
                                                      s_uintTypes[dataTypeNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE,
                                                      s_uintTypes[dataTypeNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE,
                                                      s_uintTypes[dataTypeNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }

                    // SAMPLER_BUFFER
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_BUFFER, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_BUFFER, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_BUFFER, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }

                    if (s_intTypes[dataTypeNdx] != glu::TYPE_INT)
                    {
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_BUFFER, s_intTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_BUFFER, s_intTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_BUFFER, s_intTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                    }

                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_BUFFER, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_BUFFER, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_BUFFER, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }

                    // SAMPLER_2D_MULTISAMPLE_ARRAY
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_MULTISAMPLE_ARRAY,
                                                      s_floatTypes[dataTypeNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,
                            s_floatTypes[dataTypeNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE_ARRAY,
                            s_floatTypes[dataTypeNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }

                    if (s_intTypes[dataTypeNdx] != glu::TYPE_INT_VEC3)
                    {
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_MULTISAMPLE_ARRAY,
                                s_intTypes[dataTypeNdx], glu::TYPE_INT));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,
                                s_intTypes[dataTypeNdx], glu::TYPE_INT));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE_ARRAY,
                                s_intTypes[dataTypeNdx], glu::TYPE_INT));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_MULTISAMPLE_ARRAY,
                                                      s_uintTypes[dataTypeNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,
                            s_uintTypes[dataTypeNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE_ARRAY,
                            s_uintTypes[dataTypeNdx], glu::TYPE_INT));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
                ctx.endSection();
            }
        }
        ctx.endSection();
    }
}

void texel_fetch_invalid_sample(NegativeTestContext &ctx)
{
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_intTypes));
    DE_ASSERT(DE_LENGTH_OF_ARRAY(s_floatTypes) == DE_LENGTH_OF_ARRAY(s_uintTypes));

    if (checkSupport(ctx) || ctx.isExtensionSupported(getDataTypeExtension(glu::TYPE_SAMPLER_CUBE_ARRAY)))
    {
        ctx.beginSection("texelFetch: Invalid sample type.");
        for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
        {
            if (ctx.isShaderSupported(s_shaders[shaderNdx]))
            {
                ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
                for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(s_floatTypes); ++dataTypeNdx)
                {
                    // SAMPLER_2D_MULTISAMPLE
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_MULTISAMPLE,
                                                      glu::TYPE_INT_VEC2, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE,
                                                      glu::TYPE_INT_VEC2, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE,
                                                      glu::TYPE_INT_VEC2, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }

                    // SAMPLER_2D_MULTISAMPLE_ARRAY
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_MULTISAMPLE_ARRAY,
                                                      glu::TYPE_INT_VEC3, s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, glu::TYPE_INT_VEC3,
                            s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE_ARRAY, glu::TYPE_INT_VEC3,
                            s_floatTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }

                    if (s_intTypes[dataTypeNdx] != glu::TYPE_INT)
                    {
                        // SAMPLER_2D_MULTISAMPLE
                        {
                            const std::string shaderSource(
                                genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_MULTISAMPLE,
                                                          glu::TYPE_INT_VEC2, s_intTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE, glu::TYPE_INT_VEC2,
                                s_intTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE, glu::TYPE_INT_VEC2,
                                s_intTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }

                        // SAMPLER_2D_MULTISAMPLE_ARRAY
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_MULTISAMPLE_ARRAY, glu::TYPE_INT_VEC3,
                                s_intTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,
                                glu::TYPE_INT_VEC3, s_intTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                        {
                            const std::string shaderSource(genShaderSourceTexelFetch(
                                ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE_ARRAY,
                                glu::TYPE_INT_VEC3, s_intTypes[dataTypeNdx]));
                            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                        }
                    }

                    // SAMPLER_2D_MULTISAMPLE
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_MULTISAMPLE,
                                                      glu::TYPE_INT_VEC2, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE,
                                                      glu::TYPE_INT_VEC2, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE,
                                                      glu::TYPE_INT_VEC2, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }

                    // SAMPLER_2D_MULTISAMPLE_ARRAY
                    {
                        const std::string shaderSource(
                            genShaderSourceTexelFetch(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_MULTISAMPLE_ARRAY,
                                                      glu::TYPE_INT_VEC3, s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, glu::TYPE_INT_VEC3,
                            s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                    {
                        const std::string shaderSource(genShaderSourceTexelFetch(
                            ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE_ARRAY, glu::TYPE_INT_VEC3,
                            s_uintTypes[dataTypeNdx]));
                        verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                    }
                }
                ctx.endSection();
            }
        }
        ctx.endSection();
    }
}

// EmitVertex, EndPrimitive
std::string genShaderSourceGeometry(NegativeTestContext &ctx, glu::ShaderType shaderType, ShaderFunction function)
{
    DE_ASSERT(function == SHADER_FUNCTION_EMIT_VERTEX || function == SHADER_FUNCTION_END_PRIMITIVE);

    std::ostringstream source;
    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType) << "void main(void)\n"
           << "{\n";

    switch (function)
    {
    case SHADER_FUNCTION_EMIT_VERTEX:
        source << "    EmitVertex();\n";
        break;

    case SHADER_FUNCTION_END_PRIMITIVE:
        source << "    EndPrimitive();\n";
        break;

    default:
        DE_FATAL("Unsupported shader function.");
    }

    source << "}\n";

    return source.str();
}

void emit_vertex(NegativeTestContext &ctx)
{
    ctx.beginSection("EmitVertex.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            if (s_shaders[shaderNdx] == glu::SHADERTYPE_GEOMETRY)
                continue;

            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            const std::string shaderSource =
                genShaderSourceGeometry(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_EMIT_VERTEX);
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void end_primitive(NegativeTestContext &ctx)
{
    ctx.beginSection("EndPrimitieve.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            if (s_shaders[shaderNdx] == glu::SHADERTYPE_GEOMETRY)
                continue;

            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            const std::string shaderSource =
                genShaderSourceGeometry(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_END_PRIMITIVE);
            verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// textureGrad
std::string genShaderSourceTextureGrad(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                       glu::DataType samplerDataType, glu::DataType pDataType,
                                       glu::DataType dpdxDataType, glu::DataType dpdyDataType)
{
    std::ostringstream source;

    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderExtensionDeclaration(getDataTypeExtension(samplerDataType))
           << getShaderInitialization(ctx, shaderType) << declareShaderUniform(samplerDataType, "sampler")
           << "void main(void)\n"
           << "{\n"
           << "    mediump " << declareAndInitializeShaderVariable(pDataType, "P") << "    mediump "
           << declareAndInitializeShaderVariable(dpdxDataType, "dPdx") << "    mediump "
           << declareAndInitializeShaderVariable(dpdyDataType, "dPdy") << "    textureGrad(sampler, P, dPdx, dPdy);\n"
           << "}\n";

    return source.str();
}

void texture_grad(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError,
                        ctx.isExtensionSupported("GL_EXT_texture_cube_map_array") || checkSupport(ctx),
                        "Test requires support for GL_EXT_texture_cube_map_array or version 3.2.");

    ctx.beginSection("textureGrad.");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceTextureGrad(ctx, s_shaders[shaderNdx],
                                                                          glu::TYPE_SAMPLER_CUBE_ARRAY, glu::TYPE_FLOAT,
                                                                          glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT_VEC3));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceTextureGrad(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY,
                                               glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC3));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceTextureGrad(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY,
                                               glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceTextureGrad(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                               glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT_VEC3));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceTextureGrad(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                               glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC3));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceTextureGrad(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                               glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceTextureGrad(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                               glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT_VEC3));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceTextureGrad(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                               glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC3));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceTextureGrad(ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                               glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// textureGather
std::string genShaderSourceTextureGather(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                         glu::DataType samplerDataType, glu::DataType pDataType,
                                         glu::DataType thirdArgument)
{
    std::ostringstream source;

    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderExtensionDeclaration(getDataTypeExtension(samplerDataType))
           << getShaderInitialization(ctx, shaderType) << declareShaderUniform(samplerDataType, "sampler")
           << "void main(void)\n"
           << "{\n"
           << "    mediump " << declareAndInitializeShaderVariable(pDataType, "P");

    if (thirdArgument != glu::TYPE_LAST)
        source << "    mediump " << declareAndInitializeShaderVariable(thirdArgument, "arg3")
               << "    textureGather(sampler, P, arg3);\n";
    else
        source << "    textureGather(sampler, P);\n";

    source << "}\n";

    return source.str();
}

std::string genShaderSourceTextureGather(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                         glu::DataType samplerDataType, glu::DataType pDataType)
{
    return genShaderSourceTextureGather(ctx, shaderType, samplerDataType, pDataType, glu::TYPE_LAST);
}

void texture_gather_sampler_2d(NegativeTestContext &ctx)
{
    ctx.beginSection("textureGrad - sampler2D");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(
                    genShaderSourceTextureGather(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceTextureGather(ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D, glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D, glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D, glu::TYPE_FLOAT_VEC2));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D, glu::TYPE_FLOAT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void texture_gather_sampler_2d_array(NegativeTestContext &ctx)
{
    ctx.beginSection("textureGrad - sampler2DArray");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D, glu::TYPE_FLOAT_VEC3));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D, glu::TYPE_FLOAT_VEC3, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void texture_gather_sampler_cube(NegativeTestContext &ctx)
{
    ctx.beginSection("textureGrad - samplerCube");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(
                    genShaderSourceTextureGather(ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D, glu::TYPE_FLOAT_VEC3));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_3D, glu::TYPE_FLOAT_VEC3, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void texture_gather_sampler_2d_shadow(NegativeTestContext &ctx)
{
    ctx.beginSection("textureGrad - sampler2DShadow");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_SHADOW, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_SHADOW, glu::TYPE_FLOAT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_SHADOW, glu::TYPE_FLOAT, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_3D, glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void texture_gather_sampler_2d_array_shadow(NegativeTestContext &ctx)
{
    ctx.beginSection("textureGrad - sampler2DArrayShadow");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY_SHADOW, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY_SHADOW, glu::TYPE_FLOAT_VEC3, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_2D_ARRAY_SHADOW, glu::TYPE_FLOAT, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_3D, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void texture_gather_sampler_cube_shadow(NegativeTestContext &ctx)
{
    ctx.beginSection("textureGrad - samplerCubeShadow");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_SHADOW, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_SHADOW, glu::TYPE_FLOAT_VEC3, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_SHADOW, glu::TYPE_FLOAT, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_3D, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void texture_gather_sampler_cube_array(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError,
                        checkSupport(ctx) || ctx.isExtensionSupported("GL_EXT_texture_cube_map_array"),
                        "Test requires extension GL_EXT_texture_cube_map_array or context version 3.2 or higher.");

    ctx.beginSection("textureGrad - samplerCubeArray");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY, glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_INT_SAMPLER_CUBE_ARRAY, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(ctx, s_shaders[shaderNdx],
                                                                            glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
                                                                            glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_UINT_SAMPLER_CUBE_ARRAY, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(ctx, s_shaders[shaderNdx],
                                                                            glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
                                                                            glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_3D, glu::TYPE_FLOAT_VEC4, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void texture_gather_sampler_cube_array_shadow(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError,
                        checkSupport(ctx) || ctx.isExtensionSupported("GL_EXT_texture_cube_map_array"),
                        "Test requires extension GL_EXT_texture_cube_map_array or context version 3.2 or higher.");

    ctx.beginSection("textureGrad - samplerCubeArrayShadow");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW, glu::TYPE_FLOAT, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(ctx, s_shaders[shaderNdx],
                                                                            glu::TYPE_SAMPLER_CUBE_ARRAY_SHADOW,
                                                                            glu::TYPE_FLOAT_VEC4, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGather(
                    ctx, s_shaders[shaderNdx], glu::TYPE_SAMPLER_3D, glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// textureGatherOffset
std::string genShaderSourceTextureGatherOffset(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                               FunctionTextureGatherOffsetModes mode, glu::DataType samplerDataType,
                                               glu::DataType pDataType, glu::DataType offsetDataType,
                                               glu::DataType fourthArgument)
{
    DE_ASSERT(mode < FUNCTION_TEXTURE_GATHER_OFFSET_MODE_LAST);

    std::ostringstream source;

    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType) << declareShaderUniform(samplerDataType, "sampler")
           << "void main(void)\n"
           << "{\n"
           << "    mediump " << declareAndInitializeShaderVariable(pDataType, "P") << "    mediump "
           << declareAndInitializeShaderVariable(offsetDataType, "offset");

    switch (mode)
    {
    case FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP:
    {
        if (fourthArgument != glu::TYPE_LAST)
            source << "    mediump " << declareAndInitializeShaderVariable(fourthArgument, "comp")
                   << "    textureGatherOffset(sampler, P, offset, comp);\n";
        else
            source << "    textureGatherOffset(sampler, P, offset);\n";
        break;
    }

    case FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z:
    {
        source << "    mediump " << declareAndInitializeShaderVariable(fourthArgument, "refZ")
               << "    textureGatherOffset(sampler, P, refZ, offset);\n";
        break;
    }

    default:
        DE_FATAL("Unsupported shader function overload.");
    }

    source << "}\n";

    return source.str();
}

std::string genShaderSourceTextureGatherOffset(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                               FunctionTextureGatherOffsetModes mode, glu::DataType samplerDataType,
                                               glu::DataType pDataType, glu::DataType offsetDataType)
{
    DE_ASSERT(mode == FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP);

    return genShaderSourceTextureGatherOffset(ctx, shaderType, mode, samplerDataType, pDataType, offsetDataType,
                                              glu::TYPE_LAST);
}

void texture_gather_offset_sampler_2d(NegativeTestContext &ctx)
{
    ctx.beginSection("textureGatherOffset - sampler2D");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_SAMPLER_2D,
                    glu::TYPE_FLOAT, glu::TYPE_INT_VEC2));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_SAMPLER_2D,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_SAMPLER_2D,
                    glu::TYPE_FLOAT, glu::TYPE_INT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_SAMPLER_2D,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_SAMPLER_2D,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT_VEC2, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_INT_SAMPLER_2D,
                    glu::TYPE_FLOAT, glu::TYPE_INT_VEC2));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_INT_SAMPLER_2D,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_INT_SAMPLER_2D,
                    glu::TYPE_FLOAT, glu::TYPE_INT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_INT_SAMPLER_2D,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_INT_SAMPLER_2D,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT_VEC2, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_UINT_SAMPLER_2D,
                    glu::TYPE_FLOAT, glu::TYPE_INT_VEC2));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_UINT_SAMPLER_2D,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_UINT_SAMPLER_2D,
                    glu::TYPE_FLOAT, glu::TYPE_INT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_UINT_SAMPLER_2D,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_UINT_SAMPLER_2D,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT_VEC2, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_SAMPLER_3D,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT_VEC2));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_SAMPLER_3D,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void texture_gather_offset_sampler_2d_array(NegativeTestContext &ctx)
{
    ctx.beginSection("textureGatherOffset - sampler2DArray");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_SAMPLER_2D_ARRAY,
                    glu::TYPE_FLOAT, glu::TYPE_INT_VEC2));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_SAMPLER_2D_ARRAY,
                    glu::TYPE_FLOAT_VEC3, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_SAMPLER_2D_ARRAY,
                    glu::TYPE_FLOAT, glu::TYPE_INT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_SAMPLER_2D_ARRAY,
                    glu::TYPE_FLOAT_VEC3, glu::TYPE_INT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_SAMPLER_2D_ARRAY,
                    glu::TYPE_FLOAT_VEC3, glu::TYPE_INT, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_INT_SAMPLER_2D_ARRAY,
                    glu::TYPE_FLOAT, glu::TYPE_INT_VEC2));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_INT_SAMPLER_2D_ARRAY,
                    glu::TYPE_FLOAT_VEC3, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_INT_SAMPLER_2D_ARRAY,
                    glu::TYPE_FLOAT, glu::TYPE_INT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_INT_SAMPLER_2D_ARRAY,
                    glu::TYPE_FLOAT_VEC3, glu::TYPE_INT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_INT_SAMPLER_2D_ARRAY,
                    glu::TYPE_FLOAT_VEC3, glu::TYPE_INT, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
                    glu::TYPE_UINT_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT, glu::TYPE_INT_VEC2));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
                    glu::TYPE_UINT_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT_VEC3, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
                    glu::TYPE_UINT_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT, glu::TYPE_INT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
                    glu::TYPE_UINT_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT_VEC3, glu::TYPE_INT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
                    glu::TYPE_UINT_SAMPLER_2D_ARRAY, glu::TYPE_FLOAT_VEC3, glu::TYPE_INT, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP, glu::TYPE_UINT_SAMPLER_3D,
                    glu::TYPE_FLOAT_VEC3, glu::TYPE_INT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void texture_gather_offset_sampler_2d_shadow(NegativeTestContext &ctx)
{
    ctx.beginSection("textureGatherOffset - sampler2DShadow");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z, glu::TYPE_SAMPLER_2D_SHADOW,
                    glu::TYPE_FLOAT, glu::TYPE_INT_VEC2, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z, glu::TYPE_SAMPLER_2D_SHADOW,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z, glu::TYPE_SAMPLER_2D_SHADOW,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z, glu::TYPE_SAMPLER_3D,
                    glu::TYPE_FLOAT_VEC2, glu::TYPE_INT_VEC2, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void texture_gather_offset_sampler_2d_array_shadow(NegativeTestContext &ctx)
{
    ctx.beginSection("textureGatherOffset - sampler2DShadow");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
                    glu::TYPE_SAMPLER_2D_ARRAY_SHADOW, glu::TYPE_FLOAT, glu::TYPE_INT_VEC2, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
                    glu::TYPE_SAMPLER_2D_ARRAY_SHADOW, glu::TYPE_FLOAT_VEC3, glu::TYPE_INT_VEC2, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
                    glu::TYPE_SAMPLER_2D_ARRAY_SHADOW, glu::TYPE_FLOAT_VEC3, glu::TYPE_INT, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceTextureGatherOffset(
                    ctx, s_shaders[shaderNdx], FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z, glu::TYPE_SAMPLER_3D,
                    glu::TYPE_FLOAT_VEC3, glu::TYPE_INT_VEC2, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// atomicAdd, atomicMin, atomicMax, atomicAnd, atomicOr, atomixXor, atomixExchange, atomicCompSwap
std::string genShaderSourceAtomicOperations(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                            ShaderFunction function, glu::DataType memDataType,
                                            glu::DataType dataDataType, glu::DataType compareDataType)
{
    DE_ASSERT(SHADER_FUNCTION_ATOMIC_ADD <= function && function <= SHADER_FUNCTION_ATOMIC_COMP_SWAP);

    std::ostringstream source;

    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType) << declareBuffer(memDataType, "mem") << "void main()\n"
           << "{\n"
           << "    mediump " << declareAndInitializeShaderVariable(dataDataType, "data");

    switch (function)
    {
    case SHADER_FUNCTION_ATOMIC_ADD:
        source << "    atomicAdd(mem, data);\n";
        break;
    case SHADER_FUNCTION_ATOMIC_MIN:
        source << "    atomicMin(mem, data);\n";
        break;
    case SHADER_FUNCTION_ATOMIC_MAX:
        source << "    atomicMax(mem, data);\n";
        break;
    case SHADER_FUNCTION_ATOMIC_AND:
        source << "    atomicAnd(mem, data);\n";
        break;
    case SHADER_FUNCTION_ATOMIC_OR:
        source << "    atomicOr(mem, data);\n";
        break;
    case SHADER_FUNCTION_ATOMIC_XOR:
        source << "    atomicXor(mem, data);\n";
        break;
    case SHADER_FUNCTION_ATOMIC_EXCHANGE:
        source << "    atomicExchange(mem, data);\n";
        break;
    case SHADER_FUNCTION_ATOMIC_COMP_SWAP:
        source << "    mediump " << declareAndInitializeShaderVariable(compareDataType, "compare")
               << "    atomicCompSwap(mem, compare, data);\n";
        break;

    default:
        DE_FATAL("Unsupported shader function.");
    }

    source << "}\n";

    return source.str();
}

std::string genShaderSourceAtomicOperations(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                            ShaderFunction function, glu::DataType memDataType,
                                            glu::DataType dataDataType)
{
    DE_ASSERT(function != SHADER_FUNCTION_ATOMIC_COMP_SWAP);

    return genShaderSourceAtomicOperations(ctx, shaderType, function, memDataType, dataDataType, glu::TYPE_LAST);
}

void atomic_add(NegativeTestContext &ctx)
{
    ctx.beginSection("atomicAdd");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_ADD, glu::TYPE_UINT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_ADD, glu::TYPE_INT, glu::TYPE_UINT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void atomic_min(NegativeTestContext &ctx)
{
    ctx.beginSection("atomicMin");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_MIN, glu::TYPE_UINT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_MIN, glu::TYPE_INT, glu::TYPE_UINT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void atomic_max(NegativeTestContext &ctx)
{
    ctx.beginSection("atomicMax");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_MAX, glu::TYPE_UINT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_MAX, glu::TYPE_INT, glu::TYPE_UINT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void atomic_and(NegativeTestContext &ctx)
{
    ctx.beginSection("atomicAnd");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_AND, glu::TYPE_UINT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_AND, glu::TYPE_INT, glu::TYPE_UINT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void atomic_or(NegativeTestContext &ctx)
{
    ctx.beginSection("atomicOr");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_OR, glu::TYPE_UINT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_OR, glu::TYPE_INT, glu::TYPE_UINT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void atomic_xor(NegativeTestContext &ctx)
{
    ctx.beginSection("atomicXor");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_XOR, glu::TYPE_UINT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_XOR, glu::TYPE_INT, glu::TYPE_UINT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void atomic_exchange(NegativeTestContext &ctx)
{
    ctx.beginSection("atomicExchange");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_EXCHANGE, glu::TYPE_UINT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(genShaderSourceAtomicOperations(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_EXCHANGE, glu::TYPE_INT, glu::TYPE_UINT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void atomic_comp_swap(NegativeTestContext &ctx)
{
    ctx.beginSection("atomicCompSwap");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(
                    genShaderSourceAtomicOperations(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_COMP_SWAP,
                                                    glu::TYPE_UINT, glu::TYPE_INT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceAtomicOperations(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_COMP_SWAP,
                                                    glu::TYPE_INT, glu::TYPE_UINT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceAtomicOperations(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_ATOMIC_COMP_SWAP,
                                                    glu::TYPE_INT, glu::TYPE_INT, glu::TYPE_UINT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// interpolatedAtCentroid, interpolatedAtSample, interpolateAtOffset,
std::string genShaderSourceInterpolateAt(NegativeTestContext &ctx, glu::ShaderType shaderType, ShaderFunction function,
                                         glu::DataType interpolantDataType, glu::DataType secondArgumentDataType)
{
    DE_ASSERT(function >= SHADER_FUNCTION_INTERPOLATED_AT_CENTROID &&
              function <= SHADER_FUNCTION_INTERPOLATED_AT_OFFSET);

    auto ctxType            = ctx.getRenderContext().getType();
    const bool isES32orGL45 = glu::contextSupports(ctxType, glu::ApiType::es(3, 2)) ||
                              glu::contextSupports(ctxType, glu::ApiType::core(4, 5));

    std::ostringstream source;
    source << (isES32orGL45 ? glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                              glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType)
           << (isES32orGL45 ? "" : getShaderExtensionDeclaration("GL_OES_shader_multisample_interpolation"))
           << declareShaderInput(interpolantDataType, "interpolant") << "void main()\n"
           << "{\n";

    switch (function)
    {
    case SHADER_FUNCTION_INTERPOLATED_AT_CENTROID:
        source << "    interpolateAtCentroid(interpolant);\n";
        break;

    case SHADER_FUNCTION_INTERPOLATED_AT_SAMPLE:
        source << "    mediump " << declareAndInitializeShaderVariable(secondArgumentDataType, "sample")
               << "    interpolateAtSample(interpolant, sample);\n";
        break;

    case SHADER_FUNCTION_INTERPOLATED_AT_OFFSET:
        source << "    mediump " << declareAndInitializeShaderVariable(secondArgumentDataType, "offset")
               << "    interpolateAtOffset(interpolant, offset);\n";
        break;

    default:
        DE_FATAL("Unsupported shader function.");
    }

    source << "}\n";

    return source.str();
}

std::string genShaderSourceInterpolateAt(NegativeTestContext &ctx, glu::ShaderType shaderType, ShaderFunction function,
                                         glu::DataType interpolantDataType)
{
    DE_ASSERT(function == SHADER_FUNCTION_INTERPOLATED_AT_CENTROID);

    return genShaderSourceInterpolateAt(ctx, shaderType, function, interpolantDataType, glu::TYPE_LAST);
}

void interpolate_at_centroid(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError,
                        checkSupport(ctx) || ctx.isExtensionSupported("GL_OES_shader_multisample_interpolation"),
                        "This test requires a context version 3.2 or higher.");

    ctx.beginSection("interpolateAtCentroid");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            if (s_shaders[shaderNdx] == glu::SHADERTYPE_FRAGMENT)
            {
                const std::string shaderSource(genShaderSourceInterpolateAt(
                    ctx, s_shaders[shaderNdx], SHADER_FUNCTION_INTERPOLATED_AT_CENTROID, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            else
            {
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_INTERPOLATED_AT_CENTROID, glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_INTERPOLATED_AT_CENTROID, glu::TYPE_FLOAT_VEC2));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_INTERPOLATED_AT_CENTROID, glu::TYPE_FLOAT_VEC3));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(
                        ctx, s_shaders[shaderNdx], SHADER_FUNCTION_INTERPOLATED_AT_CENTROID, glu::TYPE_FLOAT_VEC4));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void interpolate_at_sample(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError,
                        checkSupport(ctx) || ctx.isExtensionSupported("GL_OES_shader_multisample_interpolation"),
                        "This test requires a context version 3.2 or higher.");

    ctx.beginSection("interpolateAtSample");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            if (s_shaders[shaderNdx] == glu::SHADERTYPE_FRAGMENT)
            {
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_SAMPLE,
                                                                                glu::TYPE_INT, glu::TYPE_INT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_SAMPLE,
                                                                                glu::TYPE_FLOAT, glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_SAMPLE,
                                                                                glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_SAMPLE,
                                                                                glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_SAMPLE,
                                                                                glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            else
            {
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_SAMPLE,
                                                                                glu::TYPE_FLOAT, glu::TYPE_INT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_SAMPLE,
                                                                                glu::TYPE_FLOAT_VEC2, glu::TYPE_INT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_SAMPLE,
                                                                                glu::TYPE_FLOAT_VEC3, glu::TYPE_INT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_SAMPLE,
                                                                                glu::TYPE_FLOAT_VEC4, glu::TYPE_INT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

void interpolate_at_offset(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError,
                        checkSupport(ctx) || ctx.isExtensionSupported("GL_OES_shader_multisample_interpolation"),
                        "This test requires a context version 3.2 or higher.");

    ctx.beginSection("interpolateAtOffset");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            if (s_shaders[shaderNdx] == glu::SHADERTYPE_FRAGMENT)
            {
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_OFFSET,
                                                                                glu::TYPE_INT, glu::TYPE_FLOAT_VEC2));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_OFFSET,
                                                                                glu::TYPE_FLOAT, glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_OFFSET,
                                                                                glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_OFFSET,
                                                                                glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_OFFSET,
                                                                                glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            else
            {
                {
                    const std::string shaderSource(genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx],
                                                                                SHADER_FUNCTION_INTERPOLATED_AT_OFFSET,
                                                                                glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC2));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_INTERPOLATED_AT_OFFSET,
                                                     glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT_VEC2));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_INTERPOLATED_AT_OFFSET,
                                                     glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT_VEC2));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
                {
                    const std::string shaderSource(
                        genShaderSourceInterpolateAt(ctx, s_shaders[shaderNdx], SHADER_FUNCTION_INTERPOLATED_AT_OFFSET,
                                                     glu::TYPE_FLOAT_VEC4, glu::TYPE_FLOAT_VEC2));
                    verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
                }
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// textureGatherOffsets
std::string genShaderSourceTextureGatherOffsets(NegativeTestContext &ctx, glu::ShaderType shaderType,
                                                const TextureGatherOffsetsTestSpec &spec)
{
    std::ostringstream source;

    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType) << declareShaderUniform(spec.samplerDataType, "sampler")
           << "void main(void)\n"
           << "{\n"
           << "    mediump " << declareAndInitializeShaderVariable(spec.pDataType, "P") << "    mediump "
           << (spec.offsetIsConst ? "const " : "")
           << declareShaderArrayVariable(spec.offsetsDataType, "offsets", spec.offsetArraySize) << "\n";

    switch (spec.mode)
    {
    case FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP:
    {
        if (spec.fourthArgument != glu::TYPE_LAST)
            source << "    mediump " << declareAndInitializeShaderVariable(spec.fourthArgument, "comp")
                   << "    textureGatherOffsets(sampler, P, offsets, comp);\n";
        else
            source << "    textureGatherOffsets(sampler, P, offsets);\n";
        break;
    }

    case FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z:
    {
        source << "    mediump " << declareAndInitializeShaderVariable(spec.fourthArgument, "refZ")
               << "    textureGatherOffsets(sampler, P, refZ, offsets);\n";
        break;
    }

    default:
        DE_FATAL("Unsupported shader function overload.");
        break;
    }

    source << "}\n";
    return source.str();
}

void texture_gather_offsets(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError, checkSupport(ctx) || ctx.isExtensionSupported("GL_EXT_gpu_shader5"),
                        "This test requires a context version 3.2 or higher.");

    const struct TextureGatherOffsetsTestSpec testSpecs[] = {
        //mode                                        samplerDataType                        pDataType                offsetsDataType            fourthArgument        offsetIsConst    offsetArraySize
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D,
            glu::TYPE_FLOAT_VEC2,
            glu::TYPE_INT_VEC2,
            glu::TYPE_LAST,
            false,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D,
            glu::TYPE_FLOAT_VEC2,
            glu::TYPE_INT_VEC2,
            glu::TYPE_LAST,
            true,
            3,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D,
            glu::TYPE_FLOAT,
            glu::TYPE_INT_VEC2,
            glu::TYPE_LAST,
            true,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D,
            glu::TYPE_FLOAT_VEC2,
            glu::TYPE_INT,
            glu::TYPE_LAST,
            true,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D,
            glu::TYPE_FLOAT_VEC2,
            glu::TYPE_INT_VEC2,
            glu::TYPE_INT,
            false,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D,
            glu::TYPE_FLOAT_VEC2,
            glu::TYPE_INT_VEC2,
            glu::TYPE_FLOAT,
            true,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D,
            glu::TYPE_FLOAT_VEC2,
            glu::TYPE_INT_VEC2,
            glu::TYPE_INT,
            true,
            3,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D,
            glu::TYPE_FLOAT,
            glu::TYPE_INT_VEC2,
            glu::TYPE_INT,
            true,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D,
            glu::TYPE_FLOAT_VEC2,
            glu::TYPE_INT,
            glu::TYPE_INT,
            true,
            4,
        },

        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D_ARRAY,
            glu::TYPE_FLOAT_VEC3,
            glu::TYPE_INT_VEC2,
            glu::TYPE_LAST,
            false,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D_ARRAY,
            glu::TYPE_FLOAT_VEC3,
            glu::TYPE_INT_VEC2,
            glu::TYPE_LAST,
            true,
            3,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D_ARRAY,
            glu::TYPE_FLOAT,
            glu::TYPE_INT_VEC2,
            glu::TYPE_LAST,
            true,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D_ARRAY,
            glu::TYPE_FLOAT_VEC3,
            glu::TYPE_INT,
            glu::TYPE_LAST,
            true,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D_ARRAY,
            glu::TYPE_FLOAT_VEC3,
            glu::TYPE_INT_VEC2,
            glu::TYPE_INT,
            false,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D_ARRAY,
            glu::TYPE_FLOAT_VEC3,
            glu::TYPE_INT_VEC2,
            glu::TYPE_FLOAT,
            true,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D_ARRAY,
            glu::TYPE_FLOAT_VEC3,
            glu::TYPE_INT_VEC2,
            glu::TYPE_INT,
            true,
            3,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D_ARRAY,
            glu::TYPE_FLOAT,
            glu::TYPE_INT_VEC2,
            glu::TYPE_INT,
            true,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_COMP,
            glu::TYPE_SAMPLER_2D_ARRAY,
            glu::TYPE_FLOAT_VEC3,
            glu::TYPE_INT,
            glu::TYPE_INT,
            true,
            4,
        },

        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
            glu::TYPE_SAMPLER_2D_SHADOW,
            glu::TYPE_FLOAT_VEC2,
            glu::TYPE_INT_VEC2,
            glu::TYPE_FLOAT,
            false,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
            glu::TYPE_SAMPLER_2D_SHADOW,
            glu::TYPE_FLOAT_VEC2,
            glu::TYPE_INT_VEC2,
            glu::TYPE_FLOAT,
            true,
            3,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
            glu::TYPE_SAMPLER_2D_SHADOW,
            glu::TYPE_FLOAT,
            glu::TYPE_INT_VEC2,
            glu::TYPE_FLOAT,
            true,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
            glu::TYPE_SAMPLER_2D_SHADOW,
            glu::TYPE_FLOAT_VEC2,
            glu::TYPE_INT,
            glu::TYPE_FLOAT,
            true,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
            glu::TYPE_SAMPLER_2D_SHADOW,
            glu::TYPE_FLOAT_VEC2,
            glu::TYPE_INT_VEC2,
            glu::TYPE_INT,
            true,
            4,
        },

        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
            glu::TYPE_SAMPLER_2D_ARRAY_SHADOW,
            glu::TYPE_FLOAT_VEC3,
            glu::TYPE_INT_VEC2,
            glu::TYPE_FLOAT,
            false,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
            glu::TYPE_SAMPLER_2D_ARRAY_SHADOW,
            glu::TYPE_FLOAT_VEC3,
            glu::TYPE_INT_VEC2,
            glu::TYPE_FLOAT,
            true,
            3,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
            glu::TYPE_SAMPLER_2D_ARRAY_SHADOW,
            glu::TYPE_FLOAT,
            glu::TYPE_INT_VEC2,
            glu::TYPE_FLOAT,
            true,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
            glu::TYPE_SAMPLER_2D_ARRAY_SHADOW,
            glu::TYPE_FLOAT_VEC3,
            glu::TYPE_INT,
            glu::TYPE_FLOAT,
            true,
            4,
        },
        {
            FUNCTION_TEXTURE_GATHER_OFFSET_MODE_REF_Z,
            glu::TYPE_SAMPLER_2D_ARRAY_SHADOW,
            glu::TYPE_FLOAT_VEC3,
            glu::TYPE_INT_VEC2,
            glu::TYPE_INT,
            true,
            4,
        },
    };

    ctx.beginSection("textureGatherOffsets");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            for (int specNdx = 0; specNdx < DE_LENGTH_OF_ARRAY(testSpecs); ++specNdx)
            {
                const std::string shaderSource(
                    genShaderSourceTextureGatherOffsets(ctx, s_shaders[shaderNdx], testSpecs[specNdx]));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

// fma
std::string genShaderSourceFma(NegativeTestContext &ctx, glu::ShaderType shaderType, glu::DataType aDataType,
                               glu::DataType bDataType, glu::DataType cDataType)
{
    std::ostringstream source;

    source << (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ?
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                   glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES))
           << "\n"
           << getShaderInitialization(ctx, shaderType) << "void main(void)\n"
           << "{\n"
           << "    mediump " << declareAndInitializeShaderVariable(aDataType, "a") << "    mediump "
           << declareAndInitializeShaderVariable(bDataType, "b") << "    mediump "
           << declareAndInitializeShaderVariable(cDataType, "c") << "    fma(a, b, c);"
           << "}\n";
    return source.str();
}

void fma(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError, checkSupport(ctx) || ctx.isExtensionSupported("GL_EXT_gpu_shader5"),
                        "This test requires a context version 3.2 or higher.");

    ctx.beginSection("fma");
    for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(s_shaders); ++shaderNdx)
    {
        if (ctx.isShaderSupported(s_shaders[shaderNdx]))
        {
            ctx.beginSection("Verify shader: " + std::string(getShaderTypeName(s_shaders[shaderNdx])));
            {
                const std::string shaderSource(
                    genShaderSourceFma(ctx, s_shaders[shaderNdx], glu::TYPE_FLOAT, glu::TYPE_FLOAT, glu::TYPE_INT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceFma(ctx, s_shaders[shaderNdx], glu::TYPE_FLOAT, glu::TYPE_INT, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            {
                const std::string shaderSource(
                    genShaderSourceFma(ctx, s_shaders[shaderNdx], glu::TYPE_INT, glu::TYPE_FLOAT, glu::TYPE_FLOAT));
                verifyShader(ctx, s_shaders[shaderNdx], shaderSource);
            }
            ctx.endSection();
        }
    }
    ctx.endSection();
}

} // namespace Functional

std::vector<FunctionContainer> getNegativeShaderFunctionTestFunctions()
{
    const FunctionContainer funcs[] = {
        {bitfield_extract_invalid_value_type, "bitfield_extract_invalid_value_type",
         "Invalid usage of bitfieldExtract."},
        {bitfield_extract_invalid_offset_type, "bitfield_extract_invalid_offset_type",
         "Invalid usage of bitfieldExtract."},
        {bitfield_extract_invalid_bits_type, "bitfield_extract_invalid_bits_type", "Invalid usage of bitfieldExtract."},
        {bitfield_insert_invalid_base_type, "bitfield_insert_invalid_base_type", "Invalid usage of bitfieldInsert."},
        {bitfield_insert_invalid_insert_type, "bitfield_insert_invalid_insert_type",
         "Invalid usage of bitfieldInsert."},
        {bitfield_insert_invalid_offset_type, "bitfield_insert_invalid_offset_type",
         "Invalid usage of bitfieldInsert."},
        {bitfield_insert_invalid_bits_type, "bitfield_insert_invalid_bits_type", "Invalid usage of bitfieldInsert."},
        {bitfield_reverse, "bitfield_reverse", "Invalid usage of bitfieldReverse."},
        {bit_count, "bit_count", "Invalid usage of bitCount."},
        {find_msb, "find_msb", "Invalid usage of findMSB."},
        {find_lsb, "find_lsb", "Invalid usage of findLSB."},
        {uadd_carry_invalid_x, "uadd_carry_invalid_x", "Invalid usage of uaddCarry."},
        {uadd_carry_invalid_y, "uadd_carry_invalid_y", "Invalid usage of uaddCarry."},
        {uadd_carry_invalid_carry, "uadd_carry_invalid_carry", "Invalid usage of uaddCarry."},
        {usub_borrow_invalid_x, "usub_borrow_invalid_x", "Invalid usage of usubBorrow."},
        {usub_borrow_invalid_y, "usub_borrow_invalid_y", "Invalid usage of usubBorrow."},
        {usub_borrow_invalid_borrow, "usub_borrow_invalid_borrow", "Invalid usage of usubBorrow."},
        {umul_extended_invalid_x, "umul_extended_invalid_x", "Invalid usage of umulExtended."},
        {umul_extended_invalid_y, "umul_extended_invalid_y", "Invalid usage of umulExtended."},
        {umul_extended_invalid_msb, "umul_extended_invalid_msb", "Invalid usage of umulExtended."},
        {umul_extended_invalid_lsb, "umul_extended_invalid_lsb", "Invalid usage of umulExtended."},
        {imul_extended_invalid_x, "imul_extended_invalid_x", "Invalid usage of imulExtended."},
        {imul_extended_invalid_y, "imul_extended_invalid_y", "Invalid usage of imulExtended."},
        {imul_extended_invalid_msb, "imul_extended_invalid_msb", "Invalid usage of imulExtended."},
        {imul_extended_invalid_lsb, "imul_extended_invalid_lsb", "Invalid usage of imulExtended."},
        {frexp_invalid_x, "frexp_invalid_x", "Invalid usage of frexp."},
        {frexp_invalid_exp, "frexp_invalid_exp", "Invalid usage of frexp."},
        {ldexp_invalid_x, "ldexp_invalid_x", "Invalid usage of ldexp."},
        {ldexp_invalid_exp, "ldexp_invalid_exp", "Invalid usage of ldexp."},
        {pack_unorm_4x8, "pack_unorm_4x8", "Invalid usage of packUnorm4x8."},
        {pack_snorm_4x8, "pack_snorm_4x8", "Invalid usage of packSnorm4x8."},
        {unpack_snorm_4x8, "unpack_snorm_4x8", "Invalid usage of unpackSnorm4x8."},
        {unpack_unorm_4x8, "unpack_unorm_4x8", "Invalid usage of unpackUnorm4x8."},
        {texture_size_invalid_sampler, "texture_size_invalid_sampler", "Invalid usage of textureSize."},
        {texture_size_invalid_lod, "texture_size_invalid_lod", "Invalid usage of textureSize."},
        {texture_invalid_p, "texture_invalid_p", "Invalid usage of texture."},
        {texture_invalid_bias_or_compare, "texture_invalid_bias_or_compare", "Invalid usage of texture."},
        {texture_lod_invalid_p, "texture_lod_invalid_p", "Invalid usage of textureLod."},
        {texture_lod_invalid_lod, "texture_lod_invalid_lod", "Invalid usage of textureLod."},
        {texel_fetch_invalid_p, "texel_fetch_invalid_p", "Invalid usage of texelFetch."},
        {texel_fetch_invalid_sample, "texel_fetch_invalid_sample", "Invalid usage of texelFetch."},
        {emit_vertex, "emit_vertex", "Invalid usage of EmitVertex."},
        {end_primitive, "end_primitive", "Invalid usage of EndPrimitive."},
        {texture_grad, "texture_grad", "Invalid usage of textureGrad."},
        {texture_gather_sampler_2d, "texture_gather_sampler_2d", "Invalid usage of textureGather."},
        {texture_gather_sampler_2d_array, "texture_gather_sampler_2d_array", "Invalid usage of textureGather."},
        {texture_gather_sampler_cube, "texture_gather_sampler_cube", "Invalid usage of textureGather."},
        {texture_gather_sampler_2d_shadow, "texture_gather_sampler_2d_shadow", "Invalid usage of textureGather."},
        {texture_gather_sampler_2d_array_shadow, "texture_gather_sampler_2d_array_shadow",
         "Invalid usage of textureGather."},
        {texture_gather_sampler_cube_shadow, "texture_gather_sampler_cube_shadow", "Invalid usage of textureGather."},
        {texture_gather_sampler_cube_array, "texture_gather_sampler_cube_array", "Invalid usage of textureGather."},
        {texture_gather_sampler_cube_array_shadow, "texture_gather_sampler_cube_array_shadow",
         "Invalid usage of textureGather."},
        {texture_gather_offset_sampler_2d, "texture_gather_offset_sampler_2d", "Invalid usage of textureGatherOffset."},
        {texture_gather_offset_sampler_2d_array, "texture_gather_offset_sampler_2d_array",
         "Invalid usage of textureGatherOffset."},
        {texture_gather_offset_sampler_2d_shadow, "texture_gather_offset_sampler_2d_shadow",
         "Invalid usage of textureGatherOffset."},
        {texture_gather_offset_sampler_2d_array_shadow, "texture_gather_offset_sampler_2d_array_shadow",
         "Invalid usage of textureGatherOffset."},
        {texture_gather_offsets, "texture_gather_offsets", "Invalid usage of textureGatherOffsets."},
        {atomic_add, "atomic_add", "Invalid usage of atomicAdd."},
        {atomic_min, "atomic_min", "Invalid usage of atomicMin."},
        {atomic_max, "atomic_max", "Invalid usage of atomicMax."},
        {atomic_and, "atomic_and", "Invalid usage of atomicAnd."},
        {atomic_or, "atomic_or", "Invalid usage of atomicOr."},
        {atomic_xor, "atomic_xor", "Invalid usage of atomicXor."},
        {atomic_exchange, "atomic_exchange", "Invalid usage of atomicExchange."},
        {atomic_comp_swap, "atomic_comp_swap", "Invalid usage of atomicCompSwap."},
        {interpolate_at_centroid, "interpolate_at_centroid", "Invalid usage of interpolateAtCentroid."},
        {interpolate_at_sample, "interpolate_at_sample", "Invalid usage of interpolateAtSample."},
        {interpolate_at_offset, "interpolate_at_offset", "Invalid usage of interpolateAtOffset."},
        {fma, "fma", "Invalid usage of fma."},
    };

    return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
}

} // namespace gles31
} // namespace deqp
} // gles31
} // deqp
