Always apply flat qualifier to double inputs, same as int/uint
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcShaderConstExprTests.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19   * \file  glcShaderConstExprTests.cpp
20  * \brief Declares shader constant expressions tests.
21  */ /*-------------------------------------------------------------------*/
22
23 #include "glcShaderConstExprTests.hpp"
24 #include "deMath.h"
25 #include "deSharedPtr.hpp"
26 #include "glsShaderExecUtil.hpp"
27 #include "gluContextInfo.hpp"
28 #include "gluShaderUtil.hpp"
29 #include "tcuFloat.hpp"
30 #include "tcuStringTemplate.hpp"
31 #include "tcuTestLog.hpp"
32 #include <map>
33
34 using namespace deqp::gls::ShaderExecUtil;
35
36 namespace glcts
37 {
38
39 namespace ShaderConstExpr
40 {
41
42 struct TestParams
43 {
44         const char* name;
45         const char* expression;
46
47         glu::DataType inType;
48         int                       minComponents;
49         int                       maxComponents;
50
51         glu::DataType outType;
52         union {
53                 float outputFloat;
54                 int   outputInt;
55         };
56 };
57
58 struct ShaderExecutorParams
59 {
60         deqp::Context* context;
61
62         std::string caseName;
63         std::string source;
64
65         glu::DataType outType;
66         union {
67                 float outputFloat;
68                 int   outputInt;
69         };
70 };
71
72 template <typename OutputType>
73 class ExecutorTestCase : public deqp::TestCase
74 {
75 public:
76         ExecutorTestCase(deqp::Context& context, const char* name, glu::ShaderType shaderType, const ShaderSpec& shaderSpec,
77                                          OutputType expectedOutput);
78         virtual ~ExecutorTestCase(void);
79         virtual tcu::TestNode::IterateResult iterate(void);
80
81 protected:
82         void validateOutput(de::SharedPtr<ShaderExecutor> executor);
83
84         glu::ShaderType m_shaderType;
85         ShaderSpec              m_shaderSpec;
86         OutputType              m_expectedOutput;
87 };
88
89 template <typename OutputType>
90 ExecutorTestCase<OutputType>::ExecutorTestCase(deqp::Context& context, const char* name, glu::ShaderType shaderType,
91                                                                                            const ShaderSpec& shaderSpec, OutputType expectedOutput)
92         : deqp::TestCase(context, name, "")
93         , m_shaderType(shaderType)
94         , m_shaderSpec(shaderSpec)
95         , m_expectedOutput(expectedOutput)
96 {
97 }
98
99 template <typename OutputType>
100 ExecutorTestCase<OutputType>::~ExecutorTestCase(void)
101 {
102 }
103
104 template <>
105 void ExecutorTestCase<float>::validateOutput(de::SharedPtr<ShaderExecutor> executor)
106 {
107         float           result  = 0.0f;
108         void* const outputs = &result;
109         executor->execute(1, DE_NULL, &outputs);
110
111         const float epsilon = 0.01f;
112         if (de::abs(m_expectedOutput - result) > epsilon)
113         {
114                 m_context.getTestContext().getLog()
115                         << tcu::TestLog::Message << "Expected: " << m_expectedOutput << " ("
116                         << tcu::toHex(tcu::Float32(m_expectedOutput).bits()) << ") but constant expresion returned: " << result
117                         << " (" << tcu::toHex(tcu::Float32(result).bits()) << "), used " << epsilon << " epsilon for comparison"
118                         << tcu::TestLog::EndMessage;
119                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
120                 return;
121         }
122
123         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
124         return;
125 }
126
127 template <>
128 void ExecutorTestCase<int>::validateOutput(de::SharedPtr<ShaderExecutor> executor)
129 {
130         int                     result  = 0;
131         void* const outputs = &result;
132         executor->execute(1, DE_NULL, &outputs);
133
134         if (result == m_expectedOutput)
135         {
136                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
137                 return;
138         }
139
140         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Expected: " << m_expectedOutput
141                                                                                 << " but constant expresion returned: " << result << tcu::TestLog::EndMessage;
142         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
143 }
144
145 template <typename OutputType>
146 tcu::TestNode::IterateResult ExecutorTestCase<OutputType>::iterate(void)
147 {
148         de::SharedPtr<ShaderExecutor> executor(createExecutor(m_context.getRenderContext(), m_shaderType, m_shaderSpec));
149
150         DE_ASSERT(executor.get());
151
152         executor->log(m_context.getTestContext().getLog());
153
154         try
155         {
156                 if (!executor->isOk())
157                         TCU_FAIL("Compilation failed");
158
159                 executor->useProgram();
160
161                 validateOutput(executor);
162         }
163         catch (const tcu::NotSupportedError& e)
164         {
165                 m_testCtx.getLog() << tcu::TestLog::Message << e.what() << tcu::TestLog::EndMessage;
166                 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, e.getMessage());
167         }
168         catch (const tcu::TestError& e)
169         {
170                 m_testCtx.getLog() << tcu::TestLog::Message << e.what() << tcu::TestLog::EndMessage;
171                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, e.getMessage());
172         }
173
174         return tcu::TestNode::STOP;
175 }
176
177 template <typename OutputType>
178 void createTestCasesForAllShaderTypes(const ShaderExecutorParams& params, std::vector<tcu::TestNode*>& outputTests)
179 {
180         DE_ASSERT(params.context);
181
182         deqp::Context&   context         = *(params.context);
183         glu::ContextType contextType = context.getRenderContext().getType();
184
185         ShaderSpec shaderSpec;
186         shaderSpec.version = glu::getContextTypeGLSLVersion(contextType);
187         shaderSpec.source  = params.source;
188         shaderSpec.outputs.push_back(Symbol("out0", glu::VarType(params.outType, glu::PRECISION_HIGHP)));
189
190         // Construct list of shaders for which tests can be created
191         std::vector<glu::ShaderType> shaderTypes;
192
193         if (glu::contextSupports(contextType, glu::ApiType::core(4, 3)))
194         {
195                 shaderTypes.push_back(glu::SHADERTYPE_VERTEX);
196                 shaderTypes.push_back(glu::SHADERTYPE_FRAGMENT);
197                 shaderTypes.push_back(glu::SHADERTYPE_COMPUTE);
198                 shaderTypes.push_back(glu::SHADERTYPE_GEOMETRY);
199                 shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_CONTROL);
200                 shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_EVALUATION);
201         }
202         else if (glu::contextSupports(contextType, glu::ApiType::es(3, 2)))
203         {
204                 shaderSpec.version = glu::GLSL_VERSION_320_ES;
205                 shaderTypes.push_back(glu::SHADERTYPE_GEOMETRY);
206                 shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_CONTROL);
207                 shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_EVALUATION);
208         }
209         else if (glu::contextSupports(contextType, glu::ApiType::es(3, 1)))
210         {
211                 shaderSpec.version = glu::GLSL_VERSION_310_ES;
212                 shaderTypes.push_back(glu::SHADERTYPE_COMPUTE);
213
214                 if (context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader") ||
215                         context.getContextInfo().isExtensionSupported("GL_OES_geometry_shader"))
216                 {
217                         shaderTypes.push_back(glu::SHADERTYPE_GEOMETRY);
218                 }
219
220                 if (context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader") ||
221                         context.getContextInfo().isExtensionSupported("GL_OES_tessellation_shader"))
222                 {
223                         shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_CONTROL);
224                         shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_EVALUATION);
225                 }
226         }
227         else
228         {
229                 shaderTypes.push_back(glu::SHADERTYPE_VERTEX);
230                 shaderTypes.push_back(glu::SHADERTYPE_FRAGMENT);
231         }
232
233         shaderSpec.globalDeclarations += "precision highp float;\n";
234
235         for (std::size_t typeIndex = 0; typeIndex < shaderTypes.size(); ++typeIndex)
236         {
237                 glu::ShaderType shaderType = shaderTypes[typeIndex];
238                 std::string             caseName(params.caseName + '_' + getShaderTypeName(shaderType));
239
240                 outputTests.push_back(
241                         new ExecutorTestCase<OutputType>(context, caseName.c_str(), shaderType, shaderSpec, params.outputFloat));
242         }
243 }
244
245 void createTests(deqp::Context& context, const TestParams* cases, int numCases, const char* shaderTemplateSrc,
246                                  const char* casePrefix, std::vector<tcu::TestNode*>& outputTests)
247 {
248         const tcu::StringTemplate shaderTemplate(shaderTemplateSrc);
249         const char*                               componentAccess[] = { "", ".y", ".z", ".w" };
250
251         ShaderExecutorParams shaderExecutorParams;
252         shaderExecutorParams.context = &context;
253
254         for (int caseIndex = 0; caseIndex < numCases; caseIndex++)
255         {
256                 const TestParams&   testCase      = cases[caseIndex];
257                 const std::string   baseName      = testCase.name;
258                 const int                       minComponents = testCase.minComponents;
259                 const int                       maxComponents = testCase.maxComponents;
260                 const glu::DataType inType                = testCase.inType;
261                 const std::string   expression  = testCase.expression;
262
263                 // Check for presence of func(vec, scalar) style specialization,
264                 // use as gatekeeper for applying said specialization
265                 const bool alwaysScalar = expression.find("${MT}") != std::string::npos;
266
267                 std::map<std::string, std::string> shaderTemplateParams;
268                 shaderTemplateParams["CASE_BASE_TYPE"] = glu::getDataTypeName(testCase.outType);
269
270                 shaderExecutorParams.outType     = testCase.outType;
271                 shaderExecutorParams.outputFloat = testCase.outputFloat;
272
273                 for (int component = minComponents - 1; component < maxComponents; component++)
274                 {
275                         // Get type name eg. float, vec2, vec3, vec4 (same for other primitive types)
276                         glu::DataType dataType = static_cast<glu::DataType>(inType + component);
277                         std::string   typeName = glu::getDataTypeName(dataType);
278
279                         // ${T} => final type, ${MT} => final type but with scalar version usable even when T is a vector
280                         std::map<std::string, std::string> expressionTemplateParams;
281                         expressionTemplateParams["T"]  = typeName;
282                         expressionTemplateParams["MT"] = typeName;
283
284                         const tcu::StringTemplate expressionTemplate(expression);
285
286                         // Add vector access to expression as needed
287                         shaderTemplateParams["CASE_EXPRESSION"] =
288                                 expressionTemplate.specialize(expressionTemplateParams) + componentAccess[component];
289
290                         {
291                                 // Add type to case name if we are generating multiple versions
292                                 shaderExecutorParams.caseName = (casePrefix + baseName);
293                                 if (minComponents != maxComponents)
294                                         shaderExecutorParams.caseName += ("_" + typeName);
295
296                                 shaderExecutorParams.source = shaderTemplate.specialize(shaderTemplateParams);
297                                 if (shaderExecutorParams.outType == glu::TYPE_FLOAT)
298                                         createTestCasesForAllShaderTypes<float>(shaderExecutorParams, outputTests);
299                                 else
300                                         createTestCasesForAllShaderTypes<int>(shaderExecutorParams, outputTests);
301                         }
302
303                         // Deal with functions that allways accept one ore more scalar parameters even when others are vectors
304                         if (alwaysScalar && component > 0)
305                         {
306                                 shaderExecutorParams.caseName =
307                                         casePrefix + baseName + "_" + typeName + "_" + glu::getDataTypeName(inType);
308
309                                 expressionTemplateParams["MT"] = glu::getDataTypeName(inType);
310                                 shaderTemplateParams["CASE_EXPRESSION"] =
311                                         expressionTemplate.specialize(expressionTemplateParams) + componentAccess[component];
312
313                                 shaderExecutorParams.source = shaderTemplate.specialize(shaderTemplateParams);
314                                 if (shaderExecutorParams.outType == glu::TYPE_FLOAT)
315                                         createTestCasesForAllShaderTypes<float>(shaderExecutorParams, outputTests);
316                                 else
317                                         createTestCasesForAllShaderTypes<int>(shaderExecutorParams, outputTests);
318                         }
319                 } // component loop
320         }
321 }
322
323 } // namespace ShaderConstExpr
324
325 ShaderConstExprTests::ShaderConstExprTests(deqp::Context& context)
326         : deqp::TestCaseGroup(context, "constant_expressions", "Constant expressions")
327 {
328 }
329
330 ShaderConstExprTests::~ShaderConstExprTests(void)
331 {
332 }
333
334 void ShaderConstExprTests::init(void)
335 {
336         // Needed for autogenerating shader code for increased component counts
337         DE_STATIC_ASSERT(glu::TYPE_FLOAT + 1 == glu::TYPE_FLOAT_VEC2);
338         DE_STATIC_ASSERT(glu::TYPE_FLOAT + 2 == glu::TYPE_FLOAT_VEC3);
339         DE_STATIC_ASSERT(glu::TYPE_FLOAT + 3 == glu::TYPE_FLOAT_VEC4);
340
341         DE_STATIC_ASSERT(glu::TYPE_INT + 1 == glu::TYPE_INT_VEC2);
342         DE_STATIC_ASSERT(glu::TYPE_INT + 2 == glu::TYPE_INT_VEC3);
343         DE_STATIC_ASSERT(glu::TYPE_INT + 3 == glu::TYPE_INT_VEC4);
344
345         DE_STATIC_ASSERT(glu::TYPE_UINT + 1 == glu::TYPE_UINT_VEC2);
346         DE_STATIC_ASSERT(glu::TYPE_UINT + 2 == glu::TYPE_UINT_VEC3);
347         DE_STATIC_ASSERT(glu::TYPE_UINT + 3 == glu::TYPE_UINT_VEC4);
348
349         DE_STATIC_ASSERT(glu::TYPE_BOOL + 1 == glu::TYPE_BOOL_VEC2);
350         DE_STATIC_ASSERT(glu::TYPE_BOOL + 2 == glu::TYPE_BOOL_VEC3);
351         DE_STATIC_ASSERT(glu::TYPE_BOOL + 3 == glu::TYPE_BOOL_VEC4);
352
353         // ${T} => final type, ${MT} => final type but with scalar version usable even when T is a vector
354         const ShaderConstExpr::TestParams baseCases[] = {
355                 { "radians",                    "radians(${T} (90.0))",                                                         glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatRadians(90.0f) } },
356                 { "degrees",                    "degrees(${T} (2.0))",                                                          glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatDegrees(2.0f) } },
357                 { "sin",                                "sin(${T} (3.0))",                                                                      glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatSin(3.0f) } },
358                 { "cos",                                "cos(${T} (3.2))",                                                                      glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatCos(3.2f) } },
359                 { "asin",                               "asin(${T} (0.0))",                                                                     glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatAsin(0.0f) } },
360                 { "acos",                               "acos(${T} (1.0))",                                                                     glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatAcos(1.0f) } },
361                 { "pow",                                "pow(${T} (1.7), ${T} (3.5))",                                          glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatPow(1.7f, 3.5f) } },
362                 { "exp",                                "exp(${T} (4.2))",                                                                      glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatExp(4.2f) } },
363                 { "log",                                "log(${T} (42.12))",                                                            glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatLog(42.12f) } },
364                 { "exp2",                               "exp2(${T} (6.7))",                                                                     glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatExp2(6.7f) } },
365                 { "log2",                               "log2(${T} (100.0))",                                                           glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatLog2(100.0f) } },
366                 { "sqrt",                               "sqrt(${T} (10.0))",                                                            glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatSqrt(10.0f) } },
367                 { "inversesqrt",                "inversesqrt(${T} (10.0))",                                                     glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatRsq(10.0f) } },
368                 { "abs",                                "abs(${T} (-42))",                                                                      glu::TYPE_INT,          1,      4,      glu::TYPE_INT,          { 42 } },
369                 { "sign",                               "sign(${T} (-18.0))",                                                           glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { -1.0f } },
370                 { "floor",                              "floor(${T} (37.3))",                                                           glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatFloor(37.3f) } },
371                 { "trunc",                              "trunc(${T} (-1.8))",                                                           glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { -1.0f } },
372                 { "round",                              "round(${T} (42.1))",                                                           glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { 42.0f } },
373                 { "ceil",                               "ceil(${T} (82.2))",                                                            glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatCeil(82.2f) } },
374                 { "mod",                                "mod(${T} (87.65), ${MT} (3.7))",                                       glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { deFloatMod(87.65f, 3.7f) } },
375                 { "min",                                "min(${T} (12.3), ${MT} (32.1))",                                       glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { 12.3f } },
376                 { "max",                                "max(${T} (12.3), ${MT} (32.1))",                                       glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { 32.1f } },
377                 { "clamp",                              "clamp(${T} (42.1),     ${MT} (10.0), ${MT} (15.0))",   glu::TYPE_FLOAT,        1,      4,      glu::TYPE_FLOAT,        { 15.0f } },
378                 { "length_float",               "length(1.0)",                                                                          glu::TYPE_FLOAT,        1,      1,      glu::TYPE_FLOAT,        { 1.0f } },
379                 { "length_vec2",                "length(vec2(1.0))",                                                            glu::TYPE_FLOAT,        1,      1,      glu::TYPE_FLOAT,        { deFloatSqrt(2.0f) } },
380                 { "length_vec3",                "length(vec3(1.0))",                                                            glu::TYPE_FLOAT,        1,      1,      glu::TYPE_FLOAT,        { deFloatSqrt(3.0f) } },
381                 { "length_vec4",                "length(vec4(1.0))",                                                            glu::TYPE_FLOAT,        1,      1,      glu::TYPE_FLOAT,        { deFloatSqrt(4.0f) } },
382                 { "dot_float",                  "dot(1.0, 1.0)",                                                                        glu::TYPE_FLOAT,        1,      1,      glu::TYPE_FLOAT,        { 1.0f } },
383                 { "dot_vec2",                   "dot(vec2(1.0), vec2(1.0))",                                            glu::TYPE_FLOAT,        1,      1,      glu::TYPE_FLOAT,        { 2.0f } },
384                 { "dot_vec3",                   "dot(vec3(1.0), vec3(1.0))",                                            glu::TYPE_FLOAT,        1,      1,      glu::TYPE_FLOAT,        { 3.0f } },
385                 { "dot_vec4",                   "dot(vec4(1.0), vec4(1.0))",                                            glu::TYPE_FLOAT,        1,      1,      glu::TYPE_FLOAT,        { 4.0f } },
386                 { "normalize_float",    "normalize(1.0)",                                                                       glu::TYPE_FLOAT,        1,      1,      glu::TYPE_FLOAT,        { 1.0f } },
387                 { "normalize_vec2",             "normalize(vec2(1.0)).x",                                                       glu::TYPE_FLOAT,        1,      1,      glu::TYPE_FLOAT,        { deFloatRsq(2.0f) } },
388                 { "normalize_vec3",             "normalize(vec3(1.0)).x",                                                       glu::TYPE_FLOAT,        1,      1,      glu::TYPE_FLOAT,        { deFloatRsq(3.0f) } },
389                 { "normalize_vec4",             "normalize(vec4(1.0)).x",                                                       glu::TYPE_FLOAT,        1,      1,      glu::TYPE_FLOAT,        { deFloatRsq(4.0f) } },
390         };
391
392         const ShaderConstExpr::TestParams arrayCases[] = {
393                 { "radians",                    "radians(${T} (60.0))",                                                 glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatRadians(60.0f) } },
394                 { "degrees",                    "degrees(${T} (0.11))",                                                 glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatDegrees(0.11f) } },
395                 { "sin",                                "${T} (1.0) + sin(${T} (0.7))",                                 glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { 1.0f + deFloatSin(0.7f) } },
396                 { "cos",                                "${T} (1.0) + cos(${T} (0.7))",                                 glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { 1.0f + deFloatCos(0.7f) } },
397                 { "asin",                               "asin(${T} (0.9))",                                                             glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatAsin(0.9f) } },
398                 { "acos",                               "acos(${T} (-0.5))",                                                    glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatAcos(-0.5f) } },
399                 { "pow",                                "pow(${T} (2.0), ${T} (2.0))",                                  glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatPow(2.0f, 2.0f) } },
400                 { "exp",                                "exp(${T} (1.2))",                                                              glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatExp(1.2f) } },
401                 { "log",                                "log(${T} (8.0))",                                                              glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatLog(8.0f) } },
402                 { "exp2",                               "exp2(${T} (2.1))",                                                             glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatExp2(2.1f) } },
403                 { "log2",                               "log2(${T} (9.0))",                                                             glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatLog2(9.0) } },
404                 { "sqrt",                               "sqrt(${T} (4.5))",                                                             glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatSqrt(4.5f) } },
405                 { "inversesqrt",                "inversesqrt(${T} (0.26))",                                             glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatRsq(0.26f) } },
406                 { "abs",                                "abs(${T} (-2))",                                                               glu::TYPE_INT,          1,      4,      glu::TYPE_INT,  { 2 } },
407                 { "sign",                               "sign(${T} (18.0))",                                                    glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatSign(18.0f) } },
408                 { "floor",                              "floor(${T} (3.3))",                                                    glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatFloor(3.3f) } },
409                 { "trunc",                              "trunc(${T} (2.8))",                                                    glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { 2 } },
410                 { "round",                              "round(${T} (2.2))",                                                    glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatRound(2.2f) } },
411                 { "ceil",                               "ceil(${T} (2.2))",                                                             glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatCeil(2.2f) } },
412                 { "mod",                                "mod(${T} (7.1), ${MT} (4.0))",                                 glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatMod(7.1f, 4.0f) } },
413                 { "min",                                "min(${T} (2.3), ${MT} (3.1))",                                 glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatMin(2.3f, 3.1f) } },
414                 { "max",                                "max(${T} (2.3), ${MT} (3.1))",                                 glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { deFloatMax(2.3f, 3.1f) } },
415                 { "clamp",                              "clamp(${T} (4.1),      ${MT} (2.1), ${MT} (3.1))",     glu::TYPE_FLOAT,        1,      4,      glu::TYPE_INT,  { 3 } },
416                 { "length_float",               "length(2.1)",                                                                  glu::TYPE_FLOAT,        1,      1,      glu::TYPE_INT,  { 2 } },
417                 { "length_vec2",                "length(vec2(1.0))",                                                    glu::TYPE_FLOAT,        1,      1,      glu::TYPE_INT,  { deFloatSqrt(2.0f) } },
418                 { "length_vec3",                "length(vec3(1.0))",                                                    glu::TYPE_FLOAT,        1,      1,      glu::TYPE_INT,  { deFloatSqrt(3.0f) } },
419                 { "length_vec4",                "length(vec4(1.0))",                                                    glu::TYPE_FLOAT,        1,      1,      glu::TYPE_INT,  { deFloatSqrt(4.0f) } },
420                 { "dot_float",                  "dot(1.0, 1.0)",                                                                glu::TYPE_FLOAT,        1,      1,      glu::TYPE_INT,  { 1 } },
421                 { "dot_vec2",                   "dot(vec2(1.0), vec2(1.01))",                                   glu::TYPE_FLOAT,        1,      1,      glu::TYPE_INT,  { 2 } },
422                 { "dot_vec3",                   "dot(vec3(1.0), vec3(1.1))",                                    glu::TYPE_FLOAT,        1,      1,      glu::TYPE_INT,  { 3 } },
423                 { "dot_vec4",                   "dot(vec4(1.0), vec4(1.1))",                                    glu::TYPE_FLOAT,        1,      1,      glu::TYPE_INT,  { 4 } },
424                 { "normalize_float",    "${T} (1.0) + normalize(2.0)",                                  glu::TYPE_FLOAT,        1,      1,      glu::TYPE_INT,  { 2 } },
425                 { "normalize_vec2",             "${T} (1.0) + normalize(vec2(1.0)).x",                  glu::TYPE_FLOAT,        1,      1,      glu::TYPE_INT,  { 1.0f + deFloatRsq(2.0f) } },
426                 { "normalize_vec3",             "${T} (1.0) + normalize(vec3(1.0)).x",                  glu::TYPE_FLOAT,        1,      1,      glu::TYPE_INT,  { 1.0f + deFloatRsq(3.0f) } },
427                 { "normalize_vec4",             "${T} (1.0) + normalize(vec4(1.0)).x",                  glu::TYPE_FLOAT,        1,      1,      glu::TYPE_INT,  { 1.0f + deFloatRsq(4.0f) } },
428         };
429
430         const char* basicShaderTemplate = "const ${CASE_BASE_TYPE} cval = ${CASE_EXPRESSION};\n"
431                                                                           "out0 = cval;\n";
432
433         std::vector<tcu::TestNode*> children;
434         ShaderConstExpr::createTests(m_context, baseCases, DE_LENGTH_OF_ARRAY(baseCases), basicShaderTemplate, "basic_",
435                                                                  children);
436
437         const char* arrayShaderTemplate = "float array[int(${CASE_EXPRESSION})];\n"
438                                                                           "out0 = array.length();\n";
439
440         ShaderConstExpr::createTests(m_context, arrayCases, DE_LENGTH_OF_ARRAY(arrayCases), arrayShaderTemplate, "array_",
441                                                                  children);
442
443         for (std::size_t i = 0; i < children.size(); i++)
444                 addChild(children[i]);
445 }
446
447 } // glcts