Edit

kc3-lang/angle/src/tests/deqp_support/glcShaderConstExprTests_override.cpp

Branch :

  • Show log

    Commit

  • Author : James Darpinian
    Date : 2019-12-05 17:46:23
    Hash : d6053daa
    Message : Remove tabs from source files. WebKit's Subversion repo refuses to commit source files that contain tabs. Bug: angleproject:3439 Change-Id: I0a804bcfa0375a98e19945e20297c90d31106827 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1954410 Commit-Queue: James Darpinian <jdarpinian@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>

  • src/tests/deqp_support/glcShaderConstExprTests_override.cpp
  • /*-------------------------------------------------------------------------
     * OpenGL Conformance Test Suite
     * -----------------------------
     *
     * Copyright (c) 2017 The Khronos Group Inc.
     *
     * 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  glcShaderConstExprTests.cpp
     * \brief Declares shader constant expressions tests.
     */ /*-------------------------------------------------------------------*/
    
    #include <map>
    #include "deMath.h"
    #include "deSharedPtr.hpp"
    #include "glcShaderConstExprTests.hpp"
    #include "glsShaderExecUtil.hpp"
    #include "gluContextInfo.hpp"
    #include "gluShaderUtil.hpp"
    #include "tcuFloat.hpp"
    #include "tcuStringTemplate.hpp"
    #include "tcuTestLog.hpp"
    
    using namespace deqp::gls::ShaderExecUtil;
    
    namespace glcts
    {
    
    namespace ShaderConstExpr
    {
    
    struct TestParams
    {
        const char *name;
        const char *expression;
    
        glu::DataType inType;
        int minComponents;
        int maxComponents;
    
        glu::DataType outType;
        union
        {
            float outputFloat;
            int outputInt;
        };
    };
    
    struct ShaderExecutorParams
    {
        deqp::Context *context;
    
        std::string caseName;
        std::string source;
    
        glu::DataType outType;
        union
        {
            float outputFloat;
            int outputInt;
        };
    };
    
    template <typename OutputType>
    class ExecutorTestCase : public deqp::TestCase
    {
      public:
        ExecutorTestCase(deqp::Context &context,
                         const char *name,
                         glu::ShaderType shaderType,
                         const ShaderSpec &shaderSpec,
                         OutputType expectedOutput);
        virtual ~ExecutorTestCase(void);
        virtual tcu::TestNode::IterateResult iterate(void);
    
      protected:
        void validateOutput(de::SharedPtr<ShaderExecutor> executor);
    
        glu::ShaderType m_shaderType;
        ShaderSpec m_shaderSpec;
        OutputType m_expectedOutput;
    };
    
    template <typename OutputType>
    ExecutorTestCase<OutputType>::ExecutorTestCase(deqp::Context &context,
                                                   const char *name,
                                                   glu::ShaderType shaderType,
                                                   const ShaderSpec &shaderSpec,
                                                   OutputType expectedOutput)
        : deqp::TestCase(context, name, ""),
          m_shaderType(shaderType),
          m_shaderSpec(shaderSpec),
          m_expectedOutput(expectedOutput)
    {}
    
    template <typename OutputType>
    ExecutorTestCase<OutputType>::~ExecutorTestCase(void)
    {}
    
    template <>
    void ExecutorTestCase<float>::validateOutput(de::SharedPtr<ShaderExecutor> executor)
    {
        float result        = 0.0f;
        void *const outputs = &result;
        executor->execute(1, DE_NULL, &outputs);
    
        const float epsilon = 0.01f;
        if (de::abs(m_expectedOutput - result) > epsilon)
        {
            m_context.getTestContext().getLog()
                << tcu::TestLog::Message << "Expected: " << m_expectedOutput << " ("
                << tcu::toHex(tcu::Float32(m_expectedOutput).bits())
                << ") but constant expresion returned: " << result << " ("
                << tcu::toHex(tcu::Float32(result).bits()) << "), used " << epsilon
                << " epsilon for comparison" << tcu::TestLog::EndMessage;
            m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
            return;
        }
    
        m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
        return;
    }
    
    template <>
    void ExecutorTestCase<int>::validateOutput(de::SharedPtr<ShaderExecutor> executor)
    {
        int result          = 0;
        void *const outputs = &result;
        executor->execute(1, DE_NULL, &outputs);
    
        if (result == m_expectedOutput)
        {
            m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
            return;
        }
    
        m_context.getTestContext().getLog()
            << tcu::TestLog::Message << "Expected: " << m_expectedOutput
            << " but constant expresion returned: " << result << tcu::TestLog::EndMessage;
        m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    }
    
    template <typename OutputType>
    tcu::TestNode::IterateResult ExecutorTestCase<OutputType>::iterate(void)
    {
        de::SharedPtr<ShaderExecutor> executor(
            createExecutor(m_context.getRenderContext(), m_shaderType, m_shaderSpec));
    
        DE_ASSERT(executor.get());
    
        executor->log(m_context.getTestContext().getLog());
    
        try
        {
            if (!executor->isOk())
                TCU_FAIL("Compilation failed");
    
            executor->useProgram();
    
            validateOutput(executor);
        }
        catch (const tcu::NotSupportedError &e)
        {
            m_testCtx.getLog() << tcu::TestLog::Message << e.what() << tcu::TestLog::EndMessage;
            m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, e.getMessage());
        }
        catch (const tcu::TestError &e)
        {
            m_testCtx.getLog() << tcu::TestLog::Message << e.what() << tcu::TestLog::EndMessage;
            m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, e.getMessage());
        }
    
        return tcu::TestNode::STOP;
    }
    
    template <typename OutputType>
    void createTestCasesForAllShaderTypes(const ShaderExecutorParams &params,
                                          std::vector<tcu::TestNode *> &outputTests)
    {
        DE_ASSERT(params.context);
    
        deqp::Context &context       = *(params.context);
        glu::ContextType contextType = context.getRenderContext().getType();
    
        ShaderSpec shaderSpec;
        shaderSpec.version = glu::getContextTypeGLSLVersion(contextType);
        shaderSpec.source  = params.source;
        shaderSpec.outputs.push_back(
            Symbol("out0", glu::VarType(params.outType, glu::PRECISION_HIGHP)));
    
        // Construct list of shaders for which tests can be created
        std::vector<glu::ShaderType> shaderTypes;
    
        if (glu::contextSupports(contextType, glu::ApiType::core(4, 3)))
        {
            shaderTypes.push_back(glu::SHADERTYPE_VERTEX);
            shaderTypes.push_back(glu::SHADERTYPE_FRAGMENT);
            shaderTypes.push_back(glu::SHADERTYPE_COMPUTE);
            shaderTypes.push_back(glu::SHADERTYPE_GEOMETRY);
            shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_CONTROL);
            shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_EVALUATION);
        }
        else if (glu::contextSupports(contextType, glu::ApiType::es(3, 2)))
        {
            shaderSpec.version = glu::GLSL_VERSION_320_ES;
            shaderTypes.push_back(glu::SHADERTYPE_GEOMETRY);
            shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_CONTROL);
            shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_EVALUATION);
        }
        else if (glu::contextSupports(contextType, glu::ApiType::es(3, 1)))
        {
            shaderSpec.version = glu::GLSL_VERSION_310_ES;
            shaderTypes.push_back(glu::SHADERTYPE_COMPUTE);
            shaderTypes.push_back(glu::SHADERTYPE_GEOMETRY);
            shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_CONTROL);
            shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_EVALUATION);
        }
        else
        {
            shaderTypes.push_back(glu::SHADERTYPE_VERTEX);
            shaderTypes.push_back(glu::SHADERTYPE_FRAGMENT);
        }
    
        shaderSpec.globalDeclarations += "precision highp float;\n";
    
        for (std::size_t typeIndex = 0; typeIndex < shaderTypes.size(); ++typeIndex)
        {
            glu::ShaderType shaderType = shaderTypes[typeIndex];
            std::string caseName(params.caseName + '_' + getShaderTypeName(shaderType));
    
            outputTests.push_back(
                new ExecutorTestCase<OutputType>(context, caseName.c_str(), shaderType, shaderSpec,
                                                 static_cast<OutputType>(params.outputFloat)));
        }
    }
    
    void createTests(deqp::Context &context,
                     const TestParams *cases,
                     int numCases,
                     const char *shaderTemplateSrc,
                     const char *casePrefix,
                     std::vector<tcu::TestNode *> &outputTests)
    {
        const tcu::StringTemplate shaderTemplate(shaderTemplateSrc);
        const char *componentAccess[] = {"", ".y", ".z", ".w"};
    
        ShaderExecutorParams shaderExecutorParams;
        shaderExecutorParams.context = &context;
    
        for (int caseIndex = 0; caseIndex < numCases; caseIndex++)
        {
            const TestParams &testCase   = cases[caseIndex];
            const std::string baseName   = testCase.name;
            const int minComponents      = testCase.minComponents;
            const int maxComponents      = testCase.maxComponents;
            const glu::DataType inType   = testCase.inType;
            const std::string expression = testCase.expression;
    
            // Check for presence of func(vec, scalar) style specialization,
            // use as gatekeeper for applying said specialization
            const bool alwaysScalar = expression.find("${MT}") != std::string::npos;
    
            std::map<std::string, std::string> shaderTemplateParams;
            shaderTemplateParams["CASE_BASE_TYPE"] = glu::getDataTypeName(testCase.outType);
    
            shaderExecutorParams.outType     = testCase.outType;
            shaderExecutorParams.outputFloat = testCase.outputFloat;
    
            for (int component = minComponents - 1; component < maxComponents; component++)
            {
                // Get type name eg. float, vec2, vec3, vec4 (same for other primitive types)
                glu::DataType dataType = static_cast<glu::DataType>(inType + component);
                std::string typeName   = glu::getDataTypeName(dataType);
    
                // ${T} => final type, ${MT} => final type but with scalar version usable even when T is
                // a vector
                std::map<std::string, std::string> expressionTemplateParams;
                expressionTemplateParams["T"]  = typeName;
                expressionTemplateParams["MT"] = typeName;
    
                const tcu::StringTemplate expressionTemplate(expression);
    
                // Add vector access to expression as needed
                shaderTemplateParams["CASE_EXPRESSION"] =
                    expressionTemplate.specialize(expressionTemplateParams) +
                    componentAccess[component];
    
                {
                    // Add type to case name if we are generating multiple versions
                    shaderExecutorParams.caseName = (casePrefix + baseName);
                    if (minComponents != maxComponents)
                        shaderExecutorParams.caseName += ("_" + typeName);
    
                    shaderExecutorParams.source = shaderTemplate.specialize(shaderTemplateParams);
                    if (shaderExecutorParams.outType == glu::TYPE_FLOAT)
                        createTestCasesForAllShaderTypes<float>(shaderExecutorParams, outputTests);
                    else
                        createTestCasesForAllShaderTypes<int>(shaderExecutorParams, outputTests);
                }
    
                // Deal with functions that allways accept one ore more scalar parameters even when
                // others are vectors
                if (alwaysScalar && component > 0)
                {
                    shaderExecutorParams.caseName =
                        casePrefix + baseName + "_" + typeName + "_" + glu::getDataTypeName(inType);
    
                    expressionTemplateParams["MT"] = glu::getDataTypeName(inType);
                    shaderTemplateParams["CASE_EXPRESSION"] =
                        expressionTemplate.specialize(expressionTemplateParams) +
                        componentAccess[component];
    
                    shaderExecutorParams.source = shaderTemplate.specialize(shaderTemplateParams);
                    if (shaderExecutorParams.outType == glu::TYPE_FLOAT)
                        createTestCasesForAllShaderTypes<float>(shaderExecutorParams, outputTests);
                    else
                        createTestCasesForAllShaderTypes<int>(shaderExecutorParams, outputTests);
                }
            }  // component loop
        }
    }
    
    }  // namespace ShaderConstExpr
    
    ShaderConstExprTests::ShaderConstExprTests(deqp::Context &context)
        : deqp::TestCaseGroup(context, "constant_expressions", "Constant expressions")
    {}
    
    ShaderConstExprTests::~ShaderConstExprTests(void) {}
    
    void ShaderConstExprTests::init(void)
    {
        // Needed for autogenerating shader code for increased component counts
        DE_STATIC_ASSERT(glu::TYPE_FLOAT + 1 == glu::TYPE_FLOAT_VEC2);
        DE_STATIC_ASSERT(glu::TYPE_FLOAT + 2 == glu::TYPE_FLOAT_VEC3);
        DE_STATIC_ASSERT(glu::TYPE_FLOAT + 3 == glu::TYPE_FLOAT_VEC4);
    
        DE_STATIC_ASSERT(glu::TYPE_INT + 1 == glu::TYPE_INT_VEC2);
        DE_STATIC_ASSERT(glu::TYPE_INT + 2 == glu::TYPE_INT_VEC3);
        DE_STATIC_ASSERT(glu::TYPE_INT + 3 == glu::TYPE_INT_VEC4);
    
        DE_STATIC_ASSERT(glu::TYPE_UINT + 1 == glu::TYPE_UINT_VEC2);
        DE_STATIC_ASSERT(glu::TYPE_UINT + 2 == glu::TYPE_UINT_VEC3);
        DE_STATIC_ASSERT(glu::TYPE_UINT + 3 == glu::TYPE_UINT_VEC4);
    
        DE_STATIC_ASSERT(glu::TYPE_BOOL + 1 == glu::TYPE_BOOL_VEC2);
        DE_STATIC_ASSERT(glu::TYPE_BOOL + 2 == glu::TYPE_BOOL_VEC3);
        DE_STATIC_ASSERT(glu::TYPE_BOOL + 3 == glu::TYPE_BOOL_VEC4);
    
        // ${T} => final type, ${MT} => final type but with scalar version usable even when T is a
        // vector
        const ShaderConstExpr::TestParams baseCases[] = {
            {"radians",
             "radians(${T} (90.0))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_FLOAT,
             {deFloatRadians(90.0f)}},
            {"degrees",
             "degrees(${T} (2.0))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_FLOAT,
             {deFloatDegrees(2.0f)}},
            {"sin", "sin(${T} (3.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatSin(3.0f)}},
            {"cos", "cos(${T} (3.2))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatCos(3.2f)}},
            {"asin", "asin(${T} (0.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatAsin(0.0f)}},
            {"acos", "acos(${T} (1.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatAcos(1.0f)}},
            {"pow",
             "pow(${T} (1.7), ${T} (3.5))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_FLOAT,
             {deFloatPow(1.7f, 3.5f)}},
            {"exp", "exp(${T} (4.2))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatExp(4.2f)}},
            {"log", "log(${T} (42.12))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatLog(42.12f)}},
            {"exp2", "exp2(${T} (6.7))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatExp2(6.7f)}},
            {"log2",
             "log2(${T} (100.0))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_FLOAT,
             {deFloatLog2(100.0f)}},
            {"sqrt", "sqrt(${T} (10.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatSqrt(10.0f)}},
            {"inversesqrt",
             "inversesqrt(${T} (10.0))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_FLOAT,
             {deFloatRsq(10.0f)}},
            {"abs", "abs(${T} (-42))", glu::TYPE_INT, 1, 4, glu::TYPE_INT, {42}},
            {"sign", "sign(${T} (-18.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {-1.0f}},
            {"floor",
             "floor(${T} (37.3))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_FLOAT,
             {deFloatFloor(37.3f)}},
            {"trunc", "trunc(${T} (-1.8))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {-1.0f}},
            {"round", "round(${T} (42.1))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {42.0f}},
            {"ceil", "ceil(${T} (82.2))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatCeil(82.2f)}},
            {"mod",
             "mod(${T} (87.65), ${MT} (3.7))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_FLOAT,
             {deFloatMod(87.65f, 3.7f)}},
            {"min", "min(${T} (12.3), ${MT} (32.1))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {12.3f}},
            {"max", "max(${T} (12.3), ${MT} (32.1))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {32.1f}},
            {"clamp",
             "clamp(${T} (42.1),    ${MT} (10.0), ${MT} (15.0))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_FLOAT,
             {15.0f}},
            {"length_float", "length(1.0)", glu::TYPE_FLOAT, 1, 1, glu::TYPE_FLOAT, {1.0f}},
            {"length_vec2",
             "length(vec2(1.0))",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_FLOAT,
             {deFloatSqrt(2.0f)}},
            {"length_vec3",
             "length(vec3(1.0))",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_FLOAT,
             {deFloatSqrt(3.0f)}},
            {"length_vec4",
             "length(vec4(1.0))",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_FLOAT,
             {deFloatSqrt(4.0f)}},
            {"dot_float", "dot(1.0, 1.0)", glu::TYPE_FLOAT, 1, 1, glu::TYPE_FLOAT, {1.0f}},
            {"dot_vec2", "dot(vec2(1.0), vec2(1.0))", glu::TYPE_FLOAT, 1, 1, glu::TYPE_FLOAT, {2.0f}},
            {"dot_vec3", "dot(vec3(1.0), vec3(1.0))", glu::TYPE_FLOAT, 1, 1, glu::TYPE_FLOAT, {3.0f}},
            {"dot_vec4", "dot(vec4(1.0), vec4(1.0))", glu::TYPE_FLOAT, 1, 1, glu::TYPE_FLOAT, {4.0f}},
            {"normalize_float", "normalize(1.0)", glu::TYPE_FLOAT, 1, 1, glu::TYPE_FLOAT, {1.0f}},
            {"normalize_vec2",
             "normalize(vec2(1.0)).x",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_FLOAT,
             {deFloatRsq(2.0f)}},
            {"normalize_vec3",
             "normalize(vec3(1.0)).x",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_FLOAT,
             {deFloatRsq(3.0f)}},
            {"normalize_vec4",
             "normalize(vec4(1.0)).x",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_FLOAT,
             {deFloatRsq(4.0f)}},
        };
    
        const ShaderConstExpr::TestParams arrayCases[] = {
            {"radians",
             "radians(${T} (60.0))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_INT,
             {deFloatRadians(60.0f)}},
            {"degrees",
             "degrees(${T} (0.11))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_INT,
             {deFloatDegrees(0.11f)}},
            {"sin",
             "${T} (1.0) + sin(${T} (0.7))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_INT,
             {1.0f + deFloatSin(0.7f)}},
            {"cos",
             "${T} (1.0) + cos(${T} (0.7))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_INT,
             {1.0f + deFloatCos(0.7f)}},
            {"asin", "asin(${T} (0.9))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatAsin(0.9f)}},
            {"acos", "acos(${T} (-0.5))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatAcos(-0.5f)}},
            {"pow",
             "pow(${T} (2.0), ${T} (2.0))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_INT,
             {deFloatPow(2.0f, 2.0f)}},
            {"exp", "exp(${T} (1.2))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatExp(1.2f)}},
            {"log", "log(${T} (8.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatLog(8.0f)}},
            {"exp2", "exp2(${T} (2.1))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatExp2(2.1f)}},
            {"log2", "log2(${T} (9.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatLog2(9.0)}},
            {"sqrt", "sqrt(${T} (4.5))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatSqrt(4.5f)}},
            {"inversesqrt",
             "inversesqrt(${T} (0.26))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_INT,
             {deFloatRsq(0.26f)}},
            {"abs", "abs(${T} (-2))", glu::TYPE_INT, 1, 4, glu::TYPE_INT, {2}},
            {"sign", "sign(${T} (18.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatSign(18.0f)}},
            {"floor", "floor(${T} (3.3))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatFloor(3.3f)}},
            {"trunc", "trunc(${T} (2.8))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {2}},
            {"round", "round(${T} (2.2))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatRound(2.2f)}},
            {"ceil", "ceil(${T} (2.2))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatCeil(2.2f)}},
            {"mod",
             "mod(${T} (7.1), ${MT} (4.0))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_INT,
             {deFloatMod(7.1f, 4.0f)}},
            {"min",
             "min(${T} (2.3), ${MT} (3.1))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_INT,
             {deFloatMin(2.3f, 3.1f)}},
            {"max",
             "max(${T} (2.3), ${MT} (3.1))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_INT,
             {deFloatMax(2.3f, 3.1f)}},
            {"clamp",
             "clamp(${T} (4.1), ${MT} (2.1), ${MT} (3.1))",
             glu::TYPE_FLOAT,
             1,
             4,
             glu::TYPE_INT,
             {3}},
            {"length_float", "length(2.1)", glu::TYPE_FLOAT, 1, 1, glu::TYPE_INT, {2}},
            {"length_vec2",
             "length(vec2(1.0))",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_INT,
             {deFloatSqrt(2.0f)}},
            {"length_vec3",
             "length(vec3(1.0))",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_INT,
             {deFloatSqrt(3.0f)}},
            {"length_vec4",
             "length(vec4(1.0))",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_INT,
             {deFloatSqrt(4.0f)}},
            {"dot_float", "dot(1.0, 1.0)", glu::TYPE_FLOAT, 1, 1, glu::TYPE_INT, {1}},
            {"dot_vec2", "dot(vec2(1.0), vec2(1.01))", glu::TYPE_FLOAT, 1, 1, glu::TYPE_INT, {2}},
            {"dot_vec3", "dot(vec3(1.0), vec3(1.1))", glu::TYPE_FLOAT, 1, 1, glu::TYPE_INT, {3}},
            {"dot_vec4", "dot(vec4(1.0), vec4(1.1))", glu::TYPE_FLOAT, 1, 1, glu::TYPE_INT, {4}},
            {"normalize_float",
             "${T} (1.0) + normalize(2.0)",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_INT,
             {2}},
            {"normalize_vec2",
             "${T} (1.0) + normalize(vec2(1.0)).x",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_INT,
             {1.0f + deFloatRsq(2.0f)}},
            {"normalize_vec3",
             "${T} (1.0) + normalize(vec3(1.0)).x",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_INT,
             {1.0f + deFloatRsq(3.0f)}},
            {"normalize_vec4",
             "${T} (1.0) + normalize(vec4(1.0)).x",
             glu::TYPE_FLOAT,
             1,
             1,
             glu::TYPE_INT,
             {1.0f + deFloatRsq(4.0f)}},
        };
    
        const char *basicShaderTemplate =
            "const ${CASE_BASE_TYPE} cval = ${CASE_EXPRESSION};\n"
            "out0 = cval;\n";
    
        std::vector<tcu::TestNode *> children;
        ShaderConstExpr::createTests(m_context, baseCases, DE_LENGTH_OF_ARRAY(baseCases),
                                     basicShaderTemplate, "basic_", children);
    
        const char *arrayShaderTemplate =
            "float array[int(${CASE_EXPRESSION})];\n"
            "out0 = array.length();\n";
    
        ShaderConstExpr::createTests(m_context, arrayCases, DE_LENGTH_OF_ARRAY(arrayCases),
                                     arrayShaderTemplate, "array_", children);
    
        for (std::size_t i = 0; i < children.size(); i++)
            addChild(children[i]);
    }
    
    }  // namespace glcts