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 46namespace deqp 47{ 48 49namespace 50{ 51using std::string; 52 53using std::map; 54using std::vector; 55 56using std::function; 57using std::bind; 58using namespace std::placeholders; 59 60using std::ostringstream; 61 62enum struct TestType 63{ 64 VERTEX_SHADER_ERROR = 0, 65 FRAGMENT_SHADER_ERROR, 66 VERTEX_SHADER, 67 FRAGMENT_SHADER 68}; 69 70struct TestDefinition 71{ 72 vector<string> outputTypes; 73 vector<vector<string>> inputTypeLists; 74 string extraFields; 75}; 76 77const TestDefinition tests[] = 78{ 79 { 80 { "vec2", "vec3", "vec4" }, // vector<string> outputTypes 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" // deUint32 extraFields; 102 }, 103 { 104 { "ivec2", "ivec3", "ivec4" }, // vector<string> outputTypes 105 { // vector<vector<string>> inputTypeLists 106 { "mat2" }, 107 { "mat2x3" }, 108 { "mat2x4" }, 109 { "mat3" }, 110 { "mat3x2" }, 111 { "mat3x4" }, 112 { "mat4" }, 113 { "mat4x2" }, 114 { "mat4x3" }, 115 { "int", "mat2" }, 116 { "int", "mat2x3" }, 117 { "int", "mat2x4" }, 118 { "int", "mat3" }, 119 { "int", "mat3x2" }, 120 { "int", "mat3x4" }, 121 { "int", "mat4" }, 122 { "int", "mat4x2" }, 123 { "int", "mat4x3" }, 124 }, 125 "" // deUint32 extraFields; 126 }, 127 { 128 { "bvec2", "bvec3", "bvec4" }, // vector<string> outputTypes 129 { // vector<vector<string>> inputTypeLists 130 { "mat2" }, 131 { "mat2x3" }, 132 { "mat2x4" }, 133 { "mat3" }, 134 { "mat3x2" }, 135 { "mat3x4" }, 136 { "mat4" }, 137 { "mat4x2" }, 138 { "mat4x3" }, 139 { "bool", "mat2" }, 140 { "bool", "mat2x3" }, 141 { "bool", "mat2x4" }, 142 { "bool", "mat3" }, 143 { "bool", "mat3x2" }, 144 { "bool", "mat3x4" }, 145 { "bool", "mat4" }, 146 { "bool", "mat4x2" }, 147 { "bool", "mat4x3" }, 148 }, 149 "" // deUint32 extraFields; 150 }, 151}; 152 153struct TestParams 154{ 155 string name; 156 string description; 157 TestType testType; 158 string outputType; 159 vector<string> inputTypes; 160 string extraFields; 161}; 162 163vector<TestParams> generateTestParams() 164{ 165 vector<TestParams> result; 166 result.reserve(64); 167 for(const auto& test : tests) 168 { 169 for(const auto& outputType : test.outputTypes) 170 { 171 for(const auto& inputTypes : test.inputTypeLists) 172 { 173 ostringstream testNameVs, testNameFs; 174 ostringstream testDescriptionVs, testDescriptionFs; 175 testNameVs << outputType << "_from"; 176 testNameFs << outputType << "_from"; 177 testDescriptionVs << outputType << "("; 178 testDescriptionFs << outputType << "("; 179 for(vector<string>::size_type i = 0; i < inputTypes.size(); ++i) 180 { 181 const auto& inputType = inputTypes[i]; 182 testNameVs << "_" << inputType; 183 testNameFs << "_" << inputType; 184 if (i > 0) { 185 testDescriptionVs << ","; 186 testDescriptionFs << ","; 187 } 188 testDescriptionVs << inputType; 189 } 190 ostringstream testNameInvalidVs, testNameInvalidFs; 191 testNameInvalidVs << testNameVs.str() << "_" << inputTypes[0] << "_invalid_vs"; 192 testNameInvalidFs << testNameFs.str() << "_" << inputTypes[0] << "_invalid_fs"; 193 194 testNameVs << "_vs"; 195 testNameFs << "_fs"; 196 testDescriptionVs << ") vertex shader"; 197 testDescriptionFs << ") fragment shader"; 198 result.push_back({ testNameVs.str(), testDescriptionVs.str(), TestType::VERTEX_SHADER, outputType, inputTypes, test.extraFields }); 199 result.push_back({ testNameFs.str(), testDescriptionFs.str(), TestType::FRAGMENT_SHADER, outputType, inputTypes, test.extraFields }); 200 201 vector<string> failInputTypes; 202 failInputTypes.insert(failInputTypes.end(), inputTypes.begin(), inputTypes.end()); 203 failInputTypes.push_back(inputTypes[0]); 204 testDescriptionVs << " invalid"; 205 testDescriptionFs << " invalid"; 206 result.push_back({ testNameInvalidVs.str(), testDescriptionVs.str(), TestType::VERTEX_SHADER_ERROR, outputType, failInputTypes, test.extraFields }); 207 result.push_back({ testNameInvalidFs.str(), testDescriptionFs.str(), TestType::FRAGMENT_SHADER_ERROR, outputType, failInputTypes, test.extraFields }); 208 209 } 210 } 211 } 212 return result; 213} 214 215const string defaultVertexShader = 216 "${GLSL_VERSION}\n" 217 "in vec4 vPosition;\n" 218 "void main()\n" 219 "{\n" 220 " gl_Position = vPosition;\n" 221 "}\n"; 222 223const string defaultFragmentShader = 224 "${GLSL_VERSION}\n" 225 "precision mediump float;\n" 226 "in vec4 vColor;\n" 227 "out vec4 my_FragColor;\n" 228 "void main() {\n" 229 " my_FragColor = vColor;\n" 230 "}\n"; 231 232const string vertexShaderTemplate = 233 "${GLSL_VERSION}\n" 234 "in vec4 vPosition;\n" 235 "precision mediump int;\n" 236 "precision mediump float;\n" 237 "const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" 238 "const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" 239 "${TEST_CONSTANTS}" 240 "out vec4 vColor;\n" 241 "void main() {\n" 242 " ${TEST_CODE}\n" 243 " if ${TEST_CONDITION}\n" 244 " vColor = green;\n" 245 " else\n" 246 " vColor = red;\n" 247 " gl_Position = vPosition;\n" 248 "}\n"; 249 250const string fragmentShaderTemplate = 251 "${GLSL_VERSION}\n" 252 "precision mediump int;\n" 253 "precision mediump float;\n" 254 "const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" 255 "const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" 256 "${TEST_CONSTANTS}" 257 "out vec4 my_FragColor;\n" 258 "void main() {\n" 259 " ${TEST_CODE}\n" 260 " if ${TEST_CONDITION}\n" 261 " my_FragColor = green;\n" 262 " else\n" 263 " my_FragColor = red;\n" 264 "}\n"; 265 266const map<string, string> testConditions = 267{ 268 { "vec2" , "(abs(v[0] - 0.0) <= errorBound && abs(v[1] - 1.0) <= errorBound)" }, 269 { "vec3" , "(abs(v[0] - 0.0) <= errorBound && abs(v[1] - 1.0) <= errorBound && abs(v[2] - 2.0) <= errorBound)" }, 270 { "vec4" , "(abs(v[0] - 0.0) <= errorBound && abs(v[1] - 1.0) <= errorBound && abs(v[2] - 2.0) <= errorBound && abs(v[3] - 3.0) <= errorBound)" }, 271 { "ivec2" , "(v[0] == 0 && v[1] == 1)" }, 272 { "ivec3" , "(v[0] == 0 && v[1] == 1 && v[2] == 2)" }, 273 { "ivec4" , "(v[0] == 0 && v[1] == 1 && v[2] == 2 && v[3] == 3)" }, 274 { "bvec2" , "(v[0] == false && v[1] == true)" }, 275 { "bvec3" , "(v[0] == false && v[1] == true && v[2] == true)" }, 276 { "bvec4" , "(v[0] == false && v[1] == true && v[2] == true && v[3] == true)" } 277}; 278 279typedef function<void (ostringstream&, size_t)> GeneratorFn; 280 281struct DataTypeInfo 282{ 283 size_t numElements; 284 GeneratorFn valueFn; 285 GeneratorFn beforeValueFn; 286 GeneratorFn afterValueFn; 287}; 288 289void generateValueFloat(ostringstream& out, const size_t index) 290{ 291 out << index << ".0"; 292} 293 294void generateValueInt(ostringstream& out, const size_t index) 295{ 296 out << index; 297} 298 299void generateValueBool(ostringstream& out, const size_t index) 300{ 301 out << ((index != 0) ? "true" : "false"); 302} 303 304void generateCtorOpen(const char* className, ostringstream& out, const size_t) 305{ 306 out << className << "("; 307} 308 309void generateCtorClose(ostringstream &out, const size_t) 310{ 311 out << ")"; 312} 313 314const map<string, DataTypeInfo> dataTypeInfos = 315{ 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 340string 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 = 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 378string replacePlaceholders(const string& shaderTemplate, const TestParams& params, const glu::GLSLVersion glslVersion) 379{ 380 const auto condition = testConditions.find(params.outputType); 381 return tcu::StringTemplate(shaderTemplate).specialize( 382 { 383 { "GLSL_VERSION" , glu::getGLSLVersionDeclaration(glslVersion) }, 384 { "TEST_CONSTANTS" , params.extraFields }, 385 { "TEST_CODE" , generateTestCode(params.outputType, params.inputTypes) }, 386 { "TEST_CONDITION" , (condition != testConditions.end()) ? condition->second : "" } 387 }); 388} 389 390const vector<float> positions = 391{ 392 -1.0f, -1.0f, 393 1.0f, -1.0f, 394 -1.0f, 1.0f, 395 1.0f, 1.0f 396}; 397 398const vector<deUint32> indices = { 0, 1, 2, 3 }; 399 400const int RENDERTARGET_WIDTH = 16; 401const int RENDERTARGET_HEIGHT = 16; 402 403class GLSLVectorConstructorTestCase : public deqp::TestCase 404{ 405public: 406 GLSLVectorConstructorTestCase(deqp::Context& context, glu::GLSLVersion glslVersion, const TestParams& params); 407 408 void init(void); 409 void deinit(void); 410 IterateResult iterate(); 411 412private: 413 void setupRenderTarget(); 414 void releaseRenderTarget(); 415 416 const glu::GLSLVersion m_glslVersion; 417 const TestParams m_params; 418 glw::GLuint m_fboId; 419 glw::GLuint m_rboId; 420 421 string m_vertexShader; 422 string m_fragmentShader; 423}; 424 425GLSLVectorConstructorTestCase::GLSLVectorConstructorTestCase(deqp::Context& context, glu::GLSLVersion glslVersion, const TestParams& params) 426 : TestCase(context, params.name.c_str(), params.description.c_str()) 427 , m_glslVersion(glslVersion) 428 , m_params(params) 429 , m_fboId(0) 430 , m_rboId(0) 431{ 432 switch(m_params.testType) 433 { 434 case TestType::VERTEX_SHADER_ERROR: 435 case TestType::VERTEX_SHADER: 436 m_vertexShader = replacePlaceholders(vertexShaderTemplate, m_params, m_glslVersion); 437 m_fragmentShader = replacePlaceholders(defaultFragmentShader, m_params, m_glslVersion); 438 break; 439 case TestType::FRAGMENT_SHADER_ERROR: 440 case TestType::FRAGMENT_SHADER: 441 m_vertexShader = replacePlaceholders(defaultVertexShader, m_params, m_glslVersion); 442 m_fragmentShader = replacePlaceholders(fragmentShaderTemplate, m_params, m_glslVersion); 443 break; 444 } 445} 446 447void GLSLVectorConstructorTestCase::init(void) 448{ 449 deqp::TestCase::init(); 450} 451 452void GLSLVectorConstructorTestCase::deinit(void) 453{ 454 deqp::TestCase::deinit(); 455} 456 457GLSLVectorConstructorTestCase::IterateResult GLSLVectorConstructorTestCase::iterate() 458{ 459 const auto& renderContext = m_context.getRenderContext(); 460 const auto& gl = renderContext.getFunctions(); 461 const auto textureFormat = tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8); 462 const auto transferFormat = glu::getTransferFormat(textureFormat); 463 464 setupRenderTarget(); 465 466 glu::ShaderProgram program(renderContext, glu::makeVtxFragSources(m_vertexShader, m_fragmentShader)); 467 if (!program.isOk()) 468 { 469 switch(m_params.testType) 470 { 471 case TestType::VERTEX_SHADER_ERROR: 472 case TestType::FRAGMENT_SHADER_ERROR: 473 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 474 return STOP; 475 default: 476 TCU_FAIL("Shader compilation failed:\nVertex shader:\n" + m_vertexShader + "\nFragment shader:\n" + m_fragmentShader); 477 } 478 } 479 480 const vector<glu::VertexArrayBinding> vertexArrays = 481 { 482 glu::va::Float("vPosition", 2, positions.size() / 2, 0, positions.data()), 483 }; 484 485 gl.useProgram(program.getProgram()); 486 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram failed"); 487 488 gl.clear(GL_COLOR_BUFFER_BIT); 489 490 glu::draw(renderContext, program.getProgram(), 491 static_cast<int>(vertexArrays.size()), vertexArrays.data(), 492 glu::pr::TriangleStrip(static_cast<int>(indices.size()), indices.data())); 493 494 const auto pixelSize = tcu::getPixelSize(textureFormat); 495 vector<deUint8> fbData (RENDERTARGET_WIDTH * RENDERTARGET_HEIGHT * pixelSize); 496 497 if (pixelSize < 4) 498 gl.pixelStorei(GL_PACK_ALIGNMENT, 1); 499 500 gl.readPixels(0, 0, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT, transferFormat.format, transferFormat.dataType, fbData.data()); 501 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels"); 502 503 tcu::ConstPixelBufferAccess fbAccess { textureFormat, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT, 1, fbData.data() }; 504 const auto expectedColor = tcu::RGBA::green().toVec(); 505 bool pass = true; 506 for(int y = 0; pass && y < RENDERTARGET_HEIGHT; ++y) 507 for(int x = 0; x < RENDERTARGET_WIDTH; ++x) 508 if (fbAccess.getPixel(x,y) != expectedColor) 509 { 510 pass = false; 511 break; 512 } 513 514 releaseRenderTarget(); 515 516 const qpTestResult result = (pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL); 517 const char* desc = (pass ? "Pass" : "Pixel mismatch; vector initialization failed"); 518 519 m_testCtx.setTestResult(result, desc); 520 521 return STOP; 522} 523 524void GLSLVectorConstructorTestCase::setupRenderTarget() 525{ 526 const auto& renderContext = m_context.getRenderContext(); 527 const auto& gl = renderContext.getFunctions(); 528 529 gl.genFramebuffers(1, &m_fboId); 530 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers"); 531 532 gl.genRenderbuffers(1, &m_rboId); 533 GLU_EXPECT_NO_ERROR(gl.getError(), "GenRenderBuffers"); 534 535 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rboId); 536 GLU_EXPECT_NO_ERROR(gl.getError(), "BindRenderBuffer"); 537 538 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT); 539 GLU_EXPECT_NO_ERROR(gl.getError(), "RenderBufferStorage"); 540 541 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboId); 542 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFrameBuffer"); 543 544 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rboId); 545 GLU_EXPECT_NO_ERROR(gl.getError(), "FrameBufferRenderBuffer"); 546 547 glw::GLenum drawBuffer = GL_COLOR_ATTACHMENT0; 548 gl.drawBuffers(1, &drawBuffer); 549 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawBuffers"); 550 551 glw::GLfloat clearColor[4] = { 0, 0, 0, 0 }; 552 gl.clearBufferfv(GL_COLOR, 0, clearColor); 553 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearBuffers"); 554 555 gl.viewport(0, 0, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT); 556 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport"); 557} 558 559void GLSLVectorConstructorTestCase::releaseRenderTarget() 560{ 561 const auto& renderContext = m_context.getRenderContext(); 562 const auto& gl = renderContext.getFunctions(); 563 if (m_fboId != 0) 564 { 565 gl.deleteFramebuffers(1, &m_fboId); 566 m_fboId = 0; 567 } 568 if (m_rboId != 0) 569 { 570 gl.deleteRenderbuffers(1, &m_rboId); 571 m_rboId = 0; 572 } 573} 574 575} 576 577GLSLVectorConstructorTests::GLSLVectorConstructorTests(Context& context, glu::GLSLVersion glslVersion) 578 : deqp::TestCaseGroup(context, "glsl_constructors", "GLSL vector constructor tests") 579 , m_glslVersion(glslVersion) 580{ 581} 582 583GLSLVectorConstructorTests::~GLSLVectorConstructorTests() 584{ 585} 586 587void GLSLVectorConstructorTests::init() 588{ 589 for(const auto& params : generateTestParams()) 590 addChild(new GLSLVectorConstructorTestCase(m_context, m_glslVersion, params)); 591} 592 593} // deqp 594