1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2016 Google Inc.
6 * Copyright (c) 2016 The Khronos Group Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */ /*!
21 * \file
22 * \brief GLSL vector constructor tests.
23 */ /*-------------------------------------------------------------------*/
24 #include "glcGLSLVectorConstructorTests.hpp"
25
26 #include "gluDefs.hpp"
27 #include "gluTextureUtil.hpp"
28 #include "gluDrawUtil.hpp"
29 #include "gluShaderProgram.hpp"
30
31 #include "glwDefs.hpp"
32 #include "glwFunctions.hpp"
33 #include "glwEnums.hpp"
34
35 #include "tcuTestLog.hpp"
36 #include "tcuRenderTarget.hpp"
37 #include "tcuStringTemplate.hpp"
38
39 #include <functional>
40 #include <map>
41 #include <vector>
42 #include <sstream>
43 #include <string>
44 #include <tuple>
45
46 namespace deqp
47 {
48
49 namespace
50 {
51 using std::string;
52
53 using std::map;
54 using std::vector;
55
56 using std::bind;
57 using std::function;
58 using namespace std::placeholders;
59
60 using std::ostringstream;
61
62 enum struct TestType
63 {
64 VERTEX_SHADER_ERROR = 0,
65 FRAGMENT_SHADER_ERROR,
66 VERTEX_SHADER,
67 FRAGMENT_SHADER
68 };
69
70 struct TestDefinition
71 {
72 vector<string> outputTypes;
73 vector<vector<string>> inputTypeLists;
74 string extraFields;
75 };
76
77 const TestDefinition tests[] = {
78 {
79 {"vec2", "vec3", "vec4"}, // vector<string> outputTypes
80 {
81 // vector<vector<string>> inputTypeLists
82 {"mat2"},
83 {"mat2x3"},
84 {"mat2x4"},
85 {"mat3"},
86 {"mat3x2"},
87 {"mat3x4"},
88 {"mat4"},
89 {"mat4x2"},
90 {"mat4x3"},
91 {"float", "mat2"},
92 {"float", "mat2x3"},
93 {"float", "mat2x4"},
94 {"float", "mat3"},
95 {"float", "mat3x2"},
96 {"float", "mat3x4"},
97 {"float", "mat4"},
98 {"float", "mat4x2"},
99 {"float", "mat4x3"},
100 },
101 "const float errorBound = 1.0E-5;\n" // uint32_t extraFields;
102 },
103 {
104 {"ivec2", "ivec3", "ivec4"}, // vector<string> outputTypes
105 {
106 // vector<vector<string>> inputTypeLists
107 {"mat2"},
108 {"mat2x3"},
109 {"mat2x4"},
110 {"mat3"},
111 {"mat3x2"},
112 {"mat3x4"},
113 {"mat4"},
114 {"mat4x2"},
115 {"mat4x3"},
116 {"int", "mat2"},
117 {"int", "mat2x3"},
118 {"int", "mat2x4"},
119 {"int", "mat3"},
120 {"int", "mat3x2"},
121 {"int", "mat3x4"},
122 {"int", "mat4"},
123 {"int", "mat4x2"},
124 {"int", "mat4x3"},
125 },
126 "" // uint32_t extraFields;
127 },
128 {
129 {"bvec2", "bvec3", "bvec4"}, // vector<string> outputTypes
130 {
131 // vector<vector<string>> inputTypeLists
132 {"mat2"},
133 {"mat2x3"},
134 {"mat2x4"},
135 {"mat3"},
136 {"mat3x2"},
137 {"mat3x4"},
138 {"mat4"},
139 {"mat4x2"},
140 {"mat4x3"},
141 {"bool", "mat2"},
142 {"bool", "mat2x3"},
143 {"bool", "mat2x4"},
144 {"bool", "mat3"},
145 {"bool", "mat3x2"},
146 {"bool", "mat3x4"},
147 {"bool", "mat4"},
148 {"bool", "mat4x2"},
149 {"bool", "mat4x3"},
150 },
151 "" // uint32_t extraFields;
152 },
153 };
154
155 struct TestParams
156 {
157 string name;
158 string description;
159 TestType testType;
160 string outputType;
161 vector<string> inputTypes;
162 string extraFields;
163 };
164
generateTestParams()165 vector<TestParams> generateTestParams()
166 {
167 vector<TestParams> result;
168 result.reserve(64);
169 for (const auto &test : tests)
170 {
171 for (const auto &outputType : test.outputTypes)
172 {
173 for (const auto &inputTypes : test.inputTypeLists)
174 {
175 ostringstream testNameVs, testNameFs;
176 ostringstream testDescriptionVs, testDescriptionFs;
177 testNameVs << outputType << "_from";
178 testNameFs << outputType << "_from";
179 testDescriptionVs << outputType << "(";
180 testDescriptionFs << outputType << "(";
181 for (vector<string>::size_type i = 0; i < inputTypes.size(); ++i)
182 {
183 const auto &inputType = inputTypes[i];
184 testNameVs << "_" << inputType;
185 testNameFs << "_" << inputType;
186 if (i > 0)
187 {
188 testDescriptionVs << ",";
189 testDescriptionFs << ",";
190 }
191 testDescriptionVs << inputType;
192 }
193 ostringstream testNameInvalidVs, testNameInvalidFs;
194 testNameInvalidVs << testNameVs.str() << "_" << inputTypes[0] << "_invalid_vs";
195 testNameInvalidFs << testNameFs.str() << "_" << inputTypes[0] << "_invalid_fs";
196
197 testNameVs << "_vs";
198 testNameFs << "_fs";
199 testDescriptionVs << ") vertex shader";
200 testDescriptionFs << ") fragment shader";
201 result.push_back({testNameVs.str(), testDescriptionVs.str(), TestType::VERTEX_SHADER, outputType,
202 inputTypes, test.extraFields});
203 result.push_back({testNameFs.str(), testDescriptionFs.str(), TestType::FRAGMENT_SHADER, outputType,
204 inputTypes, test.extraFields});
205
206 vector<string> failInputTypes;
207 failInputTypes.insert(failInputTypes.end(), inputTypes.begin(), inputTypes.end());
208 failInputTypes.push_back(inputTypes[0]);
209 testDescriptionVs << " invalid";
210 testDescriptionFs << " invalid";
211 result.push_back({testNameInvalidVs.str(), testDescriptionVs.str(), TestType::VERTEX_SHADER_ERROR,
212 outputType, failInputTypes, test.extraFields});
213 result.push_back({testNameInvalidFs.str(), testDescriptionFs.str(), TestType::FRAGMENT_SHADER_ERROR,
214 outputType, failInputTypes, test.extraFields});
215 }
216 }
217 }
218 return result;
219 }
220
221 const string defaultVertexShader = "${GLSL_VERSION}\n"
222 "in vec4 vPosition;\n"
223 "void main()\n"
224 "{\n"
225 " gl_Position = vPosition;\n"
226 "}\n";
227
228 const string defaultFragmentShader = "${GLSL_VERSION}\n"
229 "precision mediump float;\n"
230 "in vec4 vColor;\n"
231 "out vec4 my_FragColor;\n"
232 "void main() {\n"
233 " my_FragColor = vColor;\n"
234 "}\n";
235
236 const string vertexShaderTemplate = "${GLSL_VERSION}\n"
237 "in vec4 vPosition;\n"
238 "precision mediump int;\n"
239 "precision mediump float;\n"
240 "const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
241 "const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
242 "${TEST_CONSTANTS}"
243 "out vec4 vColor;\n"
244 "void main() {\n"
245 " ${TEST_CODE}\n"
246 " if ${TEST_CONDITION}\n"
247 " vColor = green;\n"
248 " else\n"
249 " vColor = red;\n"
250 " gl_Position = vPosition;\n"
251 "}\n";
252
253 const string fragmentShaderTemplate = "${GLSL_VERSION}\n"
254 "precision mediump int;\n"
255 "precision mediump float;\n"
256 "const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
257 "const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
258 "${TEST_CONSTANTS}"
259 "out vec4 my_FragColor;\n"
260 "void main() {\n"
261 " ${TEST_CODE}\n"
262 " if ${TEST_CONDITION}\n"
263 " my_FragColor = green;\n"
264 " else\n"
265 " my_FragColor = red;\n"
266 "}\n";
267
268 const map<string, string> testConditions = {
269 {"vec2", "(abs(v[0] - 0.0) <= errorBound && abs(v[1] - 1.0) <= errorBound)"},
270 {"vec3", "(abs(v[0] - 0.0) <= errorBound && abs(v[1] - 1.0) <= errorBound && abs(v[2] - 2.0) <= errorBound)"},
271 {"vec4", "(abs(v[0] - 0.0) <= errorBound && abs(v[1] - 1.0) <= errorBound && abs(v[2] - 2.0) <= errorBound && "
272 "abs(v[3] - 3.0) <= errorBound)"},
273 {"ivec2", "(v[0] == 0 && v[1] == 1)"},
274 {"ivec3", "(v[0] == 0 && v[1] == 1 && v[2] == 2)"},
275 {"ivec4", "(v[0] == 0 && v[1] == 1 && v[2] == 2 && v[3] == 3)"},
276 {"bvec2", "(v[0] == false && v[1] == true)"},
277 {"bvec3", "(v[0] == false && v[1] == true && v[2] == true)"},
278 {"bvec4", "(v[0] == false && v[1] == true && v[2] == true && v[3] == true)"}};
279
280 typedef function<void(ostringstream &, size_t)> GeneratorFn;
281
282 struct DataTypeInfo
283 {
284 size_t numElements;
285 GeneratorFn valueFn;
286 GeneratorFn beforeValueFn;
287 GeneratorFn afterValueFn;
288 };
289
generateValueFloat(ostringstream & out,const size_t index)290 void generateValueFloat(ostringstream &out, const size_t index)
291 {
292 out << index << ".0";
293 }
294
generateValueInt(ostringstream & out,const size_t index)295 void generateValueInt(ostringstream &out, const size_t index)
296 {
297 out << index;
298 }
299
generateValueBool(ostringstream & out,const size_t index)300 void generateValueBool(ostringstream &out, const size_t index)
301 {
302 out << ((index != 0) ? "true" : "false");
303 }
304
generateCtorOpen(const char * className,ostringstream & out,const size_t)305 void generateCtorOpen(const char *className, ostringstream &out, const size_t)
306 {
307 out << className << "(";
308 }
309
generateCtorClose(ostringstream & out,const size_t)310 void generateCtorClose(ostringstream &out, const size_t)
311 {
312 out << ")";
313 }
314
315 const map<string, DataTypeInfo> dataTypeInfos = {
316 // numElements , valueFn , beforeValueFn , afterValueFn
317 {"float", {1, generateValueFloat, DE_NULL, DE_NULL}},
318 {"vec2", {2, generateValueFloat, bind(generateCtorOpen, "vec2", _1, _2), generateCtorClose}},
319 {"vec3", {3, generateValueFloat, bind(generateCtorOpen, "vec3", _1, _2), generateCtorClose}},
320 {"vec4", {4, generateValueFloat, bind(generateCtorOpen, "vec4", _1, _2), generateCtorClose}},
321 {"int", {1, generateValueInt, DE_NULL, DE_NULL}},
322 {"ivec2", {2, generateValueInt, bind(generateCtorOpen, "ivec2", _1, _2), generateCtorClose}},
323 {"ivec3", {3, generateValueInt, bind(generateCtorOpen, "ivec3", _1, _2), generateCtorClose}},
324 {"ivec4", {4, generateValueInt, bind(generateCtorOpen, "ivec4", _1, _2), generateCtorClose}},
325 {"bool", {1, generateValueBool, DE_NULL, DE_NULL}},
326 {"bvec2", {2, generateValueBool, bind(generateCtorOpen, "bvec2", _1, _2), generateCtorClose}},
327 {"bvec3", {3, generateValueBool, bind(generateCtorOpen, "bvec3", _1, _2), generateCtorClose}},
328 {"bvec4", {4, generateValueBool, bind(generateCtorOpen, "bvec4", _1, _2), generateCtorClose}},
329 {"mat2", {4, generateValueFloat, bind(generateCtorOpen, "mat2", _1, _2), generateCtorClose}},
330 {"mat2x3", {6, generateValueFloat, bind(generateCtorOpen, "mat2x3", _1, _2), generateCtorClose}},
331 {"mat2x4", {8, generateValueFloat, bind(generateCtorOpen, "mat2x4", _1, _2), generateCtorClose}},
332 {"mat3", {9, generateValueFloat, bind(generateCtorOpen, "mat3", _1, _2), generateCtorClose}},
333 {"mat3x2", {6, generateValueFloat, bind(generateCtorOpen, "mat3x2", _1, _2), generateCtorClose}},
334 {"mat3x4", {12, generateValueFloat, bind(generateCtorOpen, "mat3x4", _1, _2), generateCtorClose}},
335 {"mat4", {16, generateValueFloat, bind(generateCtorOpen, "mat4", _1, _2), generateCtorClose}},
336 {"mat4x2", {8, generateValueFloat, bind(generateCtorOpen, "mat4x2", _1, _2), generateCtorClose}},
337 {"mat4x3", {12, generateValueFloat, bind(generateCtorOpen, "mat4x3", _1, _2), generateCtorClose}},
338 };
339
generateTestCode(const string & outputType,const vector<string> & inputTypes)340 string generateTestCode(const string &outputType, const vector<string> &inputTypes)
341 {
342 ostringstream output;
343 const auto outputTypeInfo = dataTypeInfos.find(outputType);
344 DE_ASSERT(outputTypeInfo != dataTypeInfos.end());
345
346 output << outputType << " v = ";
347 if (outputTypeInfo->second.beforeValueFn != DE_NULL)
348 outputTypeInfo->second.beforeValueFn(output, -1);
349 int outputElementsRemaining = (int)outputTypeInfo->second.numElements;
350 int outputElementIndex = 0;
351 for (size_t i = 0; i < inputTypes.size() && outputElementsRemaining > 0; ++i)
352 {
353 const auto &inputType = inputTypes[i];
354 const auto inputTypeInfo = dataTypeInfos.find(inputType);
355 DE_ASSERT(inputTypeInfo != dataTypeInfos.end());
356
357 if (outputElementIndex > 0)
358 output << ", ";
359 if (inputTypeInfo->second.beforeValueFn != DE_NULL)
360 inputTypeInfo->second.beforeValueFn(output, i);
361 for (size_t j = 0; j < inputTypeInfo->second.numElements; ++j)
362 {
363 if (j > 0)
364 output << ", ";
365
366 inputTypeInfo->second.valueFn(output, outputElementIndex++);
367 --outputElementsRemaining;
368 }
369 if (inputTypeInfo->second.afterValueFn != DE_NULL)
370 inputTypeInfo->second.afterValueFn(output, i);
371 }
372 if (outputTypeInfo->second.afterValueFn != DE_NULL)
373 outputTypeInfo->second.afterValueFn(output, -1);
374 output << ";";
375 return output.str();
376 }
377
replacePlaceholders(const string & shaderTemplate,const TestParams & params,const glu::GLSLVersion glslVersion)378 string replacePlaceholders(const string &shaderTemplate, const TestParams ¶ms, const glu::GLSLVersion glslVersion)
379 {
380 const auto condition = testConditions.find(params.outputType);
381 return tcu::StringTemplate(shaderTemplate)
382 .specialize({{"GLSL_VERSION", glu::getGLSLVersionDeclaration(glslVersion)},
383 {"TEST_CONSTANTS", params.extraFields},
384 {"TEST_CODE", generateTestCode(params.outputType, params.inputTypes)},
385 {"TEST_CONDITION", (condition != testConditions.end()) ? condition->second : ""}});
386 }
387
388 const vector<float> positions = {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f};
389
390 const vector<uint32_t> indices = {0, 1, 2, 3};
391
392 const int RENDERTARGET_WIDTH = 16;
393 const int RENDERTARGET_HEIGHT = 16;
394
395 class GLSLVectorConstructorTestCase : public deqp::TestCase
396 {
397 public:
398 GLSLVectorConstructorTestCase(deqp::Context &context, glu::GLSLVersion glslVersion, const TestParams ¶ms);
399
400 void init(void);
401 void deinit(void);
402 IterateResult iterate();
403
404 private:
405 void setupRenderTarget();
406 void releaseRenderTarget();
407
408 const glu::GLSLVersion m_glslVersion;
409 const TestParams m_params;
410 glw::GLuint m_fboId;
411 glw::GLuint m_rboId;
412
413 string m_vertexShader;
414 string m_fragmentShader;
415 };
416
GLSLVectorConstructorTestCase(deqp::Context & context,glu::GLSLVersion glslVersion,const TestParams & params)417 GLSLVectorConstructorTestCase::GLSLVectorConstructorTestCase(deqp::Context &context, glu::GLSLVersion glslVersion,
418 const TestParams ¶ms)
419 : TestCase(context, params.name.c_str(), params.description.c_str())
420 , m_glslVersion(glslVersion)
421 , m_params(params)
422 , m_fboId(0)
423 , m_rboId(0)
424 {
425 switch (m_params.testType)
426 {
427 case TestType::VERTEX_SHADER_ERROR:
428 case TestType::VERTEX_SHADER:
429 m_vertexShader = replacePlaceholders(vertexShaderTemplate, m_params, m_glslVersion);
430 m_fragmentShader = replacePlaceholders(defaultFragmentShader, m_params, m_glslVersion);
431 break;
432 case TestType::FRAGMENT_SHADER_ERROR:
433 case TestType::FRAGMENT_SHADER:
434 m_vertexShader = replacePlaceholders(defaultVertexShader, m_params, m_glslVersion);
435 m_fragmentShader = replacePlaceholders(fragmentShaderTemplate, m_params, m_glslVersion);
436 break;
437 }
438 }
439
init(void)440 void GLSLVectorConstructorTestCase::init(void)
441 {
442 deqp::TestCase::init();
443 }
444
deinit(void)445 void GLSLVectorConstructorTestCase::deinit(void)
446 {
447 deqp::TestCase::deinit();
448 }
449
iterate()450 GLSLVectorConstructorTestCase::IterateResult GLSLVectorConstructorTestCase::iterate()
451 {
452 const auto &renderContext = m_context.getRenderContext();
453 const auto &gl = renderContext.getFunctions();
454 const auto textureFormat = tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
455 const auto transferFormat = glu::getTransferFormat(textureFormat);
456
457 setupRenderTarget();
458
459 glu::ShaderProgram program(renderContext, glu::makeVtxFragSources(m_vertexShader, m_fragmentShader));
460 if (!program.isOk())
461 {
462 switch (m_params.testType)
463 {
464 case TestType::VERTEX_SHADER_ERROR:
465 case TestType::FRAGMENT_SHADER_ERROR:
466 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
467 return STOP;
468 default:
469 TCU_FAIL("Shader compilation failed:\nVertex shader:\n" + m_vertexShader + "\nFragment shader:\n" +
470 m_fragmentShader);
471 }
472 }
473
474 const vector<glu::VertexArrayBinding> vertexArrays = {
475 glu::va::Float("vPosition", 2, (int)positions.size() / 2, 0, positions.data()),
476 };
477
478 gl.useProgram(program.getProgram());
479 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram failed");
480
481 gl.clear(GL_COLOR_BUFFER_BIT);
482
483 glu::draw(renderContext, program.getProgram(), static_cast<int>(vertexArrays.size()), vertexArrays.data(),
484 glu::pr::TriangleStrip(static_cast<int>(indices.size()), indices.data()));
485
486 const auto pixelSize = tcu::getPixelSize(textureFormat);
487 vector<uint8_t> fbData(RENDERTARGET_WIDTH * RENDERTARGET_HEIGHT * pixelSize);
488
489 if (pixelSize < 4)
490 gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
491
492 gl.readPixels(0, 0, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT, transferFormat.format, transferFormat.dataType,
493 fbData.data());
494 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
495
496 tcu::ConstPixelBufferAccess fbAccess{textureFormat, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT, 1, fbData.data()};
497 const auto expectedColor = tcu::RGBA::green().toVec();
498 bool pass = true;
499 for (int y = 0; pass && y < RENDERTARGET_HEIGHT; ++y)
500 for (int x = 0; x < RENDERTARGET_WIDTH; ++x)
501 if (fbAccess.getPixel(x, y) != expectedColor)
502 {
503 pass = false;
504 break;
505 }
506
507 releaseRenderTarget();
508
509 const qpTestResult result = (pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL);
510 const char *desc = (pass ? "Pass" : "Pixel mismatch; vector initialization failed");
511
512 m_testCtx.setTestResult(result, desc);
513
514 return STOP;
515 }
516
setupRenderTarget()517 void GLSLVectorConstructorTestCase::setupRenderTarget()
518 {
519 const auto &renderContext = m_context.getRenderContext();
520 const auto &gl = renderContext.getFunctions();
521
522 gl.genFramebuffers(1, &m_fboId);
523 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
524
525 gl.genRenderbuffers(1, &m_rboId);
526 GLU_EXPECT_NO_ERROR(gl.getError(), "GenRenderBuffers");
527
528 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rboId);
529 GLU_EXPECT_NO_ERROR(gl.getError(), "BindRenderBuffer");
530
531 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT);
532 GLU_EXPECT_NO_ERROR(gl.getError(), "RenderBufferStorage");
533
534 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboId);
535 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFrameBuffer");
536
537 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rboId);
538 GLU_EXPECT_NO_ERROR(gl.getError(), "FrameBufferRenderBuffer");
539
540 glw::GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
541 gl.drawBuffers(1, &drawBuffer);
542 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawBuffers");
543
544 glw::GLfloat clearColor[4] = {0, 0, 0, 0};
545 gl.clearBufferfv(GL_COLOR, 0, clearColor);
546 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearBuffers");
547
548 gl.viewport(0, 0, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT);
549 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
550 }
551
releaseRenderTarget()552 void GLSLVectorConstructorTestCase::releaseRenderTarget()
553 {
554 const auto &renderContext = m_context.getRenderContext();
555 const auto &gl = renderContext.getFunctions();
556 if (m_fboId != 0)
557 {
558 gl.deleteFramebuffers(1, &m_fboId);
559 m_fboId = 0;
560 }
561 if (m_rboId != 0)
562 {
563 gl.deleteRenderbuffers(1, &m_rboId);
564 m_rboId = 0;
565 }
566 }
567
568 } // namespace
569
GLSLVectorConstructorTests(Context & context,glu::GLSLVersion glslVersion)570 GLSLVectorConstructorTests::GLSLVectorConstructorTests(Context &context, glu::GLSLVersion glslVersion)
571 : deqp::TestCaseGroup(context, "glsl_constructors", "GLSL vector constructor tests")
572 , m_glslVersion(glslVersion)
573 {
574 }
575
~GLSLVectorConstructorTests()576 GLSLVectorConstructorTests::~GLSLVectorConstructorTests()
577 {
578 }
579
init()580 void GLSLVectorConstructorTests::init()
581 {
582 for (const auto ¶ms : generateTestParams())
583 addChild(new GLSLVectorConstructorTestCase(m_context, m_glslVersion, params));
584 }
585
586 } // namespace deqp
587