• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <map>
24 #include "deMath.h"
25 #include "deSharedPtr.hpp"
26 #include "glcShaderConstExprTests.hpp"
27 #include "glsShaderExecUtil.hpp"
28 #include "gluContextInfo.hpp"
29 #include "gluShaderUtil.hpp"
30 #include "tcuFloat.hpp"
31 #include "tcuStringTemplate.hpp"
32 #include "tcuTestLog.hpp"
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     {
54         float outputFloat;
55         int outputInt;
56     };
57 };
58 
59 struct ShaderExecutorParams
60 {
61     deqp::Context *context;
62 
63     std::string caseName;
64     std::string source;
65 
66     glu::DataType outType;
67     union
68     {
69         float outputFloat;
70         int outputInt;
71     };
72 };
73 
74 template <typename OutputType>
75 class ExecutorTestCase : public deqp::TestCase
76 {
77   public:
78     ExecutorTestCase(deqp::Context &context,
79                      const char *name,
80                      glu::ShaderType shaderType,
81                      const ShaderSpec &shaderSpec,
82                      OutputType expectedOutput);
83     virtual ~ExecutorTestCase(void);
84     virtual tcu::TestNode::IterateResult iterate(void);
85 
86   protected:
87     void validateOutput(de::SharedPtr<ShaderExecutor> executor);
88 
89     glu::ShaderType m_shaderType;
90     ShaderSpec m_shaderSpec;
91     OutputType m_expectedOutput;
92 };
93 
94 template <typename OutputType>
ExecutorTestCase(deqp::Context & context,const char * name,glu::ShaderType shaderType,const ShaderSpec & shaderSpec,OutputType expectedOutput)95 ExecutorTestCase<OutputType>::ExecutorTestCase(deqp::Context &context,
96                                                const char *name,
97                                                glu::ShaderType shaderType,
98                                                const ShaderSpec &shaderSpec,
99                                                OutputType expectedOutput)
100     : deqp::TestCase(context, name, ""),
101       m_shaderType(shaderType),
102       m_shaderSpec(shaderSpec),
103       m_expectedOutput(expectedOutput)
104 {}
105 
106 template <typename OutputType>
~ExecutorTestCase(void)107 ExecutorTestCase<OutputType>::~ExecutorTestCase(void)
108 {}
109 
110 template <>
validateOutput(de::SharedPtr<ShaderExecutor> executor)111 void ExecutorTestCase<float>::validateOutput(de::SharedPtr<ShaderExecutor> executor)
112 {
113     float result        = 0.0f;
114     void *const outputs = &result;
115     executor->execute(1, DE_NULL, &outputs);
116 
117     const float epsilon = 0.01f;
118     if (de::abs(m_expectedOutput - result) > epsilon)
119     {
120         m_context.getTestContext().getLog()
121             << tcu::TestLog::Message << "Expected: " << m_expectedOutput << " ("
122             << tcu::toHex(tcu::Float32(m_expectedOutput).bits())
123             << ") but constant expresion returned: " << result << " ("
124             << tcu::toHex(tcu::Float32(result).bits()) << "), used " << epsilon
125             << " epsilon for comparison" << tcu::TestLog::EndMessage;
126         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
127         return;
128     }
129 
130     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
131     return;
132 }
133 
134 template <>
validateOutput(de::SharedPtr<ShaderExecutor> executor)135 void ExecutorTestCase<int>::validateOutput(de::SharedPtr<ShaderExecutor> executor)
136 {
137     int result          = 0;
138     void *const outputs = &result;
139     executor->execute(1, DE_NULL, &outputs);
140 
141     if (result == m_expectedOutput)
142     {
143         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
144         return;
145     }
146 
147     m_context.getTestContext().getLog()
148         << tcu::TestLog::Message << "Expected: " << m_expectedOutput
149         << " but constant expresion returned: " << result << tcu::TestLog::EndMessage;
150     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
151 }
152 
153 template <typename OutputType>
iterate(void)154 tcu::TestNode::IterateResult ExecutorTestCase<OutputType>::iterate(void)
155 {
156     de::SharedPtr<ShaderExecutor> executor(
157         createExecutor(m_context.getRenderContext(), m_shaderType, m_shaderSpec));
158 
159     DE_ASSERT(executor.get());
160 
161     executor->log(m_context.getTestContext().getLog());
162 
163     try
164     {
165         if (!executor->isOk())
166             TCU_FAIL("Compilation failed");
167 
168         executor->useProgram();
169 
170         validateOutput(executor);
171     }
172     catch (const tcu::NotSupportedError &e)
173     {
174         m_testCtx.getLog() << tcu::TestLog::Message << e.what() << tcu::TestLog::EndMessage;
175         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, e.getMessage());
176     }
177     catch (const tcu::TestError &e)
178     {
179         m_testCtx.getLog() << tcu::TestLog::Message << e.what() << tcu::TestLog::EndMessage;
180         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, e.getMessage());
181     }
182 
183     return tcu::TestNode::STOP;
184 }
185 
186 template <typename OutputType>
createTestCasesForAllShaderTypes(const ShaderExecutorParams & params,std::vector<tcu::TestNode * > & outputTests)187 void createTestCasesForAllShaderTypes(const ShaderExecutorParams &params,
188                                       std::vector<tcu::TestNode *> &outputTests)
189 {
190     DE_ASSERT(params.context);
191 
192     deqp::Context &context       = *(params.context);
193     glu::ContextType contextType = context.getRenderContext().getType();
194 
195     ShaderSpec shaderSpec;
196     shaderSpec.version = glu::getContextTypeGLSLVersion(contextType);
197     shaderSpec.source  = params.source;
198     shaderSpec.outputs.push_back(
199         Symbol("out0", glu::VarType(params.outType, glu::PRECISION_HIGHP)));
200 
201     // Construct list of shaders for which tests can be created
202     std::vector<glu::ShaderType> shaderTypes;
203 
204     if (glu::contextSupports(contextType, glu::ApiType::core(4, 3)))
205     {
206         shaderTypes.push_back(glu::SHADERTYPE_VERTEX);
207         shaderTypes.push_back(glu::SHADERTYPE_FRAGMENT);
208         shaderTypes.push_back(glu::SHADERTYPE_COMPUTE);
209         shaderTypes.push_back(glu::SHADERTYPE_GEOMETRY);
210         shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_CONTROL);
211         shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_EVALUATION);
212     }
213     else if (glu::contextSupports(contextType, glu::ApiType::es(3, 2)))
214     {
215         shaderSpec.version = glu::GLSL_VERSION_320_ES;
216         shaderTypes.push_back(glu::SHADERTYPE_GEOMETRY);
217         shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_CONTROL);
218         shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_EVALUATION);
219     }
220     else if (glu::contextSupports(contextType, glu::ApiType::es(3, 1)))
221     {
222         shaderSpec.version = glu::GLSL_VERSION_310_ES;
223         shaderTypes.push_back(glu::SHADERTYPE_COMPUTE);
224         shaderTypes.push_back(glu::SHADERTYPE_GEOMETRY);
225         shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_CONTROL);
226         shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_EVALUATION);
227     }
228     else
229     {
230         shaderTypes.push_back(glu::SHADERTYPE_VERTEX);
231         shaderTypes.push_back(glu::SHADERTYPE_FRAGMENT);
232     }
233 
234     shaderSpec.globalDeclarations += "precision highp float;\n";
235 
236     for (std::size_t typeIndex = 0; typeIndex < shaderTypes.size(); ++typeIndex)
237     {
238         glu::ShaderType shaderType = shaderTypes[typeIndex];
239         std::string caseName(params.caseName + '_' + getShaderTypeName(shaderType));
240 
241         outputTests.push_back(
242             new ExecutorTestCase<OutputType>(context, caseName.c_str(), shaderType, shaderSpec,
243                                              static_cast<OutputType>(params.outputFloat)));
244     }
245 }
246 
createTests(deqp::Context & context,const TestParams * cases,int numCases,const char * shaderTemplateSrc,const char * casePrefix,std::vector<tcu::TestNode * > & outputTests)247 void createTests(deqp::Context &context,
248                  const TestParams *cases,
249                  int numCases,
250                  const char *shaderTemplateSrc,
251                  const char *casePrefix,
252                  std::vector<tcu::TestNode *> &outputTests)
253 {
254     const tcu::StringTemplate shaderTemplate(shaderTemplateSrc);
255     const char *componentAccess[] = {"", ".y", ".z", ".w"};
256 
257     ShaderExecutorParams shaderExecutorParams;
258     shaderExecutorParams.context = &context;
259 
260     for (int caseIndex = 0; caseIndex < numCases; caseIndex++)
261     {
262         const TestParams &testCase   = cases[caseIndex];
263         const std::string baseName   = testCase.name;
264         const int minComponents      = testCase.minComponents;
265         const int maxComponents      = testCase.maxComponents;
266         const glu::DataType inType   = testCase.inType;
267         const std::string expression = testCase.expression;
268 
269         // Check for presence of func(vec, scalar) style specialization,
270         // use as gatekeeper for applying said specialization
271         const bool alwaysScalar = expression.find("${MT}") != std::string::npos;
272 
273         std::map<std::string, std::string> shaderTemplateParams;
274         shaderTemplateParams["CASE_BASE_TYPE"] = glu::getDataTypeName(testCase.outType);
275 
276         shaderExecutorParams.outType     = testCase.outType;
277         shaderExecutorParams.outputFloat = testCase.outputFloat;
278 
279         for (int component = minComponents - 1; component < maxComponents; component++)
280         {
281             // Get type name eg. float, vec2, vec3, vec4 (same for other primitive types)
282             glu::DataType dataType = static_cast<glu::DataType>(inType + component);
283             std::string typeName   = glu::getDataTypeName(dataType);
284 
285             // ${T} => final type, ${MT} => final type but with scalar version usable even when T is
286             // a vector
287             std::map<std::string, std::string> expressionTemplateParams;
288             expressionTemplateParams["T"]  = typeName;
289             expressionTemplateParams["MT"] = typeName;
290 
291             const tcu::StringTemplate expressionTemplate(expression);
292 
293             // Add vector access to expression as needed
294             shaderTemplateParams["CASE_EXPRESSION"] =
295                 expressionTemplate.specialize(expressionTemplateParams) +
296                 componentAccess[component];
297 
298             {
299                 // Add type to case name if we are generating multiple versions
300                 shaderExecutorParams.caseName = (casePrefix + baseName);
301                 if (minComponents != maxComponents)
302                     shaderExecutorParams.caseName += ("_" + typeName);
303 
304                 shaderExecutorParams.source = shaderTemplate.specialize(shaderTemplateParams);
305                 if (shaderExecutorParams.outType == glu::TYPE_FLOAT)
306                     createTestCasesForAllShaderTypes<float>(shaderExecutorParams, outputTests);
307                 else
308                     createTestCasesForAllShaderTypes<int>(shaderExecutorParams, outputTests);
309             }
310 
311             // Deal with functions that allways accept one ore more scalar parameters even when
312             // others are vectors
313             if (alwaysScalar && component > 0)
314             {
315                 shaderExecutorParams.caseName =
316                     casePrefix + baseName + "_" + typeName + "_" + glu::getDataTypeName(inType);
317 
318                 expressionTemplateParams["MT"] = glu::getDataTypeName(inType);
319                 shaderTemplateParams["CASE_EXPRESSION"] =
320                     expressionTemplate.specialize(expressionTemplateParams) +
321                     componentAccess[component];
322 
323                 shaderExecutorParams.source = shaderTemplate.specialize(shaderTemplateParams);
324                 if (shaderExecutorParams.outType == glu::TYPE_FLOAT)
325                     createTestCasesForAllShaderTypes<float>(shaderExecutorParams, outputTests);
326                 else
327                     createTestCasesForAllShaderTypes<int>(shaderExecutorParams, outputTests);
328             }
329         }  // component loop
330     }
331 }
332 
333 }  // namespace ShaderConstExpr
334 
ShaderConstExprTests(deqp::Context & context)335 ShaderConstExprTests::ShaderConstExprTests(deqp::Context &context)
336     : deqp::TestCaseGroup(context, "constant_expressions", "Constant expressions")
337 {}
338 
~ShaderConstExprTests(void)339 ShaderConstExprTests::~ShaderConstExprTests(void) {}
340 
init(void)341 void ShaderConstExprTests::init(void)
342 {
343     // Needed for autogenerating shader code for increased component counts
344     DE_STATIC_ASSERT(glu::TYPE_FLOAT + 1 == glu::TYPE_FLOAT_VEC2);
345     DE_STATIC_ASSERT(glu::TYPE_FLOAT + 2 == glu::TYPE_FLOAT_VEC3);
346     DE_STATIC_ASSERT(glu::TYPE_FLOAT + 3 == glu::TYPE_FLOAT_VEC4);
347 
348     DE_STATIC_ASSERT(glu::TYPE_INT + 1 == glu::TYPE_INT_VEC2);
349     DE_STATIC_ASSERT(glu::TYPE_INT + 2 == glu::TYPE_INT_VEC3);
350     DE_STATIC_ASSERT(glu::TYPE_INT + 3 == glu::TYPE_INT_VEC4);
351 
352     DE_STATIC_ASSERT(glu::TYPE_UINT + 1 == glu::TYPE_UINT_VEC2);
353     DE_STATIC_ASSERT(glu::TYPE_UINT + 2 == glu::TYPE_UINT_VEC3);
354     DE_STATIC_ASSERT(glu::TYPE_UINT + 3 == glu::TYPE_UINT_VEC4);
355 
356     DE_STATIC_ASSERT(glu::TYPE_BOOL + 1 == glu::TYPE_BOOL_VEC2);
357     DE_STATIC_ASSERT(glu::TYPE_BOOL + 2 == glu::TYPE_BOOL_VEC3);
358     DE_STATIC_ASSERT(glu::TYPE_BOOL + 3 == glu::TYPE_BOOL_VEC4);
359 
360     // ${T} => final type, ${MT} => final type but with scalar version usable even when T is a
361     // vector
362     const ShaderConstExpr::TestParams baseCases[] = {
363         {"radians",
364          "radians(${T} (90.0))",
365          glu::TYPE_FLOAT,
366          1,
367          4,
368          glu::TYPE_FLOAT,
369          {deFloatRadians(90.0f)}},
370         {"degrees",
371          "degrees(${T} (2.0))",
372          glu::TYPE_FLOAT,
373          1,
374          4,
375          glu::TYPE_FLOAT,
376          {deFloatDegrees(2.0f)}},
377         {"sin", "sin(${T} (3.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatSin(3.0f)}},
378         {"cos", "cos(${T} (3.2))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatCos(3.2f)}},
379         {"asin", "asin(${T} (0.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatAsin(0.0f)}},
380         {"acos", "acos(${T} (1.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatAcos(1.0f)}},
381         {"pow",
382          "pow(${T} (1.7), ${T} (3.5))",
383          glu::TYPE_FLOAT,
384          1,
385          4,
386          glu::TYPE_FLOAT,
387          {deFloatPow(1.7f, 3.5f)}},
388         {"exp", "exp(${T} (4.2))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatExp(4.2f)}},
389         {"log", "log(${T} (42.12))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatLog(42.12f)}},
390         {"exp2", "exp2(${T} (6.7))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatExp2(6.7f)}},
391         {"log2",
392          "log2(${T} (100.0))",
393          glu::TYPE_FLOAT,
394          1,
395          4,
396          glu::TYPE_FLOAT,
397          {deFloatLog2(100.0f)}},
398         {"sqrt", "sqrt(${T} (10.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatSqrt(10.0f)}},
399         {"inversesqrt",
400          "inversesqrt(${T} (10.0))",
401          glu::TYPE_FLOAT,
402          1,
403          4,
404          glu::TYPE_FLOAT,
405          {deFloatRsq(10.0f)}},
406         {"abs", "abs(${T} (-42))", glu::TYPE_INT, 1, 4, glu::TYPE_INT, {42}},
407         {"sign", "sign(${T} (-18.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {-1.0f}},
408         {"floor",
409          "floor(${T} (37.3))",
410          glu::TYPE_FLOAT,
411          1,
412          4,
413          glu::TYPE_FLOAT,
414          {deFloatFloor(37.3f)}},
415         {"trunc", "trunc(${T} (-1.8))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {-1.0f}},
416         {"round", "round(${T} (42.1))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {42.0f}},
417         {"ceil", "ceil(${T} (82.2))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {deFloatCeil(82.2f)}},
418         {"mod",
419          "mod(${T} (87.65), ${MT} (3.7))",
420          glu::TYPE_FLOAT,
421          1,
422          4,
423          glu::TYPE_FLOAT,
424          {deFloatMod(87.65f, 3.7f)}},
425         {"min", "min(${T} (12.3), ${MT} (32.1))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {12.3f}},
426         {"max", "max(${T} (12.3), ${MT} (32.1))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_FLOAT, {32.1f}},
427         {"clamp",
428          "clamp(${T} (42.1),    ${MT} (10.0), ${MT} (15.0))",
429          glu::TYPE_FLOAT,
430          1,
431          4,
432          glu::TYPE_FLOAT,
433          {15.0f}},
434         {"length_float", "length(1.0)", glu::TYPE_FLOAT, 1, 1, glu::TYPE_FLOAT, {1.0f}},
435         {"length_vec2",
436          "length(vec2(1.0))",
437          glu::TYPE_FLOAT,
438          1,
439          1,
440          glu::TYPE_FLOAT,
441          {deFloatSqrt(2.0f)}},
442         {"length_vec3",
443          "length(vec3(1.0))",
444          glu::TYPE_FLOAT,
445          1,
446          1,
447          glu::TYPE_FLOAT,
448          {deFloatSqrt(3.0f)}},
449         {"length_vec4",
450          "length(vec4(1.0))",
451          glu::TYPE_FLOAT,
452          1,
453          1,
454          glu::TYPE_FLOAT,
455          {deFloatSqrt(4.0f)}},
456         {"dot_float", "dot(1.0, 1.0)", glu::TYPE_FLOAT, 1, 1, glu::TYPE_FLOAT, {1.0f}},
457         {"dot_vec2", "dot(vec2(1.0), vec2(1.0))", glu::TYPE_FLOAT, 1, 1, glu::TYPE_FLOAT, {2.0f}},
458         {"dot_vec3", "dot(vec3(1.0), vec3(1.0))", glu::TYPE_FLOAT, 1, 1, glu::TYPE_FLOAT, {3.0f}},
459         {"dot_vec4", "dot(vec4(1.0), vec4(1.0))", glu::TYPE_FLOAT, 1, 1, glu::TYPE_FLOAT, {4.0f}},
460         {"normalize_float", "normalize(1.0)", glu::TYPE_FLOAT, 1, 1, glu::TYPE_FLOAT, {1.0f}},
461         {"normalize_vec2",
462          "normalize(vec2(1.0)).x",
463          glu::TYPE_FLOAT,
464          1,
465          1,
466          glu::TYPE_FLOAT,
467          {deFloatRsq(2.0f)}},
468         {"normalize_vec3",
469          "normalize(vec3(1.0)).x",
470          glu::TYPE_FLOAT,
471          1,
472          1,
473          glu::TYPE_FLOAT,
474          {deFloatRsq(3.0f)}},
475         {"normalize_vec4",
476          "normalize(vec4(1.0)).x",
477          glu::TYPE_FLOAT,
478          1,
479          1,
480          glu::TYPE_FLOAT,
481          {deFloatRsq(4.0f)}},
482     };
483 
484     const ShaderConstExpr::TestParams arrayCases[] = {
485         {"radians",
486          "radians(${T} (60.0))",
487          glu::TYPE_FLOAT,
488          1,
489          4,
490          glu::TYPE_INT,
491          {deFloatRadians(60.0f)}},
492         {"degrees",
493          "degrees(${T} (0.11))",
494          glu::TYPE_FLOAT,
495          1,
496          4,
497          glu::TYPE_INT,
498          {deFloatDegrees(0.11f)}},
499         {"sin",
500          "${T} (1.0) + sin(${T} (0.7))",
501          glu::TYPE_FLOAT,
502          1,
503          4,
504          glu::TYPE_INT,
505          {1.0f + deFloatSin(0.7f)}},
506         {"cos",
507          "${T} (1.0) + cos(${T} (0.7))",
508          glu::TYPE_FLOAT,
509          1,
510          4,
511          glu::TYPE_INT,
512          {1.0f + deFloatCos(0.7f)}},
513         {"asin", "asin(${T} (0.9))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatAsin(0.9f)}},
514         {"acos", "acos(${T} (-0.5))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatAcos(-0.5f)}},
515         {"pow",
516          "pow(${T} (2.0), ${T} (2.0))",
517          glu::TYPE_FLOAT,
518          1,
519          4,
520          glu::TYPE_INT,
521          {deFloatPow(2.0f, 2.0f)}},
522         {"exp", "exp(${T} (1.2))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatExp(1.2f)}},
523         {"log", "log(${T} (8.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatLog(8.0f)}},
524         {"exp2", "exp2(${T} (2.1))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatExp2(2.1f)}},
525         {"log2", "log2(${T} (9.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatLog2(9.0)}},
526         {"sqrt", "sqrt(${T} (4.5))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatSqrt(4.5f)}},
527         {"inversesqrt",
528          "inversesqrt(${T} (0.26))",
529          glu::TYPE_FLOAT,
530          1,
531          4,
532          glu::TYPE_INT,
533          {deFloatRsq(0.26f)}},
534         {"abs", "abs(${T} (-2))", glu::TYPE_INT, 1, 4, glu::TYPE_INT, {2}},
535         {"sign", "sign(${T} (18.0))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatSign(18.0f)}},
536         {"floor", "floor(${T} (3.3))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatFloor(3.3f)}},
537         {"trunc", "trunc(${T} (2.8))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {2}},
538         {"round", "round(${T} (2.2))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatRound(2.2f)}},
539         {"ceil", "ceil(${T} (2.2))", glu::TYPE_FLOAT, 1, 4, glu::TYPE_INT, {deFloatCeil(2.2f)}},
540         {"mod",
541          "mod(${T} (7.1), ${MT} (4.0))",
542          glu::TYPE_FLOAT,
543          1,
544          4,
545          glu::TYPE_INT,
546          {deFloatMod(7.1f, 4.0f)}},
547         {"min",
548          "min(${T} (2.3), ${MT} (3.1))",
549          glu::TYPE_FLOAT,
550          1,
551          4,
552          glu::TYPE_INT,
553          {deFloatMin(2.3f, 3.1f)}},
554         {"max",
555          "max(${T} (2.3), ${MT} (3.1))",
556          glu::TYPE_FLOAT,
557          1,
558          4,
559          glu::TYPE_INT,
560          {deFloatMax(2.3f, 3.1f)}},
561         {"clamp",
562          "clamp(${T} (4.1), ${MT} (2.1), ${MT} (3.1))",
563          glu::TYPE_FLOAT,
564          1,
565          4,
566          glu::TYPE_INT,
567          {3}},
568         {"length_float", "length(2.1)", glu::TYPE_FLOAT, 1, 1, glu::TYPE_INT, {2}},
569         {"length_vec2",
570          "length(vec2(1.0))",
571          glu::TYPE_FLOAT,
572          1,
573          1,
574          glu::TYPE_INT,
575          {deFloatSqrt(2.0f)}},
576         {"length_vec3",
577          "length(vec3(1.0))",
578          glu::TYPE_FLOAT,
579          1,
580          1,
581          glu::TYPE_INT,
582          {deFloatSqrt(3.0f)}},
583         {"length_vec4",
584          "length(vec4(1.0))",
585          glu::TYPE_FLOAT,
586          1,
587          1,
588          glu::TYPE_INT,
589          {deFloatSqrt(4.0f)}},
590         {"dot_float", "dot(1.0, 1.0)", glu::TYPE_FLOAT, 1, 1, glu::TYPE_INT, {1}},
591         {"dot_vec2", "dot(vec2(1.0), vec2(1.01))", glu::TYPE_FLOAT, 1, 1, glu::TYPE_INT, {2}},
592         {"dot_vec3", "dot(vec3(1.0), vec3(1.1))", glu::TYPE_FLOAT, 1, 1, glu::TYPE_INT, {3}},
593         {"dot_vec4", "dot(vec4(1.0), vec4(1.1))", glu::TYPE_FLOAT, 1, 1, glu::TYPE_INT, {4}},
594         {"normalize_float",
595          "${T} (1.0) + normalize(2.0)",
596          glu::TYPE_FLOAT,
597          1,
598          1,
599          glu::TYPE_INT,
600          {2}},
601         {"normalize_vec2",
602          "${T} (1.0) + normalize(vec2(1.0)).x",
603          glu::TYPE_FLOAT,
604          1,
605          1,
606          glu::TYPE_INT,
607          {1.0f + deFloatRsq(2.0f)}},
608         {"normalize_vec3",
609          "${T} (1.0) + normalize(vec3(1.0)).x",
610          glu::TYPE_FLOAT,
611          1,
612          1,
613          glu::TYPE_INT,
614          {1.0f + deFloatRsq(3.0f)}},
615         {"normalize_vec4",
616          "${T} (1.0) + normalize(vec4(1.0)).x",
617          glu::TYPE_FLOAT,
618          1,
619          1,
620          glu::TYPE_INT,
621          {1.0f + deFloatRsq(4.0f)}},
622     };
623 
624     const char *basicShaderTemplate =
625         "const ${CASE_BASE_TYPE} cval = ${CASE_EXPRESSION};\n"
626         "out0 = cval;\n";
627 
628     std::vector<tcu::TestNode *> children;
629     ShaderConstExpr::createTests(m_context, baseCases, DE_LENGTH_OF_ARRAY(baseCases),
630                                  basicShaderTemplate, "basic_", children);
631 
632     const char *arrayShaderTemplate =
633         "float array[int(${CASE_EXPRESSION})];\n"
634         "out0 = array.length();\n";
635 
636     ShaderConstExpr::createTests(m_context, arrayCases, DE_LENGTH_OF_ARRAY(arrayCases),
637                                  arrayShaderTemplate, "array_", children);
638 
639     for (std::size_t i = 0; i < children.size(); i++)
640         addChild(children[i]);
641 }
642 
643 }  // namespace glcts
644