1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2017 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * \file glcShaderConstExprTests.cpp
20 * \brief Declares shader constant expressions tests.
21 */ /*-------------------------------------------------------------------*/
23 #include "glcShaderConstExprTests.hpp"
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"
34 using namespace deqp::gls::ShaderExecUtil;
39 namespace ShaderConstExpr
45 const char* expression;
51 glu::DataType outType;
58 struct ShaderExecutorParams
60 deqp::Context* context;
65 glu::DataType outType;
72 template <typename OutputType>
73 class ExecutorTestCase : public deqp::TestCase
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);
82 void validateOutput(de::SharedPtr<ShaderExecutor> executor);
84 glu::ShaderType m_shaderType;
85 ShaderSpec m_shaderSpec;
86 OutputType m_expectedOutput;
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)
99 template <typename OutputType>
100 ExecutorTestCase<OutputType>::~ExecutorTestCase(void)
105 void ExecutorTestCase<float>::validateOutput(de::SharedPtr<ShaderExecutor> executor)
108 void* const outputs = &result;
109 executor->execute(1, DE_NULL, &outputs);
111 const float epsilon = 0.01f;
112 if (de::abs(m_expectedOutput - result) > epsilon)
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");
123 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
128 void ExecutorTestCase<int>::validateOutput(de::SharedPtr<ShaderExecutor> executor)
131 void* const outputs = &result;
132 executor->execute(1, DE_NULL, &outputs);
134 if (result == m_expectedOutput)
136 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
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");
145 template <typename OutputType>
146 tcu::TestNode::IterateResult ExecutorTestCase<OutputType>::iterate(void)
148 de::SharedPtr<ShaderExecutor> executor(createExecutor(m_context.getRenderContext(), m_shaderType, m_shaderSpec));
150 DE_ASSERT(executor.get());
152 executor->log(m_context.getTestContext().getLog());
156 if (!executor->isOk())
157 TCU_FAIL("Compilation failed");
159 executor->useProgram();
161 validateOutput(executor);
163 catch (const tcu::NotSupportedError& e)
165 m_testCtx.getLog() << tcu::TestLog::Message << e.what() << tcu::TestLog::EndMessage;
166 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, e.getMessage());
168 catch (const tcu::TestError& e)
170 m_testCtx.getLog() << tcu::TestLog::Message << e.what() << tcu::TestLog::EndMessage;
171 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, e.getMessage());
174 return tcu::TestNode::STOP;
177 template <typename OutputType>
178 void createTestCasesForAllShaderTypes(const ShaderExecutorParams& params, std::vector<tcu::TestNode*>& outputTests)
180 DE_ASSERT(params.context);
182 deqp::Context& context = *(params.context);
183 glu::ContextType contextType = context.getRenderContext().getType();
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)));
190 // Construct list of shaders for which tests can be created
191 std::vector<glu::ShaderType> shaderTypes;
193 if (glu::contextSupports(contextType, glu::ApiType::core(4, 3)))
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);
202 else if (glu::contextSupports(contextType, glu::ApiType::es(3, 2)))
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);
209 else if (glu::contextSupports(contextType, glu::ApiType::es(3, 1)))
211 shaderSpec.version = glu::GLSL_VERSION_310_ES;
212 shaderTypes.push_back(glu::SHADERTYPE_COMPUTE);
214 if (context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader") ||
215 context.getContextInfo().isExtensionSupported("GL_OES_geometry_shader"))
217 shaderTypes.push_back(glu::SHADERTYPE_GEOMETRY);
220 if (context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader") ||
221 context.getContextInfo().isExtensionSupported("GL_OES_tessellation_shader"))
223 shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_CONTROL);
224 shaderTypes.push_back(glu::SHADERTYPE_TESSELLATION_EVALUATION);
229 shaderTypes.push_back(glu::SHADERTYPE_VERTEX);
230 shaderTypes.push_back(glu::SHADERTYPE_FRAGMENT);
233 shaderSpec.globalDeclarations += "precision highp float;\n";
235 for (std::size_t typeIndex = 0; typeIndex < shaderTypes.size(); ++typeIndex)
237 glu::ShaderType shaderType = shaderTypes[typeIndex];
238 std::string caseName(params.caseName + '_' + getShaderTypeName(shaderType));
240 outputTests.push_back(
241 new ExecutorTestCase<OutputType>(context, caseName.c_str(), shaderType, shaderSpec, params.outputFloat));
245 void createTests(deqp::Context& context, const TestParams* cases, int numCases, const char* shaderTemplateSrc,
246 const char* casePrefix, std::vector<tcu::TestNode*>& outputTests)
248 const tcu::StringTemplate shaderTemplate(shaderTemplateSrc);
249 const char* componentAccess[] = { "", ".y", ".z", ".w" };
251 ShaderExecutorParams shaderExecutorParams;
252 shaderExecutorParams.context = &context;
254 for (int caseIndex = 0; caseIndex < numCases; caseIndex++)
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;
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;
267 std::map<std::string, std::string> shaderTemplateParams;
268 shaderTemplateParams["CASE_BASE_TYPE"] = glu::getDataTypeName(testCase.outType);
270 shaderExecutorParams.outType = testCase.outType;
271 shaderExecutorParams.outputFloat = testCase.outputFloat;
273 for (int component = minComponents - 1; component < maxComponents; component++)
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);
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;
284 const tcu::StringTemplate expressionTemplate(expression);
286 // Add vector access to expression as needed
287 shaderTemplateParams["CASE_EXPRESSION"] =
288 expressionTemplate.specialize(expressionTemplateParams) + componentAccess[component];
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);
296 shaderExecutorParams.source = shaderTemplate.specialize(shaderTemplateParams);
297 if (shaderExecutorParams.outType == glu::TYPE_FLOAT)
298 createTestCasesForAllShaderTypes<float>(shaderExecutorParams, outputTests);
300 createTestCasesForAllShaderTypes<int>(shaderExecutorParams, outputTests);
303 // Deal with functions that allways accept one ore more scalar parameters even when others are vectors
304 if (alwaysScalar && component > 0)
306 shaderExecutorParams.caseName =
307 casePrefix + baseName + "_" + typeName + "_" + glu::getDataTypeName(inType);
309 expressionTemplateParams["MT"] = glu::getDataTypeName(inType);
310 shaderTemplateParams["CASE_EXPRESSION"] =
311 expressionTemplate.specialize(expressionTemplateParams) + componentAccess[component];
313 shaderExecutorParams.source = shaderTemplate.specialize(shaderTemplateParams);
314 if (shaderExecutorParams.outType == glu::TYPE_FLOAT)
315 createTestCasesForAllShaderTypes<float>(shaderExecutorParams, outputTests);
317 createTestCasesForAllShaderTypes<int>(shaderExecutorParams, outputTests);
323 } // namespace ShaderConstExpr
325 ShaderConstExprTests::ShaderConstExprTests(deqp::Context& context)
326 : deqp::TestCaseGroup(context, "constant_expressions", "Constant expressions")
330 ShaderConstExprTests::~ShaderConstExprTests(void)
334 void ShaderConstExprTests::init(void)
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);
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);
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);
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);
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) } },
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) } },
430 const char* basicShaderTemplate = "const ${CASE_BASE_TYPE} cval = ${CASE_EXPRESSION};\n"
433 std::vector<tcu::TestNode*> children;
434 ShaderConstExpr::createTests(m_context, baseCases, DE_LENGTH_OF_ARRAY(baseCases), basicShaderTemplate, "basic_",
437 const char* arrayShaderTemplate = "float array[int(${CASE_EXPRESSION})];\n"
438 "out0 = array.length();\n";
440 ShaderConstExpr::createTests(m_context, arrayCases, DE_LENGTH_OF_ARRAY(arrayCases), arrayShaderTemplate, "array_",
443 for (std::size_t i = 0; i < children.size(); i++)
444 addChild(children[i]);