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 ¶ms,
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