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 */ /*!
20 * \file glcAggressiveShaderOptimizationsTests.cpp
21 * \brief Conformance tests that checks if shader optimizations are not
22 * overly aggressive. This is done by compering result of complex
23 * trigonometric functions aproximation to shader buil
24 */ /*-------------------------------------------------------------------*/
25
26 #include "glcAggressiveShaderOptimizationsTests.hpp"
27 #include "deSharedPtr.hpp"
28 #include "glsShaderExecUtil.hpp"
29 #include "gluContextInfo.hpp"
30 #include "gluDrawUtil.hpp"
31 #include "gluPixelTransfer.hpp"
32 #include "gluShaderProgram.hpp"
33 #include "glwFunctions.hpp"
34 #include "tcuImageCompare.hpp"
35 #include "tcuRenderTarget.hpp"
36 #include "tcuStringTemplate.hpp"
37 #include "tcuSurface.hpp"
38 #include "tcuTestLog.hpp"
39
40 using namespace glw;
41
42 namespace glcts
43 {
44
45 enum ShaderType
46 {
47 TEST_VERTEX_SHADER,
48 TEST_FRAGMENT_SHADER
49 };
50
51 struct TrigonometryCaseData
52 {
53 const char *testedFunction;
54 const char *testedType;
55 const char *colorComponents;
56 ShaderType shaderType;
57 };
58
59 class TrigonometryTestCase : public deqp::TestCase
60 {
61 public:
62 TrigonometryTestCase(deqp::Context &context, const std::string &name, const TrigonometryCaseData &data);
63 virtual ~TrigonometryTestCase();
64
65 IterateResult iterate(void);
66
67 protected:
68 glu::ProgramSources prepareSineSources(bool useBuiltin);
69 glu::ProgramSources prepareCosineSources(bool useBuiltin);
70
71 void renderAndGrabSurface(glu::ProgramSources sources, tcu::Surface &result) const;
72
73 private:
74 ShaderType m_shaderType;
75 const char *m_testedFunction;
76 std::map<std::string, std::string> m_specializationMap;
77 };
78
TrigonometryTestCase(deqp::Context & context,const std::string & name,const TrigonometryCaseData & data)79 TrigonometryTestCase::TrigonometryTestCase(deqp::Context &context, const std::string &name,
80 const TrigonometryCaseData &data)
81 : deqp::TestCase(context, name.c_str(), "")
82 , m_shaderType(data.shaderType)
83 , m_testedFunction(data.testedFunction)
84 {
85 glu::ContextType contextType = m_context.getRenderContext().getType();
86 glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(contextType);
87
88 m_specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(glslVersion);
89 m_specializationMap["TYPE"] = data.testedType;
90 m_specializationMap["COLOR_COMPONENTS"] = data.colorComponents;
91
92 if (glu::contextSupports(contextType, glu::ApiType::es(3, 0)) || glu::isContextTypeGLCore(contextType))
93 {
94 m_specializationMap["IN"] = "in";
95 m_specializationMap["OUT"] = "out";
96 m_specializationMap["ATTRIBUTE"] = "in";
97 m_specializationMap["FS_OUT_COLOR_NAME"] = "fragColor";
98 m_specializationMap["FS_OUT_COLOR_DECLARATION"] = "out vec4 fragColor;";
99 }
100 else
101 {
102 m_specializationMap["IN"] = "varying";
103 m_specializationMap["OUT"] = "varying";
104 m_specializationMap["ATTRIBUTE"] = "attribute";
105 m_specializationMap["FS_OUT_COLOR_NAME"] = "gl_FragColor";
106 m_specializationMap["FS_OUT_COLOR_DECLARATION"] = "";
107 }
108 }
109
~TrigonometryTestCase()110 TrigonometryTestCase::~TrigonometryTestCase()
111 {
112 }
113
prepareSineSources(bool useBuiltinSin)114 glu::ProgramSources TrigonometryTestCase::prepareSineSources(bool useBuiltinSin)
115 {
116 const char *vsDefault = "${VERSION}\n"
117 "${ATTRIBUTE} highp vec2 position;\n"
118 "${ATTRIBUTE} highp vec3 baseColor;\n"
119 "${OUT} vec4 color;\n"
120 "void main (void) {\n"
121 " color = vec4(baseColor, 1.0);\n"
122 " gl_Position = vec4(position, 0.0, 1.0);\n"
123 "}\n";
124
125 const char *vsCalculateSin = "${VERSION}\n"
126 "${ATTRIBUTE} highp vec2 position;\n"
127 "${ATTRIBUTE} highp vec3 baseColor;\n"
128 "${OUT} vec4 color;\n"
129 "${SIN_FUNCTION_DEFINITION_VS}\n"
130 "void main (void) {\n"
131 " const float M_2PI = 2.0 * 3.14159265358979323846;\n"
132 " ${TYPE} c = baseColor.${COLOR_COMPONENTS} * M_2PI;\n"
133 " ${TYPE} sin_c = ${SIN_FUNCTION_NAME}(c);\n"
134 " \n"
135 " color = vec4(0.0, 0.0, 0.0, 1.0);\n"
136 " color.${COLOR_COMPONENTS} = sin_c * 0.5 + 0.5;\n"
137 " gl_Position = vec4(position, 0.0, 1.0);\n"
138 "}\n";
139
140 const char *fsDefault = "${VERSION}\n"
141 "precision mediump float;\n"
142 "${IN} vec4 color;\n"
143 "${FS_OUT_COLOR_DECLARATION}\n"
144 "void main (void) {\n"
145 " ${FS_OUT_COLOR_NAME} = color;\n"
146 "}\n";
147
148 const char *fsCalculateSin = "${VERSION}\n"
149 "precision mediump float;\n"
150 "${IN} vec4 color;\n"
151 "${FS_OUT_COLOR_DECLARATION}\n\n"
152 "${SIN_FUNCTION_DEFINITION_FS}\n"
153 "void main (void) {\n"
154 " const float M_2PI = 2.0 * 3.14159265358979323846;\n"
155 " ${TYPE} c = color.${COLOR_COMPONENTS};\n"
156 " ${TYPE} sin_c = ${SIN_FUNCTION_NAME}(c * M_2PI);\n"
157 " \n"
158 " ${FS_OUT_COLOR_NAME} =vec4(0.0, 0.0, 0.0, 1.0);\n"
159 " ${FS_OUT_COLOR_NAME}.${COLOR_COMPONENTS} = sin_c * 0.5 + 0.5;\n"
160 "}\n";
161
162 std::string vsTemplate;
163 std::string fsTemplate;
164
165 if (m_shaderType == TEST_VERTEX_SHADER)
166 {
167 vsTemplate = vsCalculateSin;
168 fsTemplate = fsDefault;
169 }
170 else
171 {
172 vsTemplate = vsDefault;
173 fsTemplate = fsCalculateSin;
174 }
175
176 if (useBuiltinSin)
177 {
178 m_specializationMap["SIN_FUNCTION_NAME"] = "sin";
179 m_specializationMap["SIN_FUNCTION_DEFINITION_VS"] = "";
180 m_specializationMap["SIN_FUNCTION_DEFINITION_FS"] = "";
181 }
182 else
183 {
184 std::string sinFunctionDefinitionVS = "${TYPE} ${SIN_FUNCTION_NAME}(${TYPE} c) {\n"
185 " ${TYPE} sin_c = ${TYPE}(0.0);\n"
186 " float sign = 1.0;\n"
187 " float fact;\n"
188 " float fact_of;\n"
189 " \n"
190 " // Taylors series expansion for sin \n"
191 " for(int i = 0; i < 12; i++) {\n"
192 " fact = 1.0;\n"
193 " for(int j = 2; j <= 23; j++)\n"
194 " if (j <= 2 * i + 1)\n"
195 " fact *= float(j);\n"
196 " \n"
197 " sin_c += sign * pow(c, ${TYPE}(2.0 * float(i) + 1.0)) / fact;\n"
198 " sign *= -1.0;\n"
199 " }\n"
200 " return sin_c;\n"
201 "}";
202 std::string sinFunctionDefinitionFS = "float lerpHelper(float a, float b, float weight) {\n"
203 " return a + (b - a) * weight;\n"
204 "}\n"
205 "float sinLerpHelper(int index, float weight) {\n"
206 " float sArray[17];\n"
207 " sArray[0] = 0.0;\n"
208 " sArray[1] = 0.382683;\n"
209 " sArray[2] = 0.707107;\n"
210 " sArray[3] = 0.92388;\n"
211 " sArray[4] = 1.0;\n"
212 " sArray[5] = 0.92388;\n"
213 " sArray[6] = 0.707107;\n"
214 " sArray[7] = 0.382683;\n"
215 " sArray[8] = 0.0;\n"
216 " sArray[9] = -0.382683;\n"
217 " sArray[10] = -0.707107;\n"
218 " sArray[11] = -0.92388;\n"
219 " sArray[12] = -1.0;\n"
220 " sArray[13] = -0.923879;\n"
221 " sArray[14] = -0.707107;\n"
222 " sArray[15] = -0.382683;\n"
223 " sArray[16] = 0.0;\n"
224 " \n"
225 " if (index == 0)\n"
226 " return lerpHelper(sArray[0], sArray[1], weight);\n"
227 " if (index == 1)\n"
228 " return lerpHelper(sArray[1], sArray[2], weight);\n"
229 " if (index == 2)\n"
230 " return lerpHelper(sArray[2], sArray[3], weight);\n"
231 " if (index == 3)\n"
232 " return lerpHelper(sArray[3], sArray[4], weight);\n"
233 " if (index == 4)\n"
234 " return lerpHelper(sArray[4], sArray[5], weight);\n"
235 " if (index == 5)\n"
236 " return lerpHelper(sArray[5], sArray[6], weight);\n"
237 " if (index == 6)\n"
238 " return lerpHelper(sArray[6], sArray[7], weight);\n"
239 " if (index == 7)\n"
240 " return lerpHelper(sArray[7], sArray[8], weight);\n"
241 " if (index == 8)\n"
242 " return lerpHelper(sArray[8], sArray[9], weight);\n"
243 " if (index == 9)\n"
244 " return lerpHelper(sArray[9], sArray[10], weight);\n"
245 " if (index == 10)\n"
246 " return lerpHelper(sArray[10], sArray[11], weight);\n"
247 " if (index == 11)\n"
248 " return lerpHelper(sArray[11], sArray[12], weight);\n"
249 " if (index == 12)\n"
250 " return lerpHelper(sArray[12], sArray[13], weight);\n"
251 " if (index == 13)\n"
252 " return lerpHelper(sArray[13], sArray[14], weight);\n"
253 " if (index == 14)\n"
254 " return lerpHelper(sArray[14], sArray[15], weight);\n"
255 " if (index == 15)\n"
256 " return lerpHelper(sArray[15], sArray[16], weight);\n"
257 " return sArray[16];\n"
258 "}\n"
259 "${TYPE} ${SIN_FUNCTION_NAME}(${TYPE} c) {\n"
260 " ${TYPE} arrVal = c * 2.546478971;\n"
261 " ${TYPE} weight = arrVal - floor(arrVal);\n"
262 " ${TYPE} sin_c = ${TYPE}(0.0);\n"
263 " ${INTERPOLATE_SIN}"
264 " return sin_c;\n"
265 "}";
266
267 if (m_specializationMap["TYPE"] == "float")
268 {
269 m_specializationMap["INTERPOLATE_SIN"] = "\n"
270 " int index = int(floor(arrVal));\n"
271 " sin_c = sinLerpHelper(index, weight);\n";
272 }
273 else if (m_specializationMap["TYPE"] == "vec2")
274 {
275 m_specializationMap["INTERPOLATE_SIN"] = "\n"
276 " int indexX = int(floor(arrVal.x));\n"
277 " sin_c.x = sinLerpHelper(indexX, weight.x);\n"
278 " int indexY = int(floor(arrVal.y));\n"
279 " sin_c.y = sinLerpHelper(indexY, weight.y);\n";
280 }
281 else if (m_specializationMap["TYPE"] == "vec3")
282 {
283 m_specializationMap["INTERPOLATE_SIN"] = "\n"
284 " int indexX = int(floor(arrVal.x));\n"
285 " sin_c.x = sinLerpHelper(indexX, weight.x);\n"
286 " int indexY = int(floor(arrVal.y));\n"
287 " sin_c.y = sinLerpHelper(indexY, weight.y);\n"
288 " int indexZ = int(floor(arrVal.z));\n"
289 " sin_c.z = sinLerpHelper(indexZ, weight.z);\n";
290 }
291
292 m_specializationMap["SIN_FUNCTION_NAME"] = "calculateSin";
293 m_specializationMap["SIN_FUNCTION_DEFINITION_VS"] =
294 tcu::StringTemplate(sinFunctionDefinitionVS).specialize(m_specializationMap);
295 m_specializationMap["SIN_FUNCTION_DEFINITION_FS"] =
296 tcu::StringTemplate(sinFunctionDefinitionFS).specialize(m_specializationMap);
297 }
298
299 // Specialize shader templates
300 vsTemplate = tcu::StringTemplate(vsTemplate).specialize(m_specializationMap);
301 fsTemplate = tcu::StringTemplate(fsTemplate).specialize(m_specializationMap);
302 return glu::makeVtxFragSources(vsTemplate.c_str(), fsTemplate.c_str());
303 }
304
prepareCosineSources(bool useBuiltinCos)305 glu::ProgramSources TrigonometryTestCase::prepareCosineSources(bool useBuiltinCos)
306 {
307 const char *vsDefault = "${VERSION}\n"
308 "${ATTRIBUTE} highp vec2 position;\n"
309 "${ATTRIBUTE} highp vec3 baseColor;\n"
310 "${OUT} vec4 color;\n"
311 "void main (void) {\n"
312 " color = vec4(baseColor, 1.0);\n"
313 " gl_Position = vec4(position, 0.0, 1.0);\n"
314 "}\n";
315
316 const char *vsCalculateCos = "${VERSION}\n"
317 "${ATTRIBUTE} highp vec2 position;\n"
318 "${ATTRIBUTE} highp vec3 baseColor;\n"
319 "${OUT} vec4 color;\n"
320 "${COS_FUNCTION_DEFINITION_VS}\n"
321 "void main (void) {\n"
322 " const float M_2PI = 2.0 * 3.14159265358979323846;\n"
323 " ${TYPE} c = baseColor.${COLOR_COMPONENTS};\n"
324 " ${TYPE} cos_c = ${COS_FUNCTION_NAME}(c * M_2PI);\n"
325 " \n"
326 " color = vec4(0.0, 0.0, 0.0, 1.0);\n"
327 " color.${COLOR_COMPONENTS} = cos_c * 0.5 + 0.5;\n"
328 " gl_Position = vec4(position, 0.0, 1.0);\n"
329 "}\n";
330
331 const char *fsDefault = "${VERSION}\n"
332 "precision mediump float;\n"
333 "${IN} vec4 color;\n"
334 "${FS_OUT_COLOR_DECLARATION}\n"
335 "void main (void) {\n"
336 " ${FS_OUT_COLOR_NAME} = color;\n"
337 "}\n";
338
339 const char *fsCalculateCos = "${VERSION}\n"
340 "precision mediump float;\n"
341 "${IN} vec4 color;\n"
342 "${FS_OUT_COLOR_DECLARATION}\n\n"
343 "// function definitions \n"
344 "${COS_FUNCTION_DEFINITION_FS}\n"
345 "${TYPE} preprocessColor(${TYPE} c) {\n"
346 " ${PREPROCESS_COLOR};\n"
347 " return c;\n"
348 "}\n\n"
349 "void main (void) {\n"
350 " const float M_2PI = 2.0 * 3.14159265358979323846;\n"
351 " ${TYPE} c = preprocessColor(color.${COLOR_COMPONENTS});\n"
352 " ${TYPE} cos_c = ${COS_FUNCTION_NAME}(c * M_2PI);\n"
353 " \n"
354 " ${FS_OUT_COLOR_NAME} = vec4(0.0, 0.0, 0.0, 1.0);\n"
355 " ${FS_OUT_COLOR_NAME}.${COLOR_COMPONENTS} = cos_c * 0.5 + 0.5;\n"
356 "}\n";
357
358 std::string vsTemplate;
359 std::string fsTemplate;
360
361 if (m_shaderType == TEST_VERTEX_SHADER)
362 {
363 vsTemplate = vsCalculateCos;
364 fsTemplate = fsDefault;
365 }
366 else
367 {
368 vsTemplate = vsDefault;
369 fsTemplate = fsCalculateCos;
370 }
371
372 if (useBuiltinCos)
373 {
374 m_specializationMap["PREPROCESS_COLOR"] = "";
375 m_specializationMap["COS_FUNCTION_NAME"] = "cos";
376 m_specializationMap["COS_FUNCTION_DEFINITION_VS"] = "";
377 m_specializationMap["COS_FUNCTION_DEFINITION_FS"] = "";
378 }
379 else
380 {
381 std::string cosFunctionDefinitionVS = "${TYPE} ${COS_FUNCTION_NAME}(${TYPE} c) {\n"
382 " ${TYPE} cos_c = ${TYPE}(1.0);\n"
383 " float sign = -1.0;\n"
384 " float fact = 1.0;\n"
385 " \n"
386 " for(int i = 2; i <= 20; i += 2) {\n"
387 " fact *= float(i)*float(i-1);\n"
388 " cos_c += sign*pow(c, ${TYPE}(float(i)))/fact;\n"
389 " sign = -sign;\n"
390 " }\n"
391 " return cos_c;\n"
392 "}";
393 std::string cosFunctionDefinitionFS = "${TYPE} ${COS_FUNCTION_NAME}(${TYPE} c) {\n"
394 " ${TYPE} cos_c = ${TYPE}(-1.0);\n"
395 " float sign = 1.0;\n"
396 " float fact_even = 1.0;\n"
397 " float fact_odd = 1.0;\n"
398 " ${TYPE} sum;\n"
399 " ${TYPE} exp;\n"
400 " \n"
401 " for(int i = 2; i <= 10; i += 2) {\n"
402 " fact_even *= float(i);\n"
403 " fact_odd *= float(i-1);\n"
404 " exp = ${TYPE}(float(i/2));\n"
405 " sum = sign * pow(abs(c), exp)/fact_even;\n"
406 " cos_c += pow(abs(c), exp)*(sum/fact_odd);\n"
407 " sign = -sign;\n"
408 " }\n"
409 " return cos_c;\n"
410 "}";
411
412 m_specializationMap["PREPROCESS_COLOR"] = "c = (fract(abs(c)) - 0.5)";
413 m_specializationMap["COS_FUNCTION_NAME"] = "calculateCos";
414 m_specializationMap["COS_FUNCTION_DEFINITION_VS"] =
415 tcu::StringTemplate(cosFunctionDefinitionVS).specialize(m_specializationMap);
416 m_specializationMap["COS_FUNCTION_DEFINITION_FS"] =
417 tcu::StringTemplate(cosFunctionDefinitionFS).specialize(m_specializationMap);
418 }
419
420 // Specialize shader templates
421 vsTemplate = tcu::StringTemplate(vsTemplate).specialize(m_specializationMap);
422 fsTemplate = tcu::StringTemplate(fsTemplate).specialize(m_specializationMap);
423 return glu::makeVtxFragSources(vsTemplate.c_str(), fsTemplate.c_str());
424 }
425
renderAndGrabSurface(glu::ProgramSources sources,tcu::Surface & result) const426 void TrigonometryTestCase::renderAndGrabSurface(glu::ProgramSources sources, tcu::Surface &result) const
427 {
428 static const uint16_t quadIndices[] = {0, 1, 2, 2, 1, 3};
429 static const float positions[] = {-1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0};
430 static const float baseColors[] = {1.0, 0.0, 0.25, 0.75, 0.25, 1.0, 0.0, 1.0, 0.75, 0.25, 0.5, 0.0};
431
432 glu::RenderContext &renderContext = m_context.getRenderContext();
433 const glw::Functions &gl = renderContext.getFunctions();
434 glu::ShaderProgram testProgram(renderContext, sources);
435 if (!testProgram.isOk())
436 {
437 m_testCtx.getLog() << testProgram;
438 TCU_FAIL("Test program compilation failed");
439 }
440
441 // Render
442 gl.useProgram(testProgram.getProgram());
443 const glu::VertexArrayBinding vertexArrays[] = {glu::va::Float("position", 2, 4, 0, positions),
444 glu::va::Float("baseColor", 3, 4, 0, baseColors)};
445 glu::draw(renderContext, testProgram.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
446 glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices));
447
448 // Grab surface
449 glu::readPixels(renderContext, 0, 0, result.getAccess());
450 }
451
iterate(void)452 tcu::TestNode::IterateResult TrigonometryTestCase::iterate(void)
453 {
454 glu::RenderContext &renderContext = m_context.getRenderContext();
455 const glw::Functions &gl = renderContext.getFunctions();
456
457 int renderWidth = 64;
458 int renderHeight = 64;
459 if (renderWidth > m_context.getRenderTarget().getWidth())
460 renderWidth = m_context.getRenderTarget().getWidth();
461 if (renderHeight > m_context.getRenderTarget().getHeight())
462 renderHeight = m_context.getRenderTarget().getHeight();
463 bool isSin = std::string(m_testedFunction) == "sin";
464
465 gl.viewport(0, 0, renderWidth, renderHeight);
466
467 // Use program that will call trigonometric function aproximation
468 tcu::Surface testSurface(renderWidth, renderHeight);
469 if (isSin)
470 renderAndGrabSurface(prepareSineSources(false), testSurface);
471 else
472 renderAndGrabSurface(prepareCosineSources(false), testSurface);
473
474 // Use reference program that will call builtin function
475 tcu::Surface referenceSurface(renderWidth, renderHeight);
476 if (isSin)
477 renderAndGrabSurface(prepareSineSources(true), referenceSurface);
478 else
479 renderAndGrabSurface(prepareCosineSources(true), referenceSurface);
480
481 // Compare surfaces
482 qpTestResult testResult = QP_TEST_RESULT_FAIL;
483 if (tcu::fuzzyCompare(m_testCtx.getLog(), "Result", "Image comparison result", referenceSurface, testSurface, 0.05f,
484 tcu::COMPARE_LOG_RESULT))
485 testResult = QP_TEST_RESULT_PASS;
486
487 m_testCtx.setTestResult(testResult, qpGetTestResultName(testResult));
488 return STOP;
489 }
490
AggressiveShaderOptimizationsTests(deqp::Context & context)491 AggressiveShaderOptimizationsTests::AggressiveShaderOptimizationsTests(deqp::Context &context)
492 : TestCaseGroup(context, "aggressive_optimizations", "checks if shader optimizations are not overly aggressive")
493 {
494 }
495
~AggressiveShaderOptimizationsTests()496 AggressiveShaderOptimizationsTests::~AggressiveShaderOptimizationsTests()
497 {
498 }
499
init(void)500 void AggressiveShaderOptimizationsTests::init(void)
501 {
502 TrigonometryCaseData trigonometryCases[] = {
503 {"sin", "float", "r", TEST_VERTEX_SHADER}, {"sin", "float", "r", TEST_FRAGMENT_SHADER},
504 {"sin", "vec2", "rg", TEST_VERTEX_SHADER}, {"sin", "vec2", "rg", TEST_FRAGMENT_SHADER},
505 {"sin", "vec3", "rgb", TEST_VERTEX_SHADER}, {"sin", "vec3", "rgb", TEST_FRAGMENT_SHADER},
506 {"cos", "float", "r", TEST_VERTEX_SHADER}, {"cos", "float", "r", TEST_FRAGMENT_SHADER},
507 {"cos", "vec2", "rg", TEST_VERTEX_SHADER}, {"cos", "vec2", "rg", TEST_FRAGMENT_SHADER},
508 {"cos", "vec3", "rgb", TEST_VERTEX_SHADER}, {"cos", "vec3", "rgb", TEST_FRAGMENT_SHADER},
509 };
510
511 for (int i = 0; i < DE_LENGTH_OF_ARRAY(trigonometryCases); ++i)
512 {
513 const TrigonometryCaseData &tcd = trigonometryCases[i];
514 std::string shaderType = (tcd.shaderType == TEST_VERTEX_SHADER) ? "_vert" : "_frag";
515 std::string name = std::string(tcd.testedFunction) + "_" + tcd.testedType + shaderType;
516 addChild(new TrigonometryTestCase(m_context, name, tcd));
517 }
518 }
519
520 } // namespace glcts
521